对强网杯2018“Web签到”的思考

Author Avatar
kabeor 3月 29, 2018

对强网杯2018“Web签到”的思考

题目地址: http://39.107.33.96:10000/

题目共分为三层

  1. PHP处理0e开头的md5哈希字符串的缺陷
  2. MD5函数不能处理数组
  3. 字符串md5碰撞

    第一层

    mark
    我们查看源码,可以找到
    mark
<!--
if($_POST['param1']!=$_POST['param2'] && md5($_POST['param1'])==md5($_POST['param2'])){
die("success!");
}
-->

这里PHP在处理哈希字符串时,利用”==”来对哈希值进行比较,把每一个以”0E”开头的哈希值都解释为0,因此如果两个不同的密码经过哈希以后,其哈希值都是以”0e”开头的,那么PHP将会认为它们都是0。

原理

在PHP中,e可以指幂,因此

0e123456   等价于   0*10^123456

0乘任何数等于零,因此0e开头的md5全部等于0,也就做到了这里的

md5($_POST['param1'])==md5($_POST['param2']

这里我使用的是

s878926199a md5: 0e545993274517709034328855841020
s155964671a md5: 0e342768416822451524974117254469

第二层

mark
查看源码
mark

<!--
if($_POST['param1']!==$_POST['param2'] && md5($_POST['param1'])===md5($_POST['param2'])){
die("success!");
}
-->

这里变成了===操作符,严格等于,因此我们无法利用0e
因此我们需要符合的条件为构建两个参数 使得他们类型或者值不相同 但哈希值相同

这里我们考虑到,PHP的md5函数用法如下

md5(string,raw)

string 必需。规定要计算的字符串。

raw
可选。规定十六进制或二进制输出格式:
TRUE - 原始 16 字符二进制格式
FALSE - 默认。32 字符十六进制数

返回值: 如果成功则返回已计算的 MD5 散列,如果失败则返回 FALSE。

因此,如果md5中的参数不是字符串(string),则会返回null
所以如果我们传入两个值不同的数组,就会出现

null===null

符合条件

使用Burpsuite抓包,传数组
mark

第三层

mark
源码
mark

<!--
if((string)$_POST['param1']!==(string)$_POST['param2'] && md5($_POST['param1'])===md5($_POST['param2'])){
die("success!);
}
-->

这次PHP将两个参数强行转成string.

没有漏洞,我们只能考虑md5碰撞

原理(个人理解,如有错误请指正)

2005年王小云提出了md5哈希碰撞,公式如下

f(f(s, M), M') = f(f(s, N), N')

先将明文进行64bit分组,不足的则填充,这样它的长度将是64字节的倍数。

接下来将其分为单个的64bit字节块M0, M1, …, Mn-1。

而md5的hash是由16字节的序列s0, …, sn来计算。计算规则为:si+1 = f(si, Mi) ,(i为角标), f是一个固定函数。s0是初始化向量,sn是最终状态,即计算的md5 hash

对于给定的初始化向量s,找出两组M,M’和N,N’,使得f(f(s,M),M’)= f(f(s,N),N’) ,重要的是这里不仅仅适用于标准初始化矢量s0,而对于任何初始化矢量s都适用。

也就是说对于两个不同的消息分组 M、N,s 相同,经过两次 f 函数后得到的结果是一样的。

因此可以找到任意长度的对文件,除了文件中间的128个字节,它们是相同的,而且它们具有相同的MD5散列。

mark
为了便于理解,自己做了个图

m0 m1经过两次f函数所得的hash是相同的

如果对这个有兴趣,推荐下面的网站

md5相关知识: http://www.unixwiz.net/techtips/iguide-crypto-hashes.html
可视化md5碰撞演示: http://www.links.org/?p=6
用相同的MD5散列创建两个PHP文件: https://natmchugh.blogspot.com/2014/10/how-i-made-two-php-files-with-same-md5.html
Are there two known strings which have the same MD5 hash value?: https://crypto.stackexchange.com/questions/1434/are-there-two-known-strings-which-have-the-same-md5-hash-value

我们使用md5碰撞软件fastcoll生成两个md5相同的文件,经url编码后上传即可得到flag。

From https://kabeor.github.io/对强网杯2018“Web签到”的思考/ bye

This blog is under a CC BY-NC-SA 4.0 Unported License
本文链接:https://kabeor.github.io/对强网杯2018“Web签到”的思考/