任务详情
任务描述:
在一个使用MD5哈希算法的系统中,管理员使用了一个密钥k和命令cmd的组合来生成每个命令的签名:hash(k||cmd)。你已经获得了一个允许查看文件的命令cmd=viewfile和对应的签名h,但你希望通过哈希长度延展攻击,生成一个新的签名,该签名能够让你执行删除文件的命令(删除文件的命令为rm)。
具体步骤:
- 研究MD5哈希长度延展攻击的机制,并找出适用于此场景的攻击方法。(3分)
- 使用合适的工具或脚本,基于cmd=viewfile和签名h,构造一个新的命令cmd=viewfile||padding||deletefile和新的签名。(6分)
- 提交你使用的攻击方法、工具或脚本的详细说明,以及成功构造的命令和新的签名。(6分)
解题
1 哈希延展攻击
- 来自《数字认证技术》一书,清华大学出版社
2 构造预先计算
现在我已知内容是hash(k||cmd)
,k对应的内容是20211108
,cmd对应的内容是viewfile
,hash(k||cmd)
对应内容应该为d5320b5ddd3fb43f4fadc4236af772b9
下面就要根据hash(k||cmd)
构造出hash(k||viewfile||padding||deletefile)
由于MD5在进行计算前会进行填充,且填充规则为先填充一个1,然后填充0,直到新的消息长度满足 (原长度 + 1 + 填充长度) 除以512的余数为448。在本题中原消息长度为128,则填充长度为320。
- 参考:MD5算法
3 构造
这里使用hashlab库编了一个程序进行MD5延展攻击,并且得到伪造的签名
import hashlib
def md5_extend(original_message, original_hash, extension):
# 步骤1:计算原始消息的字节长度
original_length = len(original_message.encode())
# 步骤2:初始化填充
padding = b'\x80' + b'\x00' * ((56 - (original_length + 1) % 64) % 64)
# 步骤3:添加原始消息的比特长度
padding += (original_length * 8).to_bytes(8, byteorder='little')
# 步骤4:计算新哈希值
new_hash = hashlib.md5()
new_hash.update(extension.encode())
new_hash.update(padding)
forged_message = original_message.encode() + padding + extension.encode()
# 步骤5:返回伪造消息和哈希值
return forged_message, new_hash.hexdigest()
original_message = "20211108viewfile"
original_hash = hashlib.md5(original_message.encode()).hexdigest()
extension = "rm *"
forged_message, new_hash = md5_extend(original_message, original_hash, extension)
print("原始消息:", original_message)
print("原哈希值:", original_hash)
print("伪造消息:", forged_message.hex()) # 将字节串转换为十六进制表示
print("新哈希值:", new_hash)
md5_extend函数接受原始消息(主要需要原始消息的长度)、原始哈希值和要添加的扩展内容作为输入,然后返回伪造的消息和新的哈希值。
运行结果为
PS C:\Users\Dr.Yu\OneDrive\桌面\ljp新> & C:/Users/Dr.Yu/AppData/Local/Microsoft/WindowsApps/python3.11.exe c:/Users/Dr.Yu/OneDrive/桌面/ljp新/云班课/MD5/MD5延展攻击.py
原始消息: 20211108viewfile
原哈希值: d5320b5ddd3fb43f4fadc4236af772b9
伪造消息: 32303231313130387669657766696c65800000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000726d202a
新哈希值: a1e19f6a4338a3da08265a59d0df7c34
伪造的消息是采取16进制输出的,以下是具体解释:
32 30 32 31 31 31 30 38 -> 20211108 (原始消息:key)
76 69 65 77 66 69 6c 65 -> viewfile (原始消息:命令)
80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -> 填充(0x80表示消息末尾,然后补零直到达到填充条件)
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -> 原始消息长度(8字节,十六进制的80)
72 6d 20 2a -> rm * (扩展内容,ASCII 字符串)
伪造的哈希结果为a1e19f6a4338a3da08265a59d0df7c34
伪造的消息为
76 69 65 77 66 69 6c 65 -> viewfile (原始消息:命令)
80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -> 填充(0x80表示消息末尾,然后补零直到达到填充条件)
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -> 原始消息长度(8字节,十六进制的80)
72 6d 20 2a -> rm * (扩展内容,ASCII 字符串)
注:一定得已知原消息长度和原消息的哈希值才可计算,思考如下:(严格证明暂时没想出来)
Length Extension Attack 是一种与某些特定类型的哈希函数(如 MD5,SHA-1 和 SHA-2)的特性有关的攻击。简单来说,这种攻击利用了一个事实,即知道 H(message) 和 message 的长度,我们可以轻松计算出 H(message || padding || extension) 而不需要知道 message 本身。其中 “||” 表示连接,“padding” 是根据哈希函数的规定添加的。