哈希长度拓展攻击
五一假期在干嘛?相信有很多小伙伴(其实是大表哥)开始了ISCC之旅,不知道为了在这个“动态分数”机制环境下得到更多的分数,大家的肝还好不好呢?
信息安全与对抗技术竞赛(ISCC:Information Security and Countermeasures Contest),于2004年首次举办,是教育部、工业和信息化部主办的第一个国家级信息安全技术竞赛,初入茅庐的我(小菜鸟)也去水了水,苦战许久,开始总结与学习,于是就写这篇文章,第一次写博客,不足之处很多,希望大表哥们纠正。
在做题的时候,有一道题很有趣,web250的hash长度拓展攻击,这个方法原理不难,在几年前已经出现了,在2009年,Thai Duong 与 Juliano Rizzo发布了ASP.NET的padding oracle攻击,同时还写了一篇关于Flickr API签名可伪造的paper,Flickr API签名这个漏洞,实际上用的是MD5 Length Extension Attack,钻研了一个多星期的各位大表哥写的文章以及hash加密的具体算法,我想谈谈自己理解,并且分享一份自己写的利用代码。
首先先看一张图片
这有一幅图,感觉能把核心思路与过程充分地体现出来,不过在此之前我们应该了解MD5加密的大体步骤:填充与使用上一次计算出来的幻值进行四轮运算。
我们输入一个需要加密的字符的时候,该算法会对字符串进行分组,每448位(bit)也就是56字节一组,当不足448位时需要进行补充,我们先说一下448位的来源。
每一个进行四轮运算的字符串,长度为64字节也就是512位,其中有8个字节是记录信息的长度(长度的意思是信息是多少二进制位),那么容纳信息的就只要56字节。假设我们对一个10个字节(80bit)的字符串A进行填充至64字节
第一步,需要查看该信息是否小于等于56字节,即length(A)%64<=56?这里单位是以字节为单位。
第二步,对不足56字节的字符串进行填充,那么对A来说需要填充46字节,规定第一个字节必须填充%80,其余的填充%00,那么A填充的内容为:
%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00
这里面有45个%00
填充完毕。
随后我们需要填充摘要信息,也是信息的长度,A有10字节,也就是80bit,换算成16进制为0x50,那么后面需要填充的8个字节为:
%50%00%00%00%00%00%00%00
为什么不是%00%00%00%00%00%00%00%50呢?
因为MD5是小端存储,也就是低地址存储高位字节。
对于小端储存,比如0x1234=>34120000(假设32位储存长度)。
至此我们需要处理的64位数据已经构造成功,这时候需要上一次MD5运算得到的ABCD来作为本次MD5运算的初始序列ABCD。
在这里我们解释一下初始序列,对于第一次运算来说会默认四个32位初始序列
A=0x01234567
B=0x89abcdef
C=0xfedcba98
D=0x7654321
它们被称为链接变量
将上面四个变量分别赋值到a,b,c,d变量中
然后进行主循环(四轮),每一轮都很相似。第一轮进行16次操作。每次操作对a,b,c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上a,b,c或d中之一。最后用该结果取代a,b,c或d中之一。这样新的链接变量诞生了,如果还需要进行加密,那么就作为下一次加密的初始序列,如果结束的话,那么就把a,b,c,d连接在一块。
理论说完了,我们来看一下题目:
题目直接给了源代码,简单的审计题目比较容易做
我们我们可以知道,如果enc($username) === $_COOKIE['verify']那么就setcookie的verifty为md5($key+'guest')可以知道未知的secret是$key,而且我们从下一语句可以知道,$key的length:setcookie("len", strlen($key), time()+60*60*24*7);
因此这个题目已经分析出来了
已知的是:$key的length
md5($key+'guest')
$username里要有admin子串
那么第一步上bp抓包找一下需要的数据
可以发现 verify=78cfc57d983b4a17e55828c001a3e781 len=46
使用hashpump
我们把
payload:guest%80%00%00%00%00%98%01%00%00%00%00%00%00admin
verify:5f585093a7fe86971766c3d25c43d0eb
进行repeater
成功拿到flag
对于hash长度拓展攻击,挺感兴趣的,之后看了很多资料,按着自己的理解写了一个脚本,虽然写出来了,对md5加密的算法理解了,但是不知道在md5四轮运算中,参与运算的固定的16进制为什么是这几个,还是应该好好研究。
对于这个的用法,我简单的说一下
python expliot.py 作为初始序列的md5值 最为第二轮md5运算的字符 上一次的md5运算前的padding的时候%80前面字符串的二进制位数
推荐一篇很棒的文章 Everything you need to know about hash length extension attacks » SkullSecurity