上学期本来看过一些长度扩展攻击的东西的,但是时间过了太久了都忘得差不多了.近期刷题恰好又刷到一道md5长度扩展的题,正好总结一下. 我们先了解一下md5加密流程: 参考链接:传送门
首先对长度进行填充和分组
填充是把数据变成512*N+448位的形式,比如如果长度小于448,那么直接补成448位;如果长度大于448位小于512位,就补充成512+448位这种。
填充方法:在消息后面加个1然后无限补0,16进制就是补个80然后无限补0直到448位。
填充完之后前面每组512位,最后一组448位,即56个字节。第57个字节是补位之前的消息长度,后面继续补0直到64字节.就比如下图
abc三个字母,即3字节,24位,十六进制是0x18,所以填个18,后面补0x00.
然后
完成上述过程之后就是获取一个链变量,然后和这个链变量一起进行一波复杂运算(这里不管) 这个链变量一开始是定值,后面的链变量都是上一个块运算得到的结果.
最后
获得最后一次消息的摘要之后进行一个高低位互换即可获得md5。
md5长度扩展攻击
md5长度扩展攻击是什么呢?它的实质就是构造明文控制加盐哈希,比如我前面构造和已经补位了的块完全相同的块,那么我第一部分获得的链变量就是相同的,如果我用这个链变量来后续处理我自己添加的字符串,那我是不是就可以在你的hash后面加东西了. 举个例子: 本来一个字符串\(a="test",0x74657374 我构造一个字符串\)str1: 0x746573748000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000002000000000000000 如果我们知道"test"的hash值,那么这个部分计算出来的值我们是知道的,因为"test"运算的时候也要补位 补位的操作和我们手动的操作是一致的,所以结果是一样的,但是不同的是,我们对字符串后面加了我们自己要添加的东西,比如 0x746573748000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000002000000000000000746573748 这个时候字符串大于512位,所以计算的时候会先补位位1024位,如下 \(str=0x7465737480000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000020000000000000007465737480000 00000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000002002000000000000 计算的时候先算 0x746573748000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000002000000000000000 前面这个部分的链变量为: A=0xcd6b8f09 B=0x73d32146 C=0x834edeca D=0xf6b42726 那么后面的运算用这个部分的链变量来计算即可 0x746573748000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000002002000000000000 通过这种方式,假如我们知道md5(\)salt.\(msg1)的值,知道\)salt长度,那么我们就可以获得md5(\(salt.\)msg1.\(padding.\)hack_content)的值。 在使用长度扩展攻击的时候可以使用hashpump工具,或者是python的hashpumpy库(自行pip安装) 然后我们本地实验一下(自行去掉换行,这里为了美观)
1 |
|
得到结果为
然后使用hashpump工具得到的结果如图
所以工具是可以信赖的(hhhh,测试一下嘛...) 具体可以看下面两道题
第一题
实验吧的一道题-让我进去 传送门
首先cookie的source改成1看源码,然后发现要让cookie的getmein的值为md5(salt+username+password)
然而salt值我们不知道,然后题目给出了salt长度为15,并且给出了md5(salt+"admin"+"admin"),但是要求getmein不能为这个已经给出的hash,所以这是一道非常经典的长度扩展攻击的题目,通过给出的hash和salt长度,构造出md5(salt+已知值+padding+控制值).
具体工具使用
其中签名是已知hash,然后inputdata是后面密码那个admin,长度是前面的salt+username的admin共计20
然后假设加上padding,然后自己控制数据为blacsheep,那么我们就可以获得flag了.
我们的username填admin,然后密码填admin%80%00%00%00%00%00%00%00%00%00%00%00
%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%c8%00%00%00%00
%00%00%00blacsheep cookie的getmein填fd9b223a9c562017f65eaf824f3ca8dd
如图
第二题
Jarvis的一道题-flag在管理员手里 首先index.php~源码泄漏,vim -r恢复一下 得到源码:
1 | <!DOCTYPE html> |
分析一下源码:首先cookie里面的role要为"admin"的序列化值
而cookie里面的hsh要为md5(salt+"admin"的序列化值的倒序)
而目前我们已经有了md5(salt+"guest"的序列化的倒序)
不过我们并不知道salt的长度 这里需要暴力跑一下. 整理一下条件 我们已知条件
md5(salt+;"tseug":5:s)为3a4727d57463f122833d9e732f94e4e0
要求md5(salt+;"nimda":5:s)
但实际上,反序列化是存在一个小漏洞的,比如 反序列化到分号就停止了
所以这里我们只用把自定义数据改成;"nimda":5:s
所以我们实际上是求md5(salt+;"tseug":5:s+padding+;"nimda":5:s)
本来长度扩展攻击放在最后的一段数据因为反向到前面,又因为反序列化的小漏洞,直接返回了admin
由这些就可以拿到flag了 所以我们写个脚本实验一下
1 | import requests |
然后运行结果 这就拿到flag了
避免md5长度扩展攻击的方法就是md5(salt+md5(input))