哈希扩展长度攻击详细介绍
in 安全技巧 with 0 comment

哈希扩展长度攻击详细介绍

in 安全技巧 with 0 comment

0x01 原理讲解

首先,当hash函数拿到需要被hash的字符串后
先将其字节长度整除64,取得余数。
如果该余数正好等于56,那么就在该字符串最后添加上8个字节的长度描述符(具体用bit表示)。
如果不等于56,就先对字符串进行长度填充,
填充时第一个字节为hex(80),其他字节均用hex(00)填充,
填充至余数为56后,同样增加8个字节的长度描述符(该长度描述符为需要被hash的字符串的长度,不是填充之后整个字符串的长度)。
以上过程,称之为补位。
补位完成后,字符串以64位一组进行分组(因为上面的余数为56,加上8个字节的长度描述符后,正好是64位,凑成一组)。
字符串能被分成几组就会进行多少次“复杂的数学变化”。
在进行数学运算之前,规定了一组初始值(又叫registers),
被设置为这组数是固定的(你没看错是固定死的):

这个registers值会进入复杂的数学运算,
每次进行“复杂的数学变化”都会生成一组新的registers值供下一次“复杂的数学变化”来调用。
当后面已经没有分组可以进行数学变化时,
该组生成的registers值就是最后的hash值。
说了这么多,我们来举个例子:
当需要被hash的字符串为str_a = ”123456”,
程序首先判断,len(str_a) % 64 == 56是否成立。
这里很明显不成立。那么程序就进行补位操作。首先补位成余数为56的长度。
QQ20170521-120524@2x.png
如上图,蓝色字体就为程序对该字符串进行补位的数据。
当满足len(str_a) % 64 == 56后,
程序就在该字符串的后面添加8个字节的长度描述符。
注意,此处的长度为原始需要被hash的长度。
也就是len(str_a) = 6字节*8bit/字节= 48bit=0x30bit。
QQ20170521-120545@2x.png
补位+长度描述符=64个字节,正好是一个分组。
所以此处只要进行一次复杂的数学变化就可以了。

0x02利用场景

现在假如你要下载网站上的一个文件,给我传一个文件名,就比如是report.pdf
我在服务端这样处理
QQ20170521-120555@2x.png
$filename被过滤了,由于用户不知道我$salt的值,
所以这个返回的md5值用户也是不能伪造的,然后生成一个链接:
http://example.com/download?file=report.pdf&mac=563162c9c71a17367d44c165b84b85ab59d036f9
这个链接是一个下载的页面,我们来看服务端怎么处理
QQ20170521-120606@2x.png
到这里,我们想想,在create_hash这个函数中,我们的$filename被过滤了,
所以我们就不能伪造用于下载的mac值,
就不能下载我们想要的文件(例如:../../etc/password.php)
这是基于mac值不能伪造的情况下,但是实际情况中,
只要我们知道了$salt的长度,mac值就能被伪造

0x03 攻击过程

这里假如我们的$salt=123456789abcdefg,$filename=report.pdf
QQ20170521-120618@2x.png
然后会填充,填充之后的结果如下
QQ20170521-120629@2x.png
我们可以看到,这正好是64个字节,
也就是只用进行一次复杂的数学运算就可以了,
得到的md5值0a8d538b724c6f2b4288526eb540ee7c
我们刚刚提到了,md5函数的registers值是a,b,c,d,
经过一轮复杂的数学变换之后变成a1,b1,c1,d1,
然后a1.b1.c1.d1组合起来就是最后的md5值
重点来了,假如我们这样构造
QQ20170521-120641@2x.png
也就是$filename=”report.pdf%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%00%00%00%00%00%00%00%00%00%00%00%D0../../etc/passwd”
我们可以看到,这样总的长度就超过了64位,
但是小于128位,也就是说需要经过两轮复杂数学变换得到最后的md5值,如下

最后的a2,b2,c2,d2组合起来是我们提交的$filename的md5值吧
我们再看,这个a1,b1,c1,d1是不是我们提交$filename=”report.pdf”就可以得到的,
是服务器返回给我们的。
也就是说我们只需要把md5函数中的初始值由a,b,c,d改成a1,b1,c1,d1,
然后用修改之后的md5函数,加密字符串
”../../etc/passwd”(填充结果需要修改后8位)就可以了
我们就可以得到a2,b2,c2,d2的值,也就能伪造出mac值了
这就是哈希扩展长度攻击的整个过程
攻击py脚本
科普hash扩展长度攻击

Comments are closed.