MD5加密及Hash长度拓展攻击通俗易懂
Posted p0pl4r
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MD5加密及Hash长度拓展攻击通俗易懂相关的知识,希望对你有一定的参考价值。
先放一个简单点的利用了Hash长度拓展攻击的题目
if($COOKIE["getmein"] === md5($secret . urldecode($username . $password))) { echo "Congratulations! You are a registered user. "; die ("The flag is ". $flag); }
在理解Hash长度拓展攻击之前需要大致了解下MD5的加密原理
MD5加密过程
1.数据分组
在MD5加密算法中,将一个字符串分为若干个大小为512位的分组,而每一个分组又可分为16个子分组m0~m3{A},m4~m7{B},m8~m11{C},m12~m15{D}(这里的ABCD在稍后的Hash计算中会讲解到)。
2.数据填充
MD5值的计算都必须以512位为一组进行计算,所以就必须使得填充后的数据 [原字符串+填充100...+原字符串总长(64位)],刚好等于512的倍数。比如:
$str = "test",十六进制表示为0x74657374
数据填充后为0x74657374800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000
中间的80...H=10000000...B,最后四字节也就是2000000000000000代表前面‘test‘的长度,也就是4×8位=32D=20H。
如下图所示(图取自另一篇博客,忽略水映啦~~)
下面说一下具体的一些计算:在MD5中有四个32位的被称作链接变量的整数参数,是如下设置(这个ABCD是初始的固定的值,即初始向量):
A=0x67452301,
B=0xefcdab89,
C=0x98badcfe,
D=0x10325476。
通过小端规则转换A{m3~m0}B{m7~m4}C{m11~m8}D{m15~m12}就是MD5值:0123456789abcdeffedcba9876543210。即为初始向量的MD5值,记为md5_0。
之后有四个非线性函数,将字符串和那四个链接变量经过一系列的复杂运算(具体运算规则请自行查阅),算出一组新的A,B,C,D的值,公式即$md5_1=MD5($md_0+$ex_str_0);如果消息小于512,也就是只需要计算一次,这时候的$md5_1就是最终的MD5值;如果消息大于512的话,就用第一次得到的$md5_1代入公式$md5_2=MD5($md_1+$ex_str_1)对第二个512位数据进行运算...如此迭代即可。
这种加密可能导致的问题
思考,如果是这种情况,由两个字符串组成一个字符串($str=$a+$b),第一个字符串($a)不知道也不可控,只可控第二个字符串($b),但知道第一个字符串($a)的MD5值和长度,这时候我将第二个字符串精心构造一下,便可以算出合成的字符串$str的MD5的值。
如何精心构造,且看下文。
正向计算
假如第一个字符串$a=“test”,十六进制表示0x74657374
构造第二个字符串首先手动将$str补成一个标准的可以直接计算的512位
$str=0x74657374800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000
这样子,这时候再在后面追加一个0x746573748
$str=0x74657374800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000746573748
这时候再将$str大于512位,程序会自动先将这串数据补为1024位,补充完如下
$str=0x7465737480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000074657374800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000
这时将$str分为两部分
74657374800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000
和
74657374800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000
这时候程序计算前一部分的ABCD的值,由于和之前算的test的数值是相同的所以
A=0xcd6b8f09
B=0x73d32146
C=0x834edeca
D=0xf6b42726
对应的MD5:098f6bcd4621d373cade4e832627b4f6
到了第二部分,第二部分的计算是用的第一部分的ABCD去计算,计算新的ABCD如下
A=0x226359e5
b=0x99df12eb
C=0x6853f59e
D=0xf5406385
最后算出来的MD5:e5596322eb12df999ef55368856340f5
按照给定条件计算一遍(此即MD5的Hash长度拓展攻击原理)
我们知道的条件
1.$a的MD5(098f6bcd4621d373cade4e832627b4f6)
2.$a的长度=4
3.$b我们可以任意控制
由1的MD5我们可以逆推算出其ABCD的值
A=0xcd6b8f09
B=0x73d32146
C=0x834edeca
D=0xf6b42726
我们构造$b=‘x80x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20x00x00x00x00x00x00x00‘+‘test‘
此时$str如下,由于不知道$a,我们假设$a="aaaa"(任意构造,但需满足条件已知长度为4)
那么假设内容就为$str=‘aaaa‘+‘x80x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x20x00x00x00x00x00x00x00‘+‘test‘
好了我们脑补一下程序计算str的过程
1.由于大于512位,先补全为1024位,
2.将其分为两部分
3.计算第一部分的ABCD的值
4.再用第一部分算出来的ABCD拿来算第二部分的值。
这里由于第一部分的ABCD我们可以逆推出来,我们可以直接跳过前三部分直接进行第四部分的计算,只需要将标准的MD5的源码里面的初始的ABCD的值改为逆推出来的那个值。
我们用假的初始的ABCD计算一下
0x74657374800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002002000000000000
的MD5,发现是e5596322eb12df999ef55368856340f5,和上面正向计算出来的一样!
这里可能需要反复理解一下,有点绕,但这就是真正理解Hash长度拓展攻击原理的临门一脚,过了便不难。
再结合一开始的那道题目来理解下吧,题目中,需要满足条件$COOKIE["getmein"] === md5($secret . urldecode($username . $password))才能获取到flag,但由于$secret不知道也不可控,所以就需要将我们构造的(512<位数(str)<1024)数据中第一个512位数据计算得到的md5值来取代$secret(即用第一向量md5_1取代初始向量md5_0/$secret),而usename和password仍旧是第一个512位数中的值,再将$COOKIE[‘getmein‘]改为第二个512位拓展数据得到的MD5值即可(即将第二向量md5_2取代第一向量md5_1)。我说过很好理解的叭~^^
总结
存在此类缺陷的加密算法主要有:md和sha系列等等
防范:1. Hash(secret, Hash(message))
2. HMAC算法 HMAC(secret||padding)=H(secret||H(secret||padding))
3. 交换secret和padding的位置,即MAC(padding||secret)
利用工具:主要有hash_dump,hash_extender,还有一些大佬的脚本,相关博客很多,自行学习吧。
任何疑问可留言,看到回复~^^
以上是关于MD5加密及Hash长度拓展攻击通俗易懂的主要内容,如果未能解决你的问题,请参考以下文章