浅析php反序列化漏洞

Posted by grt1stnull on 2017-04-04

反序列化在很多语言中都比较常见,下面简单介绍php的反序列化漏洞(对象注入)。

原文发表在了freebuf:
由HITCON 2016一道web聊一聊php反序列化漏洞
,但是最近看了一下,写的太烂了,所以重新写了一下。

0x00.是什么——what

php反序列化漏洞,又叫对象注入。

涉及到的是php中的两个函数:unsearialize()与serialize()。后者为将一个对象或者数组转换为字符串以便保存,前者则将尝试将字符串恢复为对象或者数组。

关于这个漏洞大家平时可能很少见,它的触发点主要是在代码审计中cms的session序列化与反序列化和ctf中相关反序列化字符串的构建。

执行方式是通过自动执行的魔术方法构造pop链,然后执行危险函数造成漏洞的产生。

0x01.为什么——why

总结了一下整个流程:

1
unserialize()函数的参数可控 => 实例化类 => 魔术方法自动调用 => 危险函数执行

1.魔术方法

魔术方法,magic method。魔术方法有各自的属性,类、对象进行各种操作时会自动调用。

常见的魔术方法如下:

魔术方法 属性
__construct() 构造函数,实例化对类时自动调用
__destruct() 析构函数,销毁对象时自动调用
__sleep() 序列化对象时自动调用
__wakeup() 反序列化对象时自动调用
__toString() echo输出对象时自动调用

2.构造payload

定义一个测试类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class foo{
function __construct($str, $function)
{
$this->str = $str;
$this->function = $function;
}
function __wakeup()
{
echo "[+]$this->function is :$this->str<br>";
}
}
if (isset($_GET['str'])){
@unserialize($_GET['str']);
}
else{
highlight_file(__FILE__);
}
?>

构造payload方法1:

1
2
3
4
<?php
$a = new foo('strings', 'show');
print_r(@serialize($a));
?>

构造payload方法2(推荐):

1
2
3
4
5
6
7
8
9
10
11
<?php
class foo{
function __construct()
{
$this->str = 'strings';
$this->function = 'show';
}
}
$a = new foo();
print_r(@serialize($a))
?>

3.口算payload

示例:

1
2
3
4
5
6
7
O:3:"foo":2:{s:3:"str";s:7:"strings";s:8:"function";s:4:"show";}
O:表示为对象objecta表示数组
3:对象、数组名长度
2:变量数目
Sstring类型
3:长度

0x02.怎么做——how

1.一些值得看一看的例子

cms漏洞:

1
2
3
SugarCRM v6.5.23 PHP反序列化 对象注入漏洞
wecenter反序列化造成任意SQL语句执行
vBulletin 5.x.x 远程任意代码执行漏洞

ctf题目:

1
2
3
hitcon2016 babytrick
0ctf2016 piapiapia
三个白帽挑战赛第三期

2.CVE-2016-7124

序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行

例子:

1
2
SugarCRM v6.5.23 PHP反序列化
hitcon2016 babytrick

3.Session反序列化

session.serialize_handler(php反序列化处理器):

1
2
3
php_binary:存储方式是,键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值
php:存储方式是,键名+竖线+经过serialize()函数序列处理的值
php_serialize(php>5.5.4):存储方式是,经过serialize()函数序列化处理的值

使用方法:

1
2
init_set('session.serialize_handle', 'php_serialize');
session_start();

关于这部分,有如下参考:

1
2
参考:PHP Session 序列化及反序列化处理器设置使用不当带来的安全隐患(wooyun drops)
例子:安恒杯web3Joomla远程代码执行漏洞

整个流程为:

1
反序列化与序列化处理器不同 => 使用php_serialize处理器序列化,值中含有| => 使用php处理器反序列化,格式为”键名|serialize()处理后的值” => |前解析为键名,|后进行反序列化

0x03.其他

自己做了个ppt,下载地址:https://cdn.grt1st.cn/php_unse.pptx