大致描述:
系统会自动生成一串任意的字节串secret,以及一串明文c1然后进行哈希加密,
m1=hash(secret+c1)
我们可以得到加密后的密文m1,
然后我们需要提供一个密文m2,以及一串明文c2
使得
m2=hash(secret+c2)
#一般来说,c1 in c2,c2实际上为c1的拓展部分,我们需要把明文的长度拓展一下,进行攻击
然后即可得到flag
下面介绍哈希函数的加密原理
攻击原理:
- 分块
哈希计算进行加密时,通常是将明文信息以类似块密码的形式进行分组,对各个组块依次加密,每一块一般为512bit,也就是64bytes,每组的明文部分为56bytes,剩下的8bytes表示这块明文消息未填充前的长度
- 填充
在明文消息的最后一块一般是不满足56ytes时就对这个最后一块进行padding填充,填充至56bytes的位置,,填充方式为,在16进制下,我们需要在消息后添加一个80,然后加0,直至56bytes时
- 变量计算
哈希加密的在分块之后,每块在进行加密运算之前都会有一个链变量(key),有每一个链变量与该块进行运算,除了第一块,每一块相对应的链变量都是前一块进行哈希计算后的字符串生成的,也就是说,每一块都对下一块有影响,(有点类似于CBC了),而第一块会有一个初始的链变量,为(无需考虑计算过程的细节)
A=0x67452301
B=0xefcdab89
C=0x98badcfe
D=0x10325476
而最后一块生成的链变量需要进行高低位互换(如:aabbccdd -> ddccbbaa),再拼接在一起就是我们计算出来的哈希值
代码验证
from hashlib import md5,sha256
import os
flag=b'flag{welcome}'
secrets=os.urandom(15)
m=b'admin'
k1=sha256(secrets+m+m).hexdigest()
print(k1)
key=input("输入key的16进制")
cipher=input("输入哈希值")
s1=secrets+m+bytes.fromhex(key)
'''经过多次尝试后发现,在python中,输入16进制字符串时对格式最友好的
如果输入为类似\x00\x00\x00\x00\x00\x80的字符串,
进行encode转为字节串会生成\\x00\\x00\\x00\\x00\\x00\\x80的错误形式
即使转为urlcode在转回来的时候也会有误差,可能是我python环境的问题
'''
'''
在使用hashpump时
signnature:已知的hash加密的字符串
data:hash加密字符串中明文中已知的部分
key length: 未知的字符串长度
add:自己想添加的附值
'''
k2=sha256(s1).hexdigest()
print(k2)
if cipher==k2:
print(flag)
利用工具实现哈希长度拓展攻击
当然,此攻击已经有很多成熟的工具了,不用再这么麻烦的自己写脚本跑。下面介绍几款好用的工具:
转载来自 <哈希长度拓展攻击(Hash Length Extension Attacks) - 先知社区>
- HashPump 这是pcat写的一篇"哈希长度扩展攻击的简介以及HashPump安装使用方法"