[极客大挑战 2019]BuyFlag
打开靶场发现是一个网站主页,回想起来之前也有这个网站主页的题目,其flag藏在介绍中,于是查看网页源代码,结合题目名称,发现存在一个pay.php
的可疑文件
访问该文件来到另外一个页面,页面提示了获取flag的要求
查看网页源代码,发现存在一段泄露的源码,指示了应该如何传递money
和password
这样一来就可以构造来满足money
和password
,其中password
是一个php弱类型比较的绕过,只需要构造password=404a
即可满足非数字类型,并且在进行弱类型比较时会强制类型转换成404从而比较成功
但是还有一个条件没有满足,那就是需要是CUIT成员才能得到flag,通过观察数据包,发现在请求头中的cookie
字段存在user
参数,将其从0改为1,发现密码对了,但是又有新的报错
数字长度太长,考虑到可能是存在strcmp()
函数的绕过漏洞,于是将1000000000修改成1e9,成功得到flag{466195e3-c19b-4b32-98fa-d534c596f135}
总结:
- 解题思路:从题目名称结合网页源代码信息了解到
pay.php
可疑文件的存在,访问后从网页源代码中发现flag的获取要求,根据要求构造money
参数、passowrd
参数以及cookie
字段,其中money
参数利用了科学计数法绕过strcmp()
函数的校验,password
参数利用了php弱类型比较进行绕过,从而得到flag - 对于
money
长度过长的问题,可以通过科学计数法进行绕过,通过查阅writeup后发现也可以利用strcmp()
函数的特性进行绕过,即在php5.3之前的版本中,当传入了非字符串类型的数据时,strcmp()
函数会发生错误,但是其只会显示报错的警告信息后,并return 0
,也就是虽然报错,但是却判定其相等,因此money
参数可以构造为money[]=1
[BJDCTF2020]Easy MD5
打开靶机,发现是一个输入框,第一感觉就是可能是sql注入类型的漏洞
burp抓包重放,发现响应包存在hint
请求头字段给出了后台sql查询语句的格式如下
select * from 'admin' where password=md5($pass,true)
首先了解一下md5
函数在php中的用法
若我们能找到一个字符串,该字符串经过md5
加密后再转换成hex(十六进制)形式输出刚好是'or '6XXXX'
,则可以构成恒真句式使得查询为真,根据网上writeup可以知道有字符串ffifdyop
可以满足要求,输入该字符串进入下一关
查看网页源代码发现泄露的部分源代码
<!--
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-->
根据提示,需要构造参数a
和b
,并且其值不等,但是md5
值要弱相等,即要构造一个md5
碰撞,根据网上writeup可以用a=s878926199a
以及b=s155964671a
来构造通过本关,参数传递后来到第三关,直接给了源代码
<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}
从源代码中可以看出,我们需要构造POST参数param1
和param2
,使得两个参数值不同但是md5
值要强相等,可以通过php数组绕过,即哈希函数无法处理php数组,在遇到数组时会返回null
,因此可以构造利用null=null
使得条件成立,因此传递POST参数param1[]=1¶m2[]=2
成功得到flag{5b90749c-47de-465f-ada0-9c5e234c95ab}
总结:
-
解题思路:首先根据响应包请求头中的
hint
字段了解到后台的sql查询语句,根据查询语句的特点,需要构造经过md5
加密并转换成十六进制输出并进行ASCII解释后拼接进sql查询语句中可以实现恒真句式的字符串,而ffifdyop
便是这样一个常用的字符串,从而可以进入第二关;基于php的弱类型比较,可以找到明文不同的md5
碰撞,从而可以进入第三关;基于php的md5
函数漏洞,对于数组类型的输入md5
函数会返回null
,从而可以构造两个值不相同的数组使得md5
强相等 -
MySQL中会把十六进制转为ASCII进行解释;MySQL在进行布尔类型判断时,以数字开头的字符串会被当作整形数处理;
ffifdyop
字符串经过md5
加密后并转换成十六进制为276f722736c95d99e921722cf9ed621c
(这是md5
函数进行的操作),再对该十六进制数进行ASCII码转换,则可以得到'or '6XXXX'
(这是MySQL对十六进制数的解释方式,XXX
代表乱码或者不可见字符),进而实际上拼接到sql查询语句中的是select * from ‘admin’ where password=''or'6XXXX'
,相当于select * from ‘admin’ where password=''or 6
(这是MySQL将数字开头的字符串当作整型数处理),相当于select * from ‘admin’ where password=''or true
(非0数字在判断时相当于true
),因此形成恒真句式
- 常见的
md5
碰撞组合有
s878926199a //原始字符串
0e545993274517709034328855841020 //md5值
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
- md5函数的漏洞:无法处理数组类型字符串,当输入数组类型字符串时会返回
null
,以下是一些常见以数组为输入的php函数的特性
md5(array()) = null
sha1(array()) = null
ereg(pattern,array()) = null vs preg_match(pattern,array) = false
strcmp(array(), "abc") = null
strpos(array(),"abc") = null
参考文章
- BUUCTF-[极客大挑战 2019]BuyFlag 记录:学习了利用php的strcmp()函数特性进行绕过的方法
- [BJDCTF2020]Easy MD5:学习了关于ffifdyop字符串是如何经过md5加密再以十六进制输出后经过MySQL数据库的解释得到恒真句式
- Buuctf [BJDCTF2020]Easy MD5:学习了常见的md5碰撞组合
- [BUUOJ记录] [BJDCTF2020]Easy MD5:学习了以数组为参数的php的一些特性