又是做xy学到的。xy真是每一题都在学习。

md5加密

我们先聊聊md5加密。

加密过程

我们会发现在md5加密后总是会输出一个128位的字符串,不管是多大的数据,因为md5是一个有损加密,这也就导致了我们认为md5加密不可逆。但是可以碰撞。
至于其加密流程我直接先贴个图

填充

加密的第一步就是填充。在进行md5加密时第一步就是填充,加密数据小于448位的数据会先先填充到448位填充的字符就是16进制的\x80\x00\x00\x00\x00。填充到448位最后的再写入64位的内容代表原数据的长度。补充到512位。如果数据大于512就补充道1024位。如果等于512也要补充到1024

分组加密

md5的加密是将数据按512一组分成多组与初始的幻数加密

1
2
3
4
0x67452301
0xEFCDAB89
0x98BADCFE
0x10325476

初始幻数与第一组进行一系列复杂的运算,得到第二组幻数,第二组幻数再与第而做的数据进行运算,以此类推到最后一组得到的四个最终的幻数进行下面的操作就是得到的md5值
假设最后得到的4组幻数都是0xabcdefgh
那么首先两两分组
得到
1
2
3
4
ab cd ef gh
ab cd ef gh
ab cd ef gh
ab cd ef gh

再逆序拼接
1
ghefcdabghefcdabghefcdabghefcdab

这就是最终的md5值

哈希扩展攻击的原理

我们先看一下下面的demo

1
2
3
echo md5($flag)
if($_POST['md5']===md5($_flag.$_GET['data']))
echo $flag

上面的demo给出了flag的md5值但是我们都知道md5是不可逆的,所以我们无法直接推导出flag。
那么我们来看一下if语句
1
if($_POST['md5']===md5($_flag.$_GET['data']))

我们可以看到我们可以控制字符与$_flag进行拼接,之后再与我们输入的md5值进行比较。
那么上面就出现了哈希扩展漏洞。我们都知道md5再加密直接回进行填充,而前一组的加密的结果会被当成后一组的幻数进行再一次的加密。
那么我们如果用输入的data来使得flag被正确填充到512位,再加密md5($_flag.$_GET['data'])时第二组的幻数不就是第一组加密的值即flag的md5经过逆序的值吗?,那么我们知道了flag的md5值,即知道了第二组的幻数那么我们输入的md5值只要是以第二做的幻数为初始幻数加密的数据不就可以通过了吗?

流程

我们要先知道$flag的长度(因为我们再对字符进行填充时最后的64位要为),不知道可以多次尝试来爆破。然后再进行填充如输入以下字段填充。

1
8000000000000000000....lalalalala

而lalalala就是第二组的内容。
那么我们接下来就是利用第一组的加密结果即泄露的md5值的逆序来加密第二组数据。最终我们得到的加密结果就是md5($_flag.$_GET['data'])这个结果。

脚本

上面的流程我们是不可能手打的我们可以使用脚本进行攻击
可能是因为环境原因我无法从GitHub上拉取hashpump,所以我这里用的是下面这个脚本
hash-ext-attack
流程就是按脚本提示的输入,攻击的条件就是已知长度,已知md5值,并且拼接进行比较