fi3ework's Studio.

hash长度攻击

2018/02/24

Hash长度扩展攻击


在ctf题里遇到一个hash长度攻击的题

关键代码:

1
if ($COOKIE["getmein"] === md5($secret . urldecode($username . $password)))

这里的secret我们不可知 但是我们知道它的长度 这就是在设计了hash扩展长度攻击


介绍一下MD5算法

Image

上面的图示是转载别人博客上的

MD5会把原数据分成512为一块的许多块,最后一块加上64字节来表示他的长度,一共构成512*n个字节然后再对这N个512数据块进行N次加密计算

举个例子


比如计算字符串“test”

十六进制0x74657374

二进制0b1110100011001010111001101110100

md5后面运算过程都是需要512比特为一组来进行运算,先说一下简单的数据比较少 不存在分组的时候的填充,首先512比特的末尾64比特是存放原明文消息的长度,512比特开始是明文数据紧接着明文后填一位1(2进制),其余全是0,假设我明文就一个字符串‘test’那么填充就是0x74657374800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000

最后的四字节 2000000000000000 代表’test’长度

将补位后的数据进行一次复杂的运算,计算出

A=0xcd6b8f09

B=0x73d32146

C=0x834edeca

D=0xf6b42726

因为数据小于512位 将ABCD通过小端规则转换就是MD5值

如果输入不是test 而是大于512小于1024就要算两次,大于1024小于1536就要算3次

用前面一次的512的ABCD值来计算后面一次512ABCD值,直到最后一次数据小于512位

那么 两个字符串组成一个字符串($str=$a+$b),第一个字符串不可知也不可控,只可控第二个字符串(b),同时知道第一个字符串(a)的MD5值和长度,把第二个字符串构造一下,就可以算出(str)的MD5值


假如$a = “test”,为了方便转为十六进制0x74657374

构造第二个字符串首先手动把$str补为一个标准的可以直接计算的512位 就像上面的例子的

然后我们添加一个0x746573748

使得str大于512小于1024位 补充之后是

1
$str=0x7465737480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000074657374800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000

我们可以计算前面一部分的ABCD的值,和之前test计算值相同

第二部分就用第一部分的ABCD再去计算 算出来是:

1
e5596322eb12df999ef55368856340f5

我们知道的条件:

a的MD5值 a的长度 = 4 b为我们控制

由第一个可以得到ABCD(逆算) 我们构造

1
$b='\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00'+'test'

str里的a我们不知道 假设四个长度a=“aaaa”

1
$str='aaaa'+'\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00'+'test'

我们再继续算str

因为大于512位,补为1024位,分为两个部分,计算第一个部分ABCD值,再用第一部分算出来的ABCD算第二部分

因为第一部分ABCD我们可以逆推出来,我们可以直接进行用第一步ABCD算第二部分的值,只需要把标准MD5值改为逆推的值