NSSCTF | [SWPUCTF 2021 新生赛]easy_md5

发布于:2024-05-10 ⋅ 阅读:(25) ⋅ 点赞:(0)

打开题目,是一个高亮显示的php脚本

<?php 
 highlight_file(__FILE__);
 include 'flag2.php';
 
if (isset($_GET['name']) && isset($_POST['password'])){
    $name = $_GET['name'];
    $password = $_POST['password'];
    if ($name != $password && md5($name) == md5($password)){
        echo $flag;
    }
    else {
        echo "wrong!";
    }
 
}
else {
    echo 'wrong!';
}
?>

这段PHP代码用于演示一个典型的安全挑战,特别是关于PHP中md5哈希函数的特性和弱类型比较的问题。以下是逐行分析:

第1行:展示当前文件源代码

通过highlight_file(__FILE__);展示当前文件的源代码。__FILE__是一个特殊的预定义常量,表示当前文件的完整路径和文件名。

第2行:包含外部文件

include 'flag2.php';引入外部文件flag2.php。我们可以假设这个文件定义了一个名为$flag的变量,其中包含了需要在满足特定条件下显示的敏感信息(即"flag")。

第3-17行:校验GET和POST参数

代码首先检查是否同时通过GET方法提交了name参数和通过POST方法提交了password参数。如果没有,输出"wrong!"。

如果两个参数都存在,分别将它们赋值给变量$name$password

条件判断和漏洞点

核心逻辑在于这个条件判断:

if ($name != $password && md5($name) == md5($password)){
    echo $flag;
}
  • 条件要求$name$password不相等,但它们的MD5哈希值必须相等,才会输出$flag变量的值(即满足挑战条件)。
  • 这里利用的是PHP中md5哈希函数的特性和弱类型比较(==)。在某些特殊情况下,不同的输入可以产生相同的MD5哈希值长文本输出(尽管这是极为罕见的),或者在使用==进行比较时利用PHP弱类型的特性来绕过检查。

实际上,满足这个条件的一个通常方法是利用PHP中的"魔术哈希"(Magic Hash)问题。"魔术哈希"是指一些特殊值,它们的MD5哈希值以"0e"开头,接下来是纯数字,这在PHP中会被解释为科学记数法表示的0,导致弱类型比较时等于另一个具有相同特性的哈希值。

总结

这个脚本的挑战点在于找到使得$name$password的MD5哈希值在弱类型比较下相等,但这两个值本身并不相等的输入。正确的解决方式通常涉及寻找或利用已知的“魔术哈希”值。

这道题有两种解法,一种是寻找两变量值不相等,但md5后的散列值相等的一组数据,分别使用GET和POST两种请求方法传入即可得到flag。

另一种是通过数组绕过的方式。

第一种解法:md5绕过

介绍几个符合两变量值不相等,但md5后的散列值相等的数据

//md5加密后以0E开头,且后面均为纯数字
QNKCDZO
240610708
s878926199a
s155964671a

 然后利用Hackbar传参即可得到flag。

payload:?name=QNKCDZO

POST:password=240610708

第二种方法:数组绕过

payload:?name[]=1

POST:password[]=2

PHP 中的 md5 函数在处理字符串时运行正常,但如果传入的是一个数组,md5 函数返回 NULL。在 PHP 中,当你尝试对一个数组使用 md5() 函数时,会发生类型错误,因为 md5 预期的是一个字符串。如果请求的参数是一个数组(例如通过 name[]=1),则 $_GET['name'] 和 $_POST['password'] 将会是数组而不是字符串。

那么,在提及的代码逻辑中,当同时使用GET传参 ?name[]=1 和POST传参 password[]=2 时,$name 和 $password 都会成为数组。这将导致条件:

if ($name != $password && md5($name) == md5($password)){
    echo $flag;
}

结果如下:

  • $name != $password 返回 true,因为两个数组不相等。
  • 由于 PHP 会对名称后带 [] 的参数自动创建数组,因此 md5($name) 和 md5($password) 都会尝试对数组进行哈希处理,导致它们都返回 NULL 或者产生一个警告并返回一个布尔值 false
  • 在 PHP 中,(NULL == NULL) 为 true,(false == false) 也为 true。因此使得 md5($name) == md5($password) 返回 true,而忽略了实际哈希值因为它们都是 NULL 或者 false。

因此尽管 $name 和 $password 都没有被哈希处理,但由于它们都返回了 NULL 或者 false,相等性比较因类型转换返回了 true,从而导致它们按照代码的逻辑满足了输出 $flag 的条件。这是一个类型弱检查的问题,说明==在 PHP 中可能会导致一些非预期的行为,尤其是当比较的值中包含非字符串类型,像是数组时。

本题完。

 


网站公告

今日签到

点亮在社区的每一天
去签到