hash扩展学习

MD5的运算流程

下面大致了解一下MD5的运算流程:

  • 1.填充消息:首先,被MD5的字符串长度 ≡ 56 mod 64,即填充后的长度比64的整数倍少8;即使长度满足了要求,仍然需要填充;填充的第一位为0x80,剩下填充0x00;
  • 2.填充长度:用8字节表示填充前的长度,附在第一步所得结果之后;8字节的第一位的为填充前的长度的bit值,剩下七位的值为0x00;
  • 3.分组:以64位为一组进行分组;
  • 4.进行复杂的数学变化:第一组使用默认的registers值进行复杂的数学变化,之后产生一组新的registers值供下一组复杂的数学变化来调用

其中,registers为:

MD5的中间结果和最终结果保存在4字节的缓冲区中,缓冲区用4个4字节的寄存器(A,B,C,D表示),这些寄存器初始化为下列32bit的16进制整数:

  • A = 67452301
  • B = EFCDAB89
  • C = 98BADCFE
  • D = 10325476

大致先了解这么多……

hash长度扩展

hash长度扩展的意思就是:

若知道字符串salt的长度,以及sha1(salt)的值,那么就可以得到sha1(salt+填充数据+data)的值;这里填充数据为salt进行hash运算时填充的数据;data为任意字符串

下面分析一道实验吧里的hash长度扩展的题目:

题目地址:http://ctf5.shiyanbar.com/web/kzhan.php/index.php

首先抓包,将source=0改成source=1,得到源码;这里就不放源码了,题目的意思就是:

已知:

1.lenth($secret) = 15
2.md5($secret+'adminadmin') = 571580b26c65f306376d4f64e53cb5c7

求:

md5($secret+'adminadmin'+任意数据)

则按照上述MD5运算流程:

  • 1.填充消息:由于$secret+'adminadmin'的长度为25,则需要填充31位,第一位为0x80,剩下三十位为0x00;
  • 2.填充长度:填充消息前的长度为25,则填充的值第一位为25*8=200bit,即16进制的0xc8,后面七位为0x00;

则填充之后的数据为:

\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\xc8\x00\x00\x00\x00\x00\x00\x00

如果将填充之后的数据后面加上字符串”dawn”,那么进行MD5运算时填充后会分为两组,第一组得到的registers的值即为md5($secret+'adminadmin'),之后再与第二组进行“复杂的数学运算”,即可在不知道$secret的情况下得出MD5结果

使用hashpumpy库可以很方便的计算出扩展后的MD5值,但是不知出了神马问题安装失败。。在网上找到一个脚本,计算出扩展后的MD5值:

在提交数据时,要将填充的16进制数据进行urlencode

hash长度扩展其他形式

Jarvis OJ中的一道题:

只有管理员才能获得flag,你能想办法获得吗?

抓包后,发现:

s%3A5%3A%22guest%22%3B进行url解密,得到s:5:"guest";,即序列化后的字符串guest

则首先想的是将guest改成Admin,不过没用;注意到了hsh,将其去掉后发包,显示出了错误信息:

进行扫描,发现有/index.php~这个文件,访问后下载下来一个文件,将其改名为.index.php.swp放到linux下恢复,得到源码

代码的意思为,要想得到flag,就要满足:

1.使role的值反序列化后为`admin`

2.使hsh===md5($salt.strrev($_COOKIE["role"]))

其中,strrev()函数的作用为反转(逆序)原字符串,.即为拼接字符串

再看看我们已知的信息:

md5($salt+';"tseug":5:s') === 3a4727d57463f122833d9e732f94e4e0    

$salt以及它的长度是未知的;那么,要如何构造cookie中的role和hsh的值呢?

首先,应该确定构造的role:以's:5:"admin";'开头,以's:5:"guest";'结尾。

因为反序列函数存在00截断,则将's:5:"admin";'放开头;逆序后求MD5,因此以's:5:"guest";'结尾,这样可以利用已知的md5($salt+';"tseug":5:s')进行扩展

由于不知道$salt长度,因此需要进行爆破。将上面那道题的脚本改了两天没成功。。。。。后来找工具又出现一大堆问题。。。。。后来终于在我的虚拟机上装上了hash_extender!!!服!

安装过程记录下:

1.安装OpenSSL开发包: apt-get install -y libssl-dev
2.cd到下载的hash_extender目录下,执行make命令

输入命令:

./hash_extender --data ';"tseug":5:s' --signature 3a4727d57463f122833d9e732f94e4e0 --format md5 --append ';"nimda":5:s' --secret-min 1 --secret-max 43

跑出来是这样的:

虽然得到的MD5值都一样,但填充的不一样…不知道怎么回事

写了个脚本,写完才发现这个方法没什么用…因为我看wp,知道salt长度为12,然后选取相应的填充用脚本跑…如果要是比赛,那就得一个个试了…….

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
new_list = input('Input: ')
n = 2 #平均分成n个
new_list = [new_list[i:i + n] for i in range(0, len(new_list), n)]

fin_0 = new_list[:12]
fin_1 = new_list[12:-12]
fin_2 = new_list[-12:]

fin_0.reverse()
fin_1.reverse()
fin_2.reverse()

s = ''
for i in fin_2: # admin在前
s = s + chr(int(i, 16))
for i in fin_1: # 填充
i = '%' + i
s = s + i
for i in fin_0: # guest在后
s = s + chr(int(i, 16))

print(s)

又累个半死也没有安装好hashpumpy…以后虚拟机多了再弄,心累.

参考文章:

https://www.freebuf.com/articles/web/69264.html
https://www.jianshu.com/p/17e6dcf2c79c
https://err0rzz.github.io/2017/09/18/hash长度扩展攻击