BUUCTF—[MRCTF2020]Ez_bypass1

题目链接:BUUCTF在线评测

一、知识点

        1.PHP代码审计

        2.MD5碰撞(强碰撞,"===")

        3.PHP类型比较

二、解题过程

1.代码审计,打开题目链接后页面显示如下

涉及的函数功能:

$ 符号是PHP语言中用来表示变量的标识符
整形变量:
$age = 25;
字符串变量:
$name = "John";


⚪include('flag.php'):
执行结果:包含并运行指定的外部文件 'flag.php'。
返回值:无。如果文件不存在或者包含失败,它会产生一个警告,但不会终止脚本执行。

⚪isset($variable):
执行结果:检查变量是否已设置并且非NULL。如果变量已设置且非NULL,返回true,否则返回false。

⚪md5($string):
执行结果:计算输入字符串的MD5散列值,返回一个32字符的十六进制散列字符串。
返回值: 字符串,表示MD5散列值。

⚪$_GET['parameter']:
执行结果:从GET请求中获取指定参数的值,通过URL传递的参数(在URL中使用问号后面的参数)。
返回值:如果参数不存在,返回null。

⚪$_POST['parameter']:
执行结果:用于获取通过HTTP POST方法传递的参数(通常在表单提交时使用)。
返回值:如果参数不存在,返回null。

⚪is_numeric($variable):
执行结果:检查变量是否是数字或者数字字符串。
返回值:如果变量是数字或数字字符串,返回true;否则返回false。

⚪echo($string):
执行结果:输出一个或多个字符串。
返回值:无。

⚪die($message):
执行结果:输出指定的消息并退出当前脚本的执行。
返回值:无。die 函数终止脚本的执行,不返回任何值。

解析页面代码

// 包含外部文件 'flag.php',该文件可能包含敏感信息
include 'flag.php';
// 定义一个变量 $flag,包含一个字符串
$flag = 'MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';

// 检查是否存在名为 'gg' 和 'id' 的 GET 参数
if(isset($_GET['gg']) && isset($_GET['id'])) {
    // 获取 GET 参数 'id' 和 'gg' 的值
    $id = $_GET['id'];
    $gg = $_GET['gg'];

    // 检查 $id 和 $gg 的 MD5 散列值是否相等,并且它们的值不相等,强比较
    if (md5($id) === md5($gg) && $id !== $gg) {
        // 输出 'You got the first step'
        echo 'You got the first step';

        // 检查是否存在名为 'passwd' 的 POST 参数
        if(isset($_POST['passwd'])) {
            // 获取 POST 参数 'passwd' 的值
            $passwd = $_POST['passwd'];

            // 检查 $passwd 是否为数字
            if (!is_numeric($passwd)) {
                // 如果 $passwd 等于 1234567,则输出 'Good Job!',显示 'flag.php' 的内容,然后终止脚本执行
                if($passwd == 1234567) {
                    echo 'Good Job!';
                    highlight_file('flag.php');
                    die('By Retr_0');
                } else {
                    // 如果 $passwd 不等于 1234567,则输出 'can you think twice??'
                    echo "can you think twice??";
                }
            } else {
                // 如果 $passwd 是数字,则输出 'You can not get it !'
                echo 'You can not get it !';
            }
        } else {
            // 如果不存在 POST 参数 'passwd',则输出 'only one way to get the flag'
            die('only one way to get the flag');
        }
    } else {
        // 如果 $id 和 $gg 的 MD5 散列值不相等,或者它们的值相等,则输出 'You are not a real hacker!'
        echo "You are not a real hacker!";
    }
} else {
    // 如果不存在 'gg' 和 'id' 的 GET 参数,则输出 'Please input first'
    die('Please input first');
}

注意点:

        "==="与"==":在PHP中,===== 是用于比较两个值是否相等的运算符,它们之间的主要区别在于比较的严格程度:

        ⚪===(严格相等运算符),=== 用于比较两个值的数值和数据类型是否完全相等。只有当两个值的数值和数据类型都相等时,=== 才会返回 true

$a = 5; // 整数
$b = '5'; // 字符串

var_dump($a === $b); // 输出 false,因为整数和字符串的数据类型不同

  ⚪==(相等运算符)== 用于比较两个值的数值是否相等。它在比较时会进行类型转换,将操作数转换为相同的类型,然后再进行比较。如果转换后的数值相等,== 就会返回 true

$a = 5; // 整数
$b = '5'; // 字符串

var_dump($a == $b); // 输出 true,因为在进行类型转换后,整数5等于字符串'5'

        "!=="与"!=":!==!= 是用于比较两个值是否不相等的运算符

        ⚪!==(不全等运算符):这是严格不相等运算符,它不仅会比较两个值的数值是否相等,还会比较它们的数据类型是否相等。只有在数值和数据类型都不相等的情况下,!== 才会返回 true

$a = 5; // 整数
$b = '5'; // 字符串

var_dump($a !== $b); // 输出 true,因为整数和字符串不全等

  ⚪!=(不等运算符):这是非严格不相等运算符,它只会比较两个值的数值是否相等,不会考虑数据类型。只要数值不相等,不论数据类型是否相同,!= 都会返回 true

$a = 5; // 整数
$b = '5'; // 字符串

var_dump($a != $b); // 输出 false,因为在不考虑数据类型的情况下,整数和字符串相等

2.绕过 

        ⚪判断条件2:PHP中"=="的问题

  if (!is_numeric($passwd)) {
                if($passwd == 1234567) 

       要求输入的$passwd不是数字或者纯数字字符串(带有字母或特殊符号),但是$passwd 的值与 1234567比较要相等。如果 $passwd 的值是字符串 '1234567a',则is_numeric($passwd)返回false,!is_numeric($passwd)则为true,满足第一个条件。第二个if条件,PHP 会尝试将 $passwd 的值和 1234567 进行比较。由于 == 比较运算符会尝试将操作数转换为相同的类型,它会尝试将字符串 '1234567a' 转换为整数。在这种情况下,$passwd 的字符串值 '1234567a' 会被尝试转换为整数 1234567。因为字符串开头的数字部分是 1234567,所以转换成功。最终,比较的结果是两个整数的比较,1234567 等于 1234567,因此条件 $passwd == 1234567 会返回 true

        ⚪判断条件1:MD5比价(强碰撞)

若为弱比较:

md5加密后为0e开头的会被识别为科学记数法,结果均为0

例如:para1=QNKCDZO ,para2=aabg7XSs

md5(para1)=0e830400451993494058024219903391

md5(para2)=0e087386482136013740957780965295

此时MD5(para1)== MD5(para2)

若为强比较:

如果传入的两个参数不是字符串,而是数组,md5()函数无法解出其数值,并且不会报错,就会得到===强比较的值相等

例如:para1[]=111  ,  para2[]=222

此时md5(para1)=== md5(para2)

三、解题实现

1.先通过GET请求发送id和gg参数,采用数组绕过md5强比较,发送数据

BUUCTF—[MRCTF2020]Ez_bypass1_第1张图片

得到的回显中显示通过第一步

BUUCTF—[MRCTF2020]Ez_bypass1_第2张图片

2.采用POST方式提交passwd,并将passwd设置为"1234567a",得到flag

BUUCTF—[MRCTF2020]Ez_bypass1_第3张图片

BUUCTF—[MRCTF2020]Ez_bypass1_第4张图片

                   

                       

你可能感兴趣的:(php,web安全)