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

相关推荐
网络安全Ash1 小时前
网络安全——Span 安全监控
安全·web安全·php
鸿业远图科技1 小时前
网件r7000刷回原厂固件合集测评
网络·智能路由器
EasyGBS1 小时前
设备通过国标GB28181接入EasyCVR,显示在线但视频无法播放的原因排查
网络·ffmpeg·音视频
网络安全Jack1 小时前
网络安全—DDoS攻防
网络·web安全·ddos
阿巴~阿巴~1 小时前
C_数据结构(队列) —— 队列的初始化、入队列队尾、队列判空、出队列队头、取队头队尾数据、队列有效元素个数、销毁队列
c语言·网络·数据结构·算法·排序算法
佛州小李哥2 小时前
AI安全最佳实践:AI云原生开发安全评估矩阵(上)
人工智能·科技·安全·ai·语言模型·aws·亚马逊云科技
不是二师兄的八戒3 小时前
PHP 中 `foreach` 循环结合引用使用时可能出现的问题
php
SRC_BLUE_173 小时前
[权限提升] Linux 提权 — 系统内核溢出漏洞提权
安全·web安全·网络安全
hgdlip4 小时前
ip属地是实时刷新吗还是网络刷新
服务器·网络·tcp/ip