Hash长度拓展攻击

Hash长度拓展攻击

参考:

https://www.0x002.com/2020/%E6%B5%85%E8%B0%88HASH%E9%95%BF%E5%BA%A6%E6%8B%93%E5%B1%95%E6%94%BB%E5%87%BB/

https://xz.aliyun.com/t/10602?time__1311=CqjxRGiteiq05DK5YIx7Ki%3DoQet6QHW4D#toc-1

https://ciphersaw.me/2017/11/12/hash-length-extension-attack/#0x00-%E5%89%8D%E8%A8%80

hash长度拓展攻击,概括一下就是由于hash的生成机制使得我们可以人为的在原先的明文基础上添加新的拓展字符,从而使得原本的加密链变长,进一步控制加密链的最后一节,使得我们得以控制最终的结果。

这里首先给出一个相关demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
include "flag.php";
$secretKey = 'xxxxxx'; #xxx为未知内容,但长度已知为6。
$v1 = $_GET['str'];
$sign = $_GET['sign'];
$token = md5($secretKey.$v1);
if($v1 === 'test') {
die($token); #token=2df51a84abc64a28740d6d2ae8cd7b16
} else {
if($token === $sign) {
die($flag);
}
}
?>

在这个例子中,我们需要使得变量$token与我们输入的sign参数满足一致才会输出flag。

而由于我们无法知道变量$secretKey的内容,所以无法得到$token的值,故而看似是没有办法获取到flag的死局,而这时便轮到我们的拓展攻击来大显身手了。

md5算法过程

MD5加密流程

md5算法是512位一组的,也就是64字节一组,见下面的例子:

由64个a和3个b组成,这里的64个a其二进制长度为512位,已经符合一个md5分组,后面的bbb是下一个分组了。

对于md5算法,我们需要将原始数据分块处理,以512个二进制数据为一块。”最后“一块的处理分为以下两种情况:

  • 明文数据的二进制数据长度<=448,填充padding(无意义占位)数据使其长度为448,再添加原始明文数据的二进制长度信息(64位)使其长度为512位即可。
  • 448<明文数据的二进制数据长度<=512,填充padding数据至下一块的448位,而后再添加原始明文数据的二进制长度信息(64位)使其长度为512位即可。

情况一:

这里其实64个字符a组成了一个md5分组,剩下的32个字符b作为下一个md5分组,然后需要进行填充。

进行填充的方式就是在二进制下第一个补1,后面的依次补0 。但是在这里咱们是以十六进制形式在010里演示的,而对于十六进制来说,一个十六进制字符对应4个二进制字符,所以对于010里面数据来说,10000000(2)==80(16),补充上去就是:

然后后面依次补0,知道填满448位为止,得到最终补位结果为:

然后还需要补位8个字节,原始明文为64个a和32个b,共96个字符,768位,转换为十六进制就是300。

情况二:

补位就不展示了,跟上面的情况一是同理的。

对于MD5算法来说,有一串初始向量如下:

1
2
3
4
A=0x67452301
B=0xefcdab89
C=0x98badcfe
D=0x10325476

这串初始向量的值是固定的,作为与第一块数据运算的原始向量。

当这串向量与第一块数据块运算之后,得到了一串新的向量值,这串新的向量值接着与第二块数据块参加运算,直到最后一块数据块。

向量运算

而最后的MD5值就是这最后的向量串经过如下转换的结果。

如向量串:

1
2
3
4
A=0xab45bc01
B=0x6a64bb53
C=0x23ba8afe
D=0x46847a62

再进行高低位互换,得到如下数据:

1
2
3
4
01 bc 45 ab
53 bb 64 6a
fe 8a ba 23
62 7a 84 46

最终拼接得到MD5值:01bc45ab53bb646afe8aba23627a8446

回首demo

然后回到先前那个例子:

对于MD5值:2df51a84abc64a28740d6d2ae8cd7b16。我们可以根据MD5与向量互转规则,将MD5转成md5($secretKey + "test")的最终向量值(A’、B’、C’、D’):

1
2
3
4
A'=0x841af52d
B'=0x284ac6ab
C'=0x2a6d0d74
D'=0x167bcde8
例子向量运算过程

这时候我们修改$v1变量的内容为:

1
2
3
"test" + [0x80 + (0x0)*45] + [0x50 + 0x0*7] + "abc"
相当于:
"test" + padding数据 + 长度数据 + "abc"

则上述过程则被延续成下图所示:

延续运算过程

而对于上述运算过程来说,我们知道了倒数第二个向量串的内容和最后一个数据块,这样一来,最终的MD5值我们也可以自己通过MD5算法计算出来了。

利用工具exploit

hash-ext-attack-master

hashpump

hash_extender

https://github.com/iagox86/hash_extender