[BJDCTF2020]Easy MD5

打开是一个提交的页面,随便提交了点东西,发现没有啥回显,开始抓包。

发现了hint.是一个md5类型的sql注入。

 

select * from 'admin' where password=md5($pass,true)

突破点在md5($pass,true)这里,先来看看md5函数的用法:

 

可以看到这里的raw参数是True,意为返回原始16字符二进制格式。

也就是说如果md5值经过hex转成字符串后为 'or'+balabala这样的字符串,则拼接后构成的SQL语句为:


select * from `admin` where password=''or'balabala'

 当'or'后面的值为True时,即可构成万能密码实现SQL注入,这里我们需要知道的是MySQL的一个特性:

在mysql里面,在用作布尔型判断时,以1开头的字符串会被当做整型数。

要注意的是这种情况是必须要有单引号括起来的,比如password=‘xxx’ or ‘1xxxxxxxxx’,那么就相当于password=‘xxx’ or 1 ,也就相当于password=‘xxx’ or true,所以返回值就是true。

当然在我后来测试中发现,不只是1开头,只要是数字开头都是可以的。
当然如果只有数字的话,就不需要单引号,比如password=‘xxx’ or 1,那么返回值也是true。(xxx指代任意字符)

select * from `admin` where password=''or'1abcdefg'    --->  True
select * from `admin` where password=''or'0abcdefg'    --->  False
select * from `admin` where password=''or'1'           --->  True
select * from `admin` where password=''or'2'           --->  True
select * from `admin` where password=''or'0'           --->  False

只要'or'后面的字符串为一个非零的数字开头都会返回True,这就是我们的突破点。

1、ffifdyop,这个点的原理是 ffifdyop 这个字符串被 md5 哈希了之后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是 ‘ or ‘6,而 Mysql 刚好又会吧 hex 转成 ascii 解释,因此拼接之后的形式是

2、ffifdyop,该字符串md5加密后若raw参数为True时会返回 'or'6<trash> (<trash>其实就是一些乱码和不可见字符,这里只要第一位是非零数字即可被判定为True,后面的<trash>会在MySQL将其转换成整型比较时丢掉)

select * from 'admin' where password='' or '6xxxxx'

等价于 or 一个永真式,因此相当于万能密码,可以绕过md5()函数。

成功构成SQL注入,我们在本题直接输入ffifdyop即可进入下一关

 查看源码

 这个考察的是PHP md5弱类型比较

正经做的话,直接可以利用数组来绕过,构造 ?a[]=1&b[]=2 即可,由于 md5 函数哈希数组会返回 NULL,因此只要传两个不同的数组即可绕过限制。此外,php 0e开头的数字会当做科学计数法解析,因此只要构造两组md5值开头为0e的值即可绕过。

md5(array()) = null
sha1(array()) = null    
ereg(pattern,array()) = null vs preg_match(pattern,array) = false
strcmp(array(), "abc") = null
strpos(array(),"abc") = null

md5()函数无法处理数组,如果传入的为数组,会返回NULL,所以两个数组经过加密后得到的都是NULL,也就是相等的。下面是0e的方法。

php md5漏洞

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

攻击者可以利用这一漏洞,通过输入一个经过哈希后以”0E”开头的字符串,即会被PHP解释为0,如果数据库中存在这种哈希值以”0E”开头的密码的话,他就可以以这个用户的身份登录进去,尽管并没有真正的密码。

即:如果md的值是以0e开头的,那么就与其他的0e开头的Md5值是相等的。

s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
s1502113478a
0e861580163291561247404381396064
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s155964671a
0e342768416822451524974117254469
s1184209335a
0e072485820392773389523109082030
s1665632922a
0e731198061491163073197128363787
s1502113478a
0e861580163291561247404381396064
s1836677006a
0e481036490867661113260034900752
s1091221200a
0e940624217856561557816327384675
s155964671a
0e342768416822451524974117254469
s1502113478a
0e861580163291561247404381396064
s155964671a
0e342768416822451524974117254469
s1665632922a
0e731198061491163073197128363787
s155964671a
0e342768416822451524974117254469
s1091221200a
0e940624217856561557816327384675
s1836677006a
0e481036490867661113260034900752
s1885207154a
0e509367213418206700842008763514
s532378020a
0e220463095855511507588041205815
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s214587387a
0e848240448830537924465865611904
s1502113478a
0e861580163291561247404381396064
s1091221200a
0e940624217856561557816327384675
s1665632922a
0e731198061491163073197128363787
s1885207154a
0e509367213418206700842008763514
s1836677006a
0e481036490867661113260034900752
s1665632922a
0e731198061491163073197128363787
s878926199a
0e545993274517709034328855841020

 

成功进入下一关。

第三部分题目把 == 全部换成了 ===,在这种情况下 0e 大法失效,只能通过传数组来解决。

 最后成功拿到flag。

总结

这里主要考察了md5的数组绕过,哈希碰撞绕过,弱类型绕过和利用二进制md5数据构造SQL注入。

弱等于时(==)可以用0e或者数组绕过

强等于时(===)只能用数组绕过

### 关于BUUCTF中Easy MD5挑战的信息 在处理BUUCTF中的Easy MD5挑战时,主要目标是理解MD5哈希函数的工作原理以及如何逆向分析特定场景下的输入输出关系。然而,在提供的参考资料中并未直接提及有关BUUCTF的具体内容。 对于BUUCTF的Easy MD5挑战,通常涉及的是给定一个MD5散列值,参赛者需要找出能够生成该散列值的原始字符串。由于MD5是一种单向加密算法,理论上无法通过计算反推出原串,但在某些特殊情况下可以通过字典攻击或者暴力破解来尝试匹配已知的常见短语或简单模式[^1]。 为了应对这类CTF竞赛题目: - **构建常用词库**:创建一个包含大量可能出现单词、短句或其他潜在候选者的列表。 - **优化查找过程**:利用多线程技术加速遍历整个数据库的速度;也可以考虑采用GPU并行运算进一步提升效率。 - **注意边界条件**:有时命题人会在提示里暗示一些额外约束(比如长度范围),这有助于缩小搜索空间。 ```python import hashlib from concurrent.futures import ThreadPoolExecutor def md5_hash(text): return hashlib.md5(text.encode()).hexdigest() target_md5 = "d41d8cd98f00b204e9800998ecf8427e" wordlist = ["hello", "world"] # 这只是一个简单的例子,请替换为实际使用的更大规模字典文件路径 with ThreadPoolExecutor(max_workers=10) as executor: futures = {executor.submit(md5_hash, word): word for word in wordlist} for future in futures: hashed_word = future.result() if hashed_word == target_md5: print(f"Found match! Original string was: {futures[future]}") break else: print("No matches found.") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值