CTF:PHP MD5函数0E绕过漏洞
CTF:PHP MD5函数0E绕过漏洞作者:高玉涵博客:blog.csdn.net/cg_i时间:2021.6.1 8:43背景昨天参加了一场CTF线上赛,面对行业内的安全强队,比赛成绩相差巨大。通过这次比赛,找到了差距,找到了不足,更增长了知识。子曰:“学而不思则罔,思而不学则殆。”计划将经后每次比赛,解题过程中的困惑、思路、整理后分享出来,以达起到巩固知识,也便于帮助有需要的人。因个人能力所限
CTF:PHP MD5函数0E绕过漏洞
作者:高玉涵
博客:blog.csdn.net/cg_i
时间:2021.6.1 8:43
背景
昨天参加了一场CTF线上赛,面对行业内的安全强队,比赛成绩相差巨大。通过这次比赛,找到了差距,找到了不足,更增长了知识。子曰:“学而不思则罔,思而不学则殆。”计划将经后每次比赛,解题过程中的困惑、思路、整理后分享出来,以达起到巩固知识,也便于帮助有需要的人。因个人能力所限,文中难免会有错误,不妥之处还请批评指正。
赛题源码
本职工作极少接触CTF相关知识,初看此题直接是懵的。代码清晰而简单这里不表,唯一让我困惑的是if($c == md5($c))这一条语句,分析可知当$c==md5($c) 即可拿到Flag。心中诧异:这怎么可能!加密前后的值要相等?逻辑上不通啊!难道要用到md5撞库?这种概率也太小了,假设真的存在这种可能,即使不考虑其巨大的计算量,稍微对加密原理有些常识的人就应知道,世上根本不会存在“加密前后的值要相等”(这还算得上加密码?)我走进了知识盲区,走进了思维的死胡同。
在长时间的懵圈后,我逐渐冷静下来并断定,主办方不可能出道需耗时100年(我电脑的计算力)才能得出的答案的题。直觉告诉我突破口应是md5()这个函数,它可能存在我不知道的漏洞,确定方向后接下来就是对它发起进攻。
MD5算法
首先还是说一下什么是MD5算法,MD5全名消息摘要算法(Message-Digest Algorithm 5),是一种密码散列函数,可以产生一个128位(16字节)的哈希值(hash value),用于确保信息传输的完整一致性,它的基础原理就是将数据预算变为另一固定长度的值。
MD5的特点
长度一致性:任意长度的数据,计算出来的哈希值长度都是固定的128位。
不对称性:从原数据计算哈希值十分容易,但是知道哈希值去碰撞原数据十分困难。
MD5算法的基本原理
这里采用网上一个大佬绘制的图。
MD5算法的安全问题
其实不仅是MD5,任何一个hash函数,都有被碰撞的可能,所谓碰撞,就是输入不同的值Value和Value得到相同的hash值,这其实不难证明,MD5生成的hash值是由128位组成的,而它必然是一个有限集合,而我们的输入数据是一个无限集,一个无限集映射到有限集上,必然存在两个或多个无限集中的元素映射到同一有限集元素的情况。
PHP MD5中的安全问题
相等操作符:用来比较两个值,测试其相等性。
PHP中有两个相等操作符“==”和“===”。$a == $b,如果类型转换后$a和$b相等,则输出true。$a === $b,如果$a和$b相等,并且类型也相同,则输出true。
PHP是弱类型语言,所以有时会根据引用变量时所处的环境,将变量自动转换为最适合的类型。下面给出例子:
$total = “45 fire engines”;
$incoming = 10;
$total = $incoming + $total; // $total = 55
因为最前面的$total字符串以整数值开头,所以计算中就使用了这个值。如果数学计算中用到包含e或E(表示科学计数法)的字符串,这个字符串将作为浮点数进行计算。
有了上述知识我们就可以通过构造特别参数,将原本不相等的if判断相等。原理:在进行“==”判断的时候,会先将字符串类型转化成相同再比较。转换的规则为,若该字符串以合法的数值开始,则使用该值,否则其值为0。因此,根据这一点,可以遍历出一个字符串,其MD5加密前后都是'0e'开头且后面纯数字,这样就能保证值是相等。
Python写的暴库代码(注:2020.6.4修改,原我写的多进程代码存在BUG,这里引用了网上的一段代码)
import hashlib
def md5_enc(s):
m = hashlib.md5()
m.update(str(s).encode('utf-8'))
return m.hexdigest()
if __name__ == '__main__':
result = []
for i in range(0, 9999999999):
i = '0e' + str(i)
enc = md5_enc(i)
print(i+" md5 is "+enc)
# md5值前两位为0e
if enc[:2] == "0e":
# md5值0e后为纯数字
if enc[2:].isdigit():
result.append(i)
print("Got Result:"+i)
break
跑了40分钟得到一个值:0e215962017
MD5 == 0e291242476940776845150308577824
构造URL:http://1.1.1.1/2.php?a=1&b=0&c=0e215962017,成功取得FLAG。如下图。
CTF意义所在
CTF题都是由业内专家命题,往往凝聚着他们多年积累出来的技能,是信息安全基本概念、攻防技术、技巧浓缩和提炼。能够给不能层次的人在技术上带来提高。除此之外,高质量得CTF题都没法直接使用现成工具解出,一般需要在理解基本原理的基础上,自己编写代码来求解,这个过程会加深和巩固计算机基础知识,通过CTF大赛和国内外强队比拼,增长了知识,开阔了视野,提升了能力。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)