Pikachu靶场之PHP反序列漏洞详解

Pikachu靶场之PHP反序列漏洞详解

  • 前言
  • PHP反序列漏洞简述
  • 正式闯关
  • 代码审计

前言

本篇文章用于巩固对自己PHP反序列漏洞的学习总结,其中部分内容借鉴了以下博客。
链接: pikachu PHP反序列化(皮卡丘漏洞平台通关系列))

PHP反序列漏洞简述

在理解这个漏洞前,你需要先搞清楚php中serialize(),unserialize()这两个函数。

先跟着pikachu简单学习一下什么叫序列化和反序列化:
但其实我已知这里有3个地方写的不对,需要更正一下:

(1)序列化结果中的S不是对象名称,而是类名称;同样的,O和S中间的1应该是类名字长度。

(2)几个魔法函数的举例有点让人误会,很容易误以为这些魔法函数都会造成反序列化漏洞,但其实__construct()在unserialize()时并不会被自动调用,这点在之后会进行演示。

(3)__wakeup()不是下图中写的那个作用,而是执行unserialize()时,先会调用这个函数,然后再进行反序列化

Pikachu靶场之PHP反序列漏洞详解_第1张图片
Pikachu靶场之PHP反序列漏洞详解_第2张图片
总之,序列化是把对象转换为字符串,从而达到传输和存储的目的;反序列化是把字符串还原为对象,以便被代码处理。

这里说的字符串不是普通字符串,是有固定格式的。

此外,根据《PHP和MySQL Web开发》一书,PHP在重新实例化类之前,需要了解类结构,因此在调用session_start()或unserialized()之前,需要引入类定义文件。

综上,要想利用反序列化漏洞,至少要知道两点:

(1)类名称

(2)类包含的变量名称

所以通常需要代码审计查找反序列化漏洞

正式闯关

观察页面,就下图这个输入框,什么提示也没有,显然不符合知道类名称和知道类中变量名两个条件

那么,要么就需要代码审计,要么估计这关的类和pikachu的解说中的类是一样的。

Pikachu靶场之PHP反序列漏洞详解_第3张图片
那先用解说中的payload:(O:1:"S":1:{s:4:"test";s:29:"";})试一下,果然可以:
Pikachu靶场之PHP反序列漏洞详解_第4张图片
接下来可以手动根据格式修改payload,也可以用代码构造payload

(1)手动修改payload

比如想要弹框显示cookie,那xss payload是:

其长度是39字节。因此,反序列化payload为:O:1:"S":1:{s:4:"test";s:39:"";}

尝试一下,可以的:
Pikachu靶场之PHP反序列漏洞详解_第5张图片
(2)用代码构造payload

创建以下内容的文件,放在www目录下(当然如果直接把xss payload写到类定义里面也可以)
Pikachu靶场之PHP反序列漏洞详解_第6张图片
代码如下

alert(document.cookie)";
	$s->test=$payload;
	echo serialize($s);
?>

浏览器访问这个文件,就可以得到反序列化的payload

Pikachu靶场之PHP反序列漏洞详解_第7张图片

代码审计

究竟是哪行代码造成了这个反序列化漏洞呢?

先看一下源代码:

反正问题肯定就在下面这段了

狼人看着反正要么就是20~22行的__construct(),要么就是33行的$html.="

{$unser->test}

";(完整源代码最后有echo $html)

就这两个地方涉及到向网页输出
Pikachu靶场之PHP反序列漏洞详解_第8张图片
那就用排除法尝试吧,先把33行注释掉

Pikachu靶场之PHP反序列漏洞详解_第9张图片
输入payload:(O:1:"S":1:{s:4:"test";s:29:"";})之后没有弹框,说明这不是__construct()的锅,到此已经可以判断是第33行起的作用了,保险起见还是再试一下。

这次把33行放出来,把__construct()注释掉:
Pikachu靶场之PHP反序列漏洞详解_第10张图片
输入payload:(O:1:"S":1:{s:4:"test";s:29:"";})之后弹框了,果不其然,抓住狼人,就是第33行。
那么疑惑就来了,为啥__construct()没起作用呢?

网上搜索了一下,很多讲解反序列化的文章都说了,__construct()这个函数虽然在对象创建时会被调用,但反序列化(unserialize())的时候并不会被调用。

所以。。尽信书不如无书,还是要多看,多想,多操作。。。
Pikachu靶场之PHP反序列漏洞详解_第11张图片

最后测试一下__destruct()函数被读取的情况。
把代码中的__construct()改成__desstruct(),并把之前的狼人($html.="

{$unser->test}

";)注释掉:

Pikachu靶场之PHP反序列漏洞详解_第12张图片
输入payload:(O:1:"S":1:{s:4:"test";s:29:"";})成功弹窗
Pikachu靶场之PHP反序列漏洞详解_第13张图片

你可能感兴趣的:(网络安全,pikachu,php,web安全,安全)