哈希长度扩展攻击的实现

0x00 引言

针对md5、sha1等哈希加密算法的攻击很多,但网上详细的分析哈希长度扩展攻击的文章却很少。其实这是一个非常简单明了的攻击手段,虽然此类哈希算法具有不可逆的特点,但是这种攻击手段很巧妙的利用了哈希算法的一个弱点,即初始幻数相同(也称初始值或registers)。在这篇文章中,默认读者对相应的算法已经有所了解,所以关于算法的实现在此不再赘述。本文以md5为例对哈希长度扩展攻击进行简要剖析。

md5算法:

sha1算法:

简单分析一下这两种算法的异同。

(回头再写www)

0x01 攻击成立的条件

1、攻击者知道哈希值和其的明文的一部分。

2、明文的另一部分长度已知或可预测(可穷举尝试或爆破以获取长度)。

3、服务器明文加盐的规律必须可预测或固定。

0x02 攻击准备

1、一个网上随处可见的正确的md5算法实现脚本(当然需要判断脚本正确与否的能力)

2、修改脚本

0x03 攻击原理分析

先建立几个概念:

1、这种攻击不是逆向的,而是正向的

2、这种攻击的本质是将服务器返回给你的哈希值作为初始状态还给服务器,让服务器在此基础上继续计算

推荐一篇讲原理讲的比较通俗易懂的文章:传送门

引言中提到过,哈希长度扩展是针对哈希算法的一个弱点展开的攻击。md5算法在一开始有四个初始幻数:

我们将明文信息长度对512bit取模,看看结果是否为448bit。一般来说很少会有信息正好满足这个条件,所以要经过一个补位的过程。补位至满足上述条件后再在信息的最后64bit加上信息的长度,若信息长度大于2的64次方,则只记原长度的低64位。补位完成后的消息应该是若干个512bit的区块。然后将补位完成后的消息以512bit为一组进行4轮运算,这里注意,所谓的运算是以明文信息为基础对幻数进行的运算,改变的是A,B,C,D这四个幻数。每一个512bit的区块对幻数进行运算后就被丢弃,每一个区块运算完毕后得出的新的4个幻数便是下一个区块运算时的初始幻数。一直到所有区块对幻数的计算结束,将最终的幻数小端反序后首尾相接便是最终输出的md5值。

那么什么是扩展攻击?简单来说,就是一种改变初始幻数后对我们可控的输入信息再进行md5的攻击。可想而知,这样计算出的md5值必定是已知的,也就是可控的。那么这种攻击的核心便是改变初始幻数,作为攻击者,我们不可能改变服务端的md5算法,也就是说真正的初始幻数是实际上不可变的。但是攻击者通过提交与服务器返回的哈希值相对应的明文来使服务器端的幻数变为之前服务器返回的哈希值,并在后面衔接自己的内容来使服务器下一次返回的哈希值成为已知。

0x04 攻击实现

我们实现这一攻击就需要一个攻击辅助脚本,下面是作者自己调试好的一个例子(调了一万年)。附有详细使用方法和注释,所以不进行说明。

本文md5实现脚本脚本来自:http://blog.csdn.net/adidala/article/details/28677393(原md5实现脚本有不少问题,会导致输出的md5值错误,这些错误在攻击辅助脚本中已被修复)
攻击辅助脚本(最好理解了原理再来看脚本):

若有需要回头加一个自动提交猜解长度的脚本。

0x05 一次攻击实例

没有找到好的例子,就拿一道ctf题为例,是PCTF的一道web题。现被收录于jarvisoj,题目名是“flag在管理员手里”。

直接从看到哈希值开始。

通过一些手段拿到的网站源码如下

分析一下源码,$role将一个序列化的cookie反序列化后读取,值得一提的是反序列化函数对单一字符串只会进行到第一个分号结束,后面有什么一概不管。也就是说类似于:

会把$role赋值为guest,后面的x就当没看见。要获得flag,这段cookie的开头必定是:

但是我们注意到在计算MD5之前有一个对cookie字符串的反序,所以正确的md5值的明文应该是这样的:

这道题最终猜解出来$salt的长度为12字节,假设现在我们已知其长度为12字节,利用脚本计算扩展:

其中xxx为我们不知道的salt,有效输出为msg,我们现在获得了扩展字符串。

显然原明文补位后的区块数为1,所以我们现在利用脚本计算payload中的MD5:

这里仍要注意反序问题,我们输入的任何内容都会被反序计算,所以这里的extension是反序的。

构造如下payload:

这里还有一个注意点,就是中间的填充字符串的顺序必须是反的,这样一来在整个字符串反序后对于md5来说才会变成正确的填充。

发包,成功获得flag。

Leave a Reply

Your email address will not be published. Required fields are marked *