5.【BUUCTF】[BJDCTF2020]Easy MD5及知识点

进入题目页面如下

尝试提交XSS攻击以及sql注入

并没有回显,尝试无果,用burp suite抓取响应包查看一下,右键→拦截→拦截响应

在响应中找到了响应头

Hint:select * from 'admin' where password =md5($pass,ture)

给出提示MD5

SQL 查询语句的提示,原始的查询语句 select * from 'admin' where password =md5($pass,true) (注意:MD5 函数第二个参数在不同数据库意义不同,在 MySQL 里 MD5() 函数只接受一个参数)

这个 SQL 语句的目的是从名为 admin 的表中查询出 password 字段值等于对变量 $pass 进行 MD5 哈希处理后结果的所有记录。

SQL 注入风险

原理:如果在实际应用中,$pass 是用户输入的内容,且没有经过严格的过滤和转义,可以通过构造特殊的输入来改变 SQL 语句的原意,从而实现 SQL 注入攻击。

php 复制代码
<?php
$pass = $_GET['pass'];
$sql = "SELECT * FROM admin WHERE password = MD5('$pass')";
// 执行 SQL 查询
?>

可以构造如下的 pass 参数:

' OR '1'='1

最终的 SQL 语句会变成:

SELECT * FROM admin WHERE password = MD5('' or '1'='1')

由于 '1'='1' 永远为真,这个查询会返回 admin 表中的所有记录,可能借此绕过登录验证或者获取敏感信息。

当'or'后的值为True时,可实现SQL注入

md5函数

md5 函数通常用于计算输入字符串的 MD5 哈希值。md5(string, raw) 这种形式的函数调用中,string 是需要进行哈希计算的输入字符串,而 raw 是一个布尔类型的参数,用于指定返回的哈希值的格式。

string:这是必需的参数,代表要进行 MD5 哈希计算的原始字符串数据。可以是任意长度的文本信息,例如用户密码、文件内容等。

raw:这是一个可选参数,不同编程语言对该参数的处理和含义可能有所不同,但一般来说:

当 raw 为 true 或者类似表示真的值时,函数会返回原始的 128 位(16 字节)二进制格式的哈希值。

当 raw 为 false 或者类似表示假的值时,函数会返回以 32 位十六进制字符串形式表示的哈希值。

在 PHP 里,md5() 函数的第二个参数用于指定是否返回原始二进制数据
php 复制代码
<?php
// 待哈希的字符串
$string = "Hello, World!";

// 返回 32 位十六进制字符串形式的哈希值
$hexHash = md5($string, false);
echo "十六进制哈希值: ". $hexHash. "\n";

// 返回原始二进制形式的哈希值
$binaryHash = md5($string, true);
echo "二进制哈希值长度: ". strlen($binaryHash). " 字节\n";
?>

在上述代码中,当第二个参数为 false 时,得到的是常见的 32 位十六进制字符串;当为 true 时,得到的是 16 字节的二进制数据。

看了大佬的博客才继续下去,附上链接

[BUUOJ记录] [BJDCTF2020]Easy MD5 - Ye'sBlog - 博客园

大佬说

ffifdyop 字符串md5加密后若raw参数为True时会返回 'or'6<trash> (<trash>

只要第一位是非零数字会被判定为True

<trash>会在MySQL将其转换成整型比较时丢掉

后端的SQL语句

复制代码
select * from `admin` where password=''or'6<trash>'

直接输入ffifdyop,点击提交

进入下一个界面

ctrl+u查看源代码

看到注释中的关键信息

这里使用了==弱比较

比较操作符分为强比较和弱比较,以 PHP 为例来详细讲解弱比较 == 的情况。当在代码里使用 md5(string, raw) 配合 == 弱比较

PHP 中 == 弱比较规则

在 PHP 里,== 是弱比较操作符,它在比较时会进行类型转换,然后再比较值是否相等。

复制代码
var_dump(0 == "abc"); // 输出: bool(true)

这是因为在使用 == 比较时,PHP 会尝试将字符串 "abc" 转换为数字,转换结果为 0,所以与整数 0 比较时结果为 true

md5()== 可能出现的问题

在某些情况下,当使用 md5() 函数计算哈希值并使用 == 进行比较时,可能会因为弱比较的特性产生意外结果。

哈希值以 0e 开头的情况

部分字符串经过 MD5 哈希后的结果会以 0e 开头,在科学计数法中,0e 后面跟着的数字表示 0 乘以 10 的多少次方,结果始终为 0。当使用 == 比较两个以 0e 开头的 MD5 哈希值时,PHP 会将它们当作科学计数法表示的数字进行比较,从而认为它们相等。

php 复制代码
$str1 = "240610708";
$str2 = "QNKCDZO";
$md5_1 = md5($str1);
$md5_2 = md5($str2);

var_dump($md5_1 == $md5_2); // 输出: bool(true)

echo "MD5 of str1: ". $md5_1. "\n"; // 输出: 0e462097431906509019562988736854
echo "MD5 of str2: ". $md5_2. "\n"; // 输出: 0e830400451993494058024219903391

在上述代码中,$str1$str2 是不同的字符串,但它们的 MD5 哈希值以 0e 开头,使用 == 比较时结果为 true

重要代码解释

php 复制代码
<?php
// 从 GET 请求中获取参数 a 的值并赋值给变量 $a
$a = $_GET['a'];
// 从 GET 请求中获取参数 b 的值并赋值给变量 $b
$b = $_GET['b'];

// 检查 $a 不等于 $b 并且它们的 MD5 哈希值相等
if ($a != $b && md5($a) == md5($b)) {
    // 若条件满足,执行这里的代码
    echo "找到了满足条件的 a 和 b!";
} else {
    // 若条件不满足,执行这里的代码
    echo "未找到满足条件的 a 和 b。";
}
?>

以下是可以绕过该条件判断的示例输入:

php 复制代码
?a=240610708&b=QNKCDZO

这两个字符串不同,但它们的 MD5 哈希值分别是:

md5(240610708) 的结果是 0e462097431906509019562988736854

md5(QNKCDZO) 的结果是 0e830400451993494058024219903391

在 PHP 的弱比较下,这两个哈希值会被判定为相等。

得到这个页面

进行代码审计

php 复制代码
<?php
// 关闭所有 PHP 错误报告,避免将错误信息暴露给用户,增强安全性,但也可能掩盖一些潜在问题
error_reporting(0);

// 引入 flag.php 文件,该文件中通常定义了敏感信息,如 flag 值
include "flag.php";

// 高亮显示当前 PHP 文件(即包含此代码的文件)的源代码,方便开发者调试或展示代码结构
highlight_file(__FILE__);

// 检查 POST 请求中 param1 和 param2 两个参数的值是否不相等,并且它们的 MD5 哈希值是否严格相等(值和类型都相等)
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
    // 如果上述条件满足,则输出 flag.php 文件中定义的 $flag 变量的值
    echo $flag;
}

由于 MD5 算法存在哈希碰撞的问题,也就是可以找到两个不同的输入,它们经过 MD5 计算后得到相同的哈希值。不过代码中使用了 === 进行严格比较,这要求不仅哈希值的内容相同,类型也要相同,所以利用以 0e 开头的 MD5 值在弱比较下相等这种方法在这里行不通。

但实际上可以利用 MD5 对数组不做处理的特性来绕过这个判断。当 md5() 函数的参数为数组时,它会返回 NULL

md5数组绕过

1. 原理概述

在许多编程语言里,当使用 MD5 函数对数组进行处理时,其行为可能并非如预期对数组元素进行哈希计算,而是会产生一些特殊结果,利用这些特殊结果可以绕过基于 MD5 哈希值比较的验证机制,这就是 MD5 数组绕过。以 PHP 语言为例,下面详细介绍其原理、示例及防范措施。

2. PHP 中 MD5 对数组的处理

在 PHP 里,md5() 函数是用于计算字符串的 MD5 哈希值的。当传入的参数是数组时,md5() 函数不会对数组元素进行哈希计算,而是直接返回 NULL

php 复制代码
<?php
$array1 = [1, 2, 3];
$array2 = [4, 5, 6];

$hash1 = md5($array1);
$hash2 = md5($array2);

var_dump($hash1);  // 输出: NULL
var_dump($hash2);  // 输出: NULL

if ($hash1 === $hash2) {
    echo "两个数组的 MD5 哈希值相等";
} else {
    echo "两个数组的 MD5 哈希值不相等";
}
?>

在上述代码中,$array1$array2 是不同的数组,但对它们使用 md5() 函数计算哈希值时,结果都为 NULL,所以在进行严格比较 $hash1 === $hash2 时,结果为 true

构造 POST 请求

可以通过构造一个包含两个不同数组的 POST 请求来绕过判断条件。

payload

param1[]=1&param2[]=2

用hackbar工具POST传参

最终得到flag

相关推荐
用户962377954481 小时前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机4 小时前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机4 小时前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户962377954486 小时前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star6 小时前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户962377954489 小时前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
BingoGo1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack1 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
cipher2 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
BingoGo2 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php