前言
继续刷,准备蓝帽,好久没做题了都。
[HFCTF2020]JustEscape
进入题目,发现首页提示run.php并且给了一些实例,我们访问这个php文件得到一个代码:
1 | <?php |
看起来是一个命令执行,还没过滤的,但是这肯定没那么简单,随便传点东西上去试试,比如code=phpinfo();
,查看返回:
1 | ReferenceError: phpinfo is not defined |
什么鬼没有定义,结合首页提示我们这真的是php吗,我们可以想到除了php以外,js中也是有eval()这个函数的,那么我们来测试一波:
1 | ?code=Error().stack |
看到返回结果,果不其然:
1 | Error at vm.js:1:1 at Script.runInContext (vm.js:131:20) at VM.run (/app/node_modules/vm2/lib/main.js:219:62) at /app/server.js:51:33 at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5) at next (/app/node_modules/express/lib/router/route.js:137:13) at Route.dispatch (/app/node_modules/express/lib/router/route.js:112:3) at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5) at /app/node_modules/express/lib/router/index.js:281:22 at Function.process_params (/app/node_modules/express/lib/router/index.js:335:12) |
那结合题目很明显这题是一个vm2逃逸,直接套poc:
1 |
|
测试后发现存在过滤用javascript的模版文字绕过。最后poc:
1 | (function (){ |
得到flag。
[HFCTF2020]BabyUpload
进来就是代码审计:
1 | <?php |
好长一段,这么长当然得一段段来看。首先是第一段:
1 | if($_SESSION['username'] ==='admin') |
这段比较简单,也是我们能获取flag的核心,只要满足两个条件就可以了:
- session中的username的值要为admin
- 存在文件/var/babyctf/success.txt
但是默认将我们的session中username的值设置为guest。
第二段:
1 | if($direction === "upload"){ |
文件上传,过滤了目录穿越,文件名也进行了哈希,不过都没啥用,唯一的作用可以说就是在/var/babyctf/下任意上传文件了,那么我们肯定要通过这个部分上传success.txt。
第三段:
1 | elseif ($direction === "download") { |
任意文件下载,同样过滤了目录穿越,可以从/vat/babyctf/中进行任意文件读取。
php的session默认存储文件名是sess_+PHPSESSID的值,我们先读取cookie中的session并尝试读取:
1 | direction=download&attr=&filename=sess_73e1e2caaba56997530a478afabf59d0 |
看到返回:
1 | usernames:5:"guest"; |
发现有一个不可打印字符,那么就可以判断储存模式是php_binary了。因为这个模式的储存方式是键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值,那么我们就可以根据这个规律伪造session了:
1 | usernames:5:"admin"; |
那么我们只要上传伪造的session文件和success.txt就可以了,直接用exp:
1 | import hashlib |
执行获取flag。
EasyBypass
同样开门见源码:
1 | <?php |
真是一题简单的bypass呢(恼怒),这过滤的也太狠了吧。因为file命令打不开文件,只能判别文件的类型,因此我们在comm1中要利用引号和分号来进行命令的控制。
对比了一下过滤程度,comm1比较少一点,而且分号还在,那就从comm1开刀。
构建payload,先将引号闭合,接着用分号结束file语句,然后跟上flag读取命令,最后闭合后引号保障不会报错:
1 | ?comm1=";tac /fla?;"&comm2=1 |
GET传入数据获取flag。
[RoarCTF 2019]Simple Upload
审代码:
1 | <?php |
[RootersCTF2019]babyWeb
进入了网页告诉我们ban掉了一批sql用的关键词,看来是sql注入了,但这题挺离谱的,万能密码注进去就返回flag了,有点没看懂。
payload:
1 | 1 || 1=1 limit 0,1 |
[NPUCTF2020]ezlogin
进网页上来一个登录框,fuzz一下发现不是sql,抓包发现是一个xml,那么先怀疑xxe,但是没有明显的注入点,而且进行登录的话xxe明显不适用,那么就怀疑xpath注入了。
关于xpath可以参考下面这篇文章:
xpath注入详解
那么就是一层一层扒到存有账号与密码的节点,并且读取出数据进行登录应该就可以了,直接网上找exp了,不是很想自己写:
1 | import requests |
得到账号密码:
1 | username=adm1n,password=cf7414b5bdb2e65ee43083f4ddbc4d9f |
将密码进行somd5解码得到密码为gtfly123,登陆进去后页面什么都无,查看源码发现base64,解码后告诉我们flag在/flag中。url存在file参数,说明可能存在文件读取,直接读取flag失败,伪代码读取成功,payload:
1 | Php://filter/convert.Base64-encode/resource=/flag |