hash长度扩展攻击

ISCC时间线好长,课业繁忙,江湖再见,告辞!

image

五一假期在干嘛?相信有很多小伙伴(其实是大表哥)开始了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加密的具体算法,我想谈谈自己理解,并且分享一份自己写的利用代码。

0x01 原理

首先先看一张图片
这有一幅图,感觉能把核心思路与过程充分地体现出来,不过在此之前我们应该了解MD5加密的大体步骤:填充与使用上一次计算出来的幻值进行四轮运算。
image

我们输入一个需要加密的字符的时候,该算法会对字符串进行分组,每448位(bit)也就是56字节一组,当不足448位时需要进行补充,我们先说一下448位的来源。
每一个进行四轮运算的字符串,长度为64字节也就是512位,其中有8个字节是记录信息的长度(长度的意思是信息是多少二进制位),那么容纳信息的就只要56字节。假设我们对一个10个字节(80bit)的字符串A进行填充至64字节
第一步,需要查看该信息是否小于等于56字节,即length(A)%64<=56?这里单位是以字节为单位。
第二步,对不足56字节的字符串进行填充,那么对A来说需要填充46字节,规定第一个字节必须填充%80,其余的填充%00,那么A填充的内容为:

1
%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个字节为:

1
%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位初始序列

1
2
3
4
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进行大端储存,并且在一块。

0x02 一道CTF题目

理论说完了,我们来看一下题目:
image

题目直接给了源代码,审计的题目比较好做走
我们我们可以知道,如果enc($username) === $_COOKIE[‘verify’]那么就setcookie的verifty:为md5($key+’guest’)可以知道未知的secret是$key,但是我们从下一套语句可以知道,$key的length:setcookie(“len”, strlen($key), time()+606024*7);
因此这个题目已经分析出来了

已知的是:

1
2
3
$key的length
md5($key+'guest')
$username里要有admin字串

那么第一步上bp抓包找一下需要的数据
image
可以发现 verify=78cfc57d983b4a17e55828c001a3e781 len=46
使用hashpump
image
我们把

1
2
payload:guest%80%00%00%00%00%98%01%00%00%00%00%00%00admin
verify:5f585093a7fe86971766c3d25c43d0eb

进行repeater
image
成功拿到flag

0x03 扩展

对于hash长度拓展攻击,挺感兴趣的,之后看了很多资料,凭着自己的理解写了一个脚本,虽然写出来了,对md5加密的算法理解了,但是不知道这四轮参与运算的固定的16进制为什么是这几个,还是应该好好研究。
image
对于这个的用法,我简单的说一下

1
python expliot.py 作为初始序列的md5值   最为第二轮md5运算的字符  上一次的md5运算前的padding的时候%80前面字符串的二进制位数

脚本我放在我的github

0x04 后记

之前一直在他大神们托管在github里的项目,这是第一次使用github
因为是在学习的时候写的这个利用脚本,注释挺多的。

推荐一篇很棒的文章 https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks

-------------本文结束&感谢您的阅读-------------