[鹤城杯 2021]Middle magic

发布时间 2023-09-13 20:21:29作者: y0Zero

[鹤城杯 2021]Middle magic

题目来源:nssctf

题目类型:web

涉及考点:弱比较

1. 直接代码审计

<?php
highlight_file(__FILE__);
include "./flag.php";
include "./result.php";
if(isset($_GET['aaa']) && strlen($_GET['aaa']) < 20){

    $aaa = preg_replace('/^(.*)level(.*)$/', '${1}<!-- filtered -->${2}', $_GET['aaa']);

    if(preg_match('/pass_the_level_1#/', $aaa)){
        echo "here is level 2";
        
        if (isset($_POST['admin']) and isset($_POST['root_pwd'])) {
            if ($_POST['admin'] == $_POST['root_pwd'])
                echo '<p>The level 2 can not pass!</p>';
        // START FORM PROCESSING    
            else if (sha1($_POST['admin']) === sha1($_POST['root_pwd'])){
                echo "here is level 3,do you kown how to overcome it?";
                if (isset($_POST['level_3'])) {
                    $level_3 = json_decode($_POST['level_3']);
                    
                    if ($level_3->result == $result) {
                        
                        echo "success:".$flag;
                    }
                    else {
                        echo "you never beat me!";
                    }
                }
                else{
                    echo "out";
                }
            }
            else{
                
                die("no");
            }
        // perform validations on the form data
        }
        else{
            echo '<p>out!</p>';
        }

    }
    
    else{
        echo 'nonono!';
    }

    echo '<hr>';
}

?>

一共三层if,我们逐层看看:

  • 第一个if要求aaa=pass_the_level_1#,但会将传入的level替换为filtered
  • 第二个if要求传入两个不相等变量adminroot_pwd,但要求两者sha1加密后相等;
  • 第三个if要求传入level_3,对其进行json_decode后,需要$level_3->result == $result

这里介绍一下json_decode()

json_decode ( string $json [, bool $assoc = false [, int $depth = 512 , int $options = 0]]] )

json_decode接受一个JSON格式的字符串并且把它转换为PHP变量,当该参数assoc为TRUE时,将返回array,否则返回object。

2. 构造payload

  • 第一个if,因为preg_replace函数只能匹配一行的数据,因此我们只需先传入换行符,那么后面的传入便不再被匹配:
/?aaa=%0apass_the_level_1%23

%0a和%23分别是换行符和井号键的url编码

  • 第二个if,我们利用数组绕过,具体原因是sha1加密时,若传入的是数组,返回值为null:
admin[]=1&root_pwd[]=2
  • 第三个if,我们传入一个JSON格式的字符串,即:
level_3={"result":0}

php弱比较在面对纯字符与0的比较时,会返回true,例如a == 0返回为true
此处推测$result是纯字符,因此构造result->0

  • 将上述传入后得到flag:
NSSCTF{5878248c-1602-4372-872e-842c0306eb9b}

日期:2023.9.13

作者:y0Zero