4

I have been trying to unserialize PHP session data in Python by using phpserialize and a serek's modules(got it from Unserialize PHP data in python), but it seems like impossible to me.

Both modules expect PHP session data to be like:

a:2:{s:3:"Usr";s:5:"AxL11";s:2:"Id";s:1:"2";}

But the data stored in the session file is:

Id|s:1:"2";Usr|s:5:"AxL11";

Any help would be very much appreciated.

Community
  • 1
  • 1
Axel
  • 457
  • 9
  • 20
  • With **phpserialize** I have tried to do the following: `>>> loads('a:2:{s:3:"Usr";s:5:"AxL11";s:2:"Id";s:1:"2";}')` `{'Usr': 'AxL11', 'Id': '2'}` This works, as you can see, but with my REAL PHP session data stored in a file: `>>> loads('Id|s:1:"2";Usr|s:5:"AxL11";')` I get a ValueError at phpserialize.py", line 444, in _expect – Axel Sep 29 '13 at 15:53
  • In my php.ini file I have the following: session.serialize_handler = php More info at [link](http://www.php.net/manual/en/session.configuration.php#ini.session.serialize-handler) – Axel Sep 29 '13 at 16:02
  • After reaching page 3 on Google, I found a [fork](https://github.com/nathanwalsh/phpserialize) of the original [phpserialize](https://github.com/mitsuhiko/phpserialize) that worked with the string that I privided: `>>> loads('Id|s:1:"2";Usr|s:5:"AxL11";')` `{'Id': '2', 'Usr': 'AxL11'}` – Axel Sep 29 '13 at 16:15

3 Answers3

2

After reaching page 3 on Google, I found a fork of the original application phpserialize that worked with the string that I provided:

>>> loads('Id|s:1:"2";Usr|s:5:"AxL11";')
{'Id': '2', 'Usr': 'AxL11'}
Axel
  • 457
  • 9
  • 20
2

The default algorithm used for PHP session serialization is not the one used by serialize, but another internal broken format called php, which

cannot store numeric index nor string index contains special characters (| and !) in $_SESSION.


The correct solution is to change the crippled default session serialization format to the one supported by Armin Ronacher's original phpserialize library, or even to serialize and deserialize as JSON, by changing the session.serialize_handler INI setting.

I decided to use the former for maximal compatibility on the PHP side by using

ini_set('session.serialize_handler', 'php_serialize')

which makes the new sessions compatible with standard phpserialize.

0

This is how I do it in a stupid way:

At first, convert Id|s:1:"2";Usr|s:5:"AxL11"; to a query string Id=2&Usr=AxL11& then use parse_qs:

import sys
import re

if sys.version_info >= (3, 0):
    from urllib.parse import parse_qs, quote
else:
    from urlparse import parse_qs
    from urllib import quote

def parse_php_session(path):
    with open(path, 'r') as sess:
        return parse_qs(
           re.sub(r'\|s:([0-9]+):"?(.*?)(?=[^;|]+\|s:[0-9]+:|$)',
                lambda m : '=' + quote(m.group(2)[:int(m.group(1))]) + '&',
                sess.read().rstrip().rstrip(';') + ';')
        )

print(parse_php_session('/session-save-path/sess_0123456789abcdef'))
# {'Id': ['2'], 'Usr': ['AxL11']}

It used to work without replacing ; to & (both are allowed). But since Python 3.10 the default separator for parse_qs is &

nggit
  • 611
  • 8
  • 8