最近看到了好多针对de1ctf ssrfme题目分析,顺便把之前没搞明白的哈希长度扩展攻击写一下
链接这篇文章讲的很仔细了,分析一下文章中的栗子
师傅给的代码
md5的过程
- MD5 padding
如果输入信息的长度(字节)对64求余的结果不等于56,就需要填充使得对64求余的结果等于56。填充的方法是填充一个x80和xx个0。填充完后,信息的长度为N*64+56(字节),并且最后8个字节用来记录原始输入信息长度
- MD5 compress
这个算法直接到网上找就行
所以MD5的过程就是:
先进行消息长度的填充(padding)。填充完后,初始化的4个Magic number会和第一个64字节的Message block进行md5 compress压缩算法。压缩算法完成后,会产生新的4个Magic number。这样再进行第二个64字节Message block的md5 compress压缩算法。以此类推……直到压缩到最后64个字节的(Message block + padding),最后得到的Magic number经过hex转化就是最后的md5 hash值
比如md5(‘admin’),由于padding之后只有64个字节,所以只进行一轮的md5 compress 得到的密文就是:
21232f297a57a5a743894a0e4a801fc3
我们可以从密文推导出4个magic number:
1 | A=0x292f2321L |
这个关系就是大小端转化一下
md5长度扩展的攻击过程
知道如下三个值:
- md5(salt+message)的值
- message内容
- salt+message长度
我们可以根据md5(salt+message)的值逆向出最后的四个magic number
1 | def compute_magic_number(self, md5str): |
这个四个magic number去和m做一下次的md5 compress
再理解一下
继续又看了一篇师傅的文章,想要好好梳理一下哈希扩展攻击
师傅是以sha1算法为例讲解的: sha1的流程如下:
sha1算法和md5很相似,也有最初的四个IV,并且是确定的(这是一种很不好的方法但是也是一种无奈的举动)
一个不足64位的字符串会被padding至64位,并且由于只有一个分组,所以只需要一轮运算即可
我们在前一次64位padding之后的字符串的基础上加入一些字符,sha1(salt+padding+add_data) 首先这里肯定是要分成两组的,前一组加密后的内容已经知道了,同时产生的新的IV会参与下一次的复杂的数学运算
而这些IV是能够从第一组的密文中得知的,这就导致下一组加密后的内容实际上我们也可以知道的
《白帽子讲web安全》上提到,如何利用长度扩展攻击:
LengthExtension 使得可以在原文之后附加任意的值,并计算出新的hash值,最常见的地方就是签名
- 错误的签名校验算法
参数连接时没有使用分隔符,本来是?a=1&b=2&c=3
在签名算法中简单地变成了a1b2c3
于是攻击者可以伪造参数?a=1b2c3[...padding....]&b=4&c=5
最终在签名算法中连接时变成了a1b2c3[...padding...]b4c5
附加任意的参数
HPP
最简单的防护就是将secret放置在参数的末尾
举例
大师傅给的栗子:
1 |
|
已知role为admin,salt的长度为4,hash值为:c7813629f22b6a7d28a08041db3e80a9
我们可以在role
后面附加任意的数据使得第一个if被绕过
用大师傅的脚本:
python md5pad.py c7813629f22b6a7d28a08041db3e80a9 joychou 9
当然也可以这样:
1 | $ hashpump |
注意第三次输入的数据长度是包括salt在内的