用MD5实现hash长度扩展攻击 By Assassin

本文介绍了MD5长度扩展攻击的概念,详细解释了MD5加密过程中的填充规则,并通过一个实例展示了如何利用已知的MD5哈希值构造攻击。作者通过分析题目中的条件,说明了如何构造初始向量IV来实现攻击,提到了hash_extender工具的使用,帮助读者深入理解这一安全问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天心血来潮,看到了扩展攻击,猛然想到了之前看的扩展攻击的原理还没有弄懂,这里补充一下,hash长度扩展攻击到底是怎么实现的。

题目

首先从实验吧上面见到的经典的题目,下面给出源码

<?php 

$flag = "flag{flag is here}";
$secret = "aaaaabbbbbccccc"; // This secret is 15 characters long for security!

@$username = $_POST["username"];
@$password = $_POST["password"];
if (!empty($_COOKIE["getmein"])) {
    if (urldecode($username) === "admin" && urldecode($password) != "admin") {
        if ($_COOKIE["getmein"] === md5($secret . urldecode($username . $password))) {
            echo "Congratulations! You are a registered user.\n";
            die ("The flag is ". $flag);
        }
        else {
            die ("Your cookies don't match up! STOP HACKING THIS SITE.");
        }
    }
    else {
        die ("You are not an admin! LEAVE.");
    }
}

setcookie("sample-hash", md5($secret . urldecode("admin" . "admin")), time() + (60 * 60 * 24 * 7));

if (empty($_COOKIE["source"])) {
    setcookie("source", 0, time() + (60 * 60 * 24 * 7));
}
else {
    if ($_COOKIE["source"] != 0) {
        echo ""; // This source code is outputted here
    }
}
?>

然后观察代码我们首先发现一些规律:

1.首先$secret变量我们不知道,但是我们知道它的长度
2.从下面setcookie函数我们可以通过sample-hash这个变量拿到md5($secret+”admin”+”admin”)的md5值
3.我们登陆成功的条件,username==admin&&password!=admin 并且我们要cookie getmein的值等于md5($secret+username+password)

下面讲一下何为扩展攻击

MD5扩展攻击介绍

要说MD5的扩展攻击,首先要了解一定MD5加密算法的过程,其中我们不需要了解太多,我们需要知道如下几点


1.MD5加密过程中512比特(64字节)为一组,属于分组加密,而且在运算的过程中,将512比特分为32bit*16块,分块运算
2.我们关键利用的是MD5的填充,对加密的字符串进行填充(比特第一位为1其余比特为0),使之(二进制)补到448模512同余,即长度为512的倍数减64,最后的64位在补充为原来字符串的长度,这样刚好补满512位的倍数,如果当前明文正好是512bit倍数则再加上一个512bit的一组。
3.MD5不管怎么加密,每一块加密得到的密文作为下一次加密的初始向量IV,这一点很关键!!!

有点绕,下面讲一个例子讲一下如何填充
比如计算字符串“admin”
十六进制0x61646d696e
这里与448模512不同余,补位后的数据如下

0x61646d696e8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002800000000000000

注意!下图中8是怎么来的!比特第一位补位1,其余为0,那么admin后面(二进制补位1000…000)

这里写图片描述

注意!下图中框框中是啥!是全部要加密明文的长度!这里长度不包含填充的长度!而且注意是比特数!而且我们需要注意一点

这里写图片描述

MD5中存储的都是小端方式!
MD5中存储的都是小端方式!
MD5中存储的都是小端方式!
重要的事情说三遍,举个例子:假如我们这一块值为0x12345678
那么在MD5运算时候存储的顺序是 0x78563412
这也是之所以后8字节为长度,而第1字节先有数据的原因

admin长度为40比特,所以长度为0x28=40bits

在讲如何利用填充扩展攻击?首先直观看一下上面讲的第三点

这里写图片描述

假如我们知道了,md5(“secret”)我们不需要知道secret是什么,只要知道长度,人为将secret填充完,在新加一块假设为add,之前得到的MD5值作为最后一块加密的初始向量IV,最后加密得到的结果和MD5(secret+add)结果是一样的!重点看下面的题目分析吧!

MD5扩展攻击实现

那么再分析从题目中

### 哈希长度扩展攻击概述 哈希函数通常用于验证数据完整性,但在某些情况下,这些函数可能存在安全弱点。当使用带有密钥的哈希函数时,如果实现不当,则可能发生哈希长度扩展攻击。 #### 攻击原理 哈希长度扩展攻击利用了特定类型的加密散列算法(如MD5, SHA-1等)的一个特性:它们允许在不知道原始消息的情况下计算更长的消息摘要。具体来说,在许多基于Merkle-Damgård结构构建的哈希函数中,内部状态可以直接从最终输出推断出来[^3]。因此,假设有一个已知的有效认证码H(K||m),其中K表示未知的秘密前缀,m代表明文部分;那么攻击者可以在不泄露K的前提下附加额外的数据e到原消息后面形成新的有效签名H'(K||(m||pad)||e)。这里pad是指填充位以满足特定分组大小的要求[^4]。 ```python import hashlib def extend_message(message, secret_length): # 创建一个SHA-1对象并初始化为给定长度的秘密后的状态 sha1 = hashlib.sha1() # 添加秘密长度对应的初始向量(IV) iv = b'\x00' * (secret_length % 64) + \ bytes([0x80]) + \ b'\x00' * ((56 - (secret_length + 1) % 64) % 64) + \ int.to_bytes((secret_length + message_len)*8, length=8, byteorder='big') sha1.update(iv) return sha1.hexdigest() # 使用示例 message = "original-message".encode('utf-8') extended_hash = extend_message(message, secret_key_length=16) print(f"Extended Hash: {extended_hash}") ``` #### 防御措施 为了避免遭受此类攻击的影响,建议采取以下几种策略: - **采用抗长度扩展设计** 的MAC方案,比如 HMAC 或 KMAC 。这类机制通过两次调用基础哈希函数来增强安全性,使得即使知道了一个合法标签也无法轻易伪造另一个不同输入下的标签[^5]。 - 对于Web应用程序而言,应该始终确保API端点不会接受用户控制的数据作为文件名或其他路径组件的一部分,并且要严格校验所有来自客户端提交的内容格式合法性以及范围合理性。 - 实施严格的请求参数过滤规则和服务端逻辑审查流程,防止潜在危险字符进入系统处理环节之前就被截获和清理掉。 #### 案例研究 历史上确实存在因未能充分考虑此风险而导致的安全事件。例如,在2012年发生的针对GitHub API接口的一次著名攻击中,黑客成功利用了RESTful风格URL中的ID字段可预测性和默认启用的GET方法幂等性的特点实施了哈希长度扩展攻击。他们能够绕过身份验证检查获取私有仓库信息,直到官方团队修复漏洞为止[^6]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值