概要
今回の実験レポートは、VulnHubで公開されている「EvilBox-One」に対するペネトレーションテストの実証記録です。
EvilBox-Oneは、ペネトレーションテストの練習用に開発されたLinuxベースのOSで、意図的に複数の脆弱性が存在するように設計されています。
目的は、一連の調査と攻撃を通じてサーバーに侵入し、最終的にroot権限を奪取してサーバー内に隠されたflagを見つけ出すことです。
1. 環境
- ホストOS: Windows 11
- 攻撃者 (Attacker): Kali Linux (VirtualBox)
- ターゲット (Target): EvilBox - One (VirtualBox)
- ネットワーク: (VirtualBox内部ネットワーク設定を想定)
2. 実験1:情報収集 (偵察)
ネットワーク上のターゲットを特定し、稼働中のサービスと公開されているディレクトリを調査する。
ターゲットのIPアドレスを取得
`netdiscover` を使用して、ローカルネットワーク内のホストを探索します。
sudo netdiscover -r 192.168.2.0/24
ターゲットのIPアドレスが `192.168.2.182` であることが分かりました。
Nmapでポートスキャン
ターゲット端末で開放されているポートと稼働中のサービスを調査します。
sudo nmap -sC -sV -p- -O 192.168.2.182
- -sC:デフォルトのスクリプト(脆弱性スキャンなど)を実行します。
- -sV:ポートで稼働しているサービスのバージョン情報を取得します。
- -p-:全65535ポートをスキャン対象とします。
- -O:OSのフィンガープリント(OSの種類を特定)を試みます。
調査の結果、SSH (ポート22) と Apache Webサーバー (ポート80) が稼働していることが分かりました。
Webサーバーが稼働しているので、アクセスしてみると、Apacheのデフォルトページが表示されました。この時点では特に何の変哲もありません。
Webサーバーの確認とディレクトリ探索
次に `Gobuster` を使って隠されたディレクトリやファイルを探索します。
sudo gobuster dir -u http://192.168.2.182 -w /usr/share/wordlists/dirb/common.txt -x html,txt,php
- -u:対象のURLを指定します。
- -w:使用するワードリスト(辞書ファイル)を指定します。
- -x:探索するファイルの拡張子を指定します。
探索結果として、`robots.txt` と `secret` というディレクトリを見つけました。
robots.txt
robots.txt とはクローラーに対して、このサイトのどこを見ていいか・見ちゃいけないかを指示するための設定ファイルです。
検索エンジンのクローラー(Googlebot など)は、サイトに来るとまず robots.txt をチェックします。そしてそこで指示されたルールに従ってクロール(内容を収集)をします。
クロールされ、その後インデックスに登録されると、ページは検索エンジンに認識され、検索対象として扱われるようになります。(サイト名を検索すると検索結果として表示されるなど)
robots.txtには検索では見つけられない未知のディレクトリ情報などが記載されている場合があるので探索の際は意識する必要があります。
今回見つけたrobots.txtを開いてみると「Hello H4x0r」と書かれているだけで、他には何もありませんでした。
secretディレクトリの探索
sudo gobuster dir -u http://192.168.2.182 -w /usr/share/wordlists/dirb/common.txt -x html,txt,php
`secret` ディレクトリをさらに探索した結果、`evil.php` といういかにもなファイルを発見しました。
3. 実験2:脆弱性調査と侵入 (LFI)
evil.phpについて考察
evil.phpはevilという名前からして他の攻撃者が仕掛けたバックドアなどの可能性を疑いました。もしそうなら何らかの入力を待ち受けている(コマンド実行やファイル読み取りの)可能性があると推測できます。
まずは、コマンドが実行できるのか試してみました。
現在のディレクトリの位置をおおよそ予測し、逆算してetc/idを指定します。例えば、もしこのファイルがWebサーバー上で/var/www/secret/evil.phpという形で位置していた場合、/etc/idを指定するには../../../etc/idとなります。しかし確実にルートディレクトリに移行したいので、今回は../../../../usr/bin/idとします。
http://192.168.2.182/secret/evil.php?cmd=../../../../usr/bin/id
このコマンドを実行してみましたが、案の定何も表示されませんでした。これはcmdの部分が本当にcmdであるとは限らないからです。
WFUZZによるパラメータの特定
そこでWFUZZを使い、ファイル読み取り(LFI)が可能か、またそのパラメータ名が何かを総当たりで調査します。
wfuzz -u "http://192.168.2.182/secret/evil.php?FUZZ=../../../../usr/bin/id" -w /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt --hw 0
- -u:対象URL。`FUZZ` の部分がワードリストの単語に置き換わります。
- -w:パラメータ名として試行するワードリスト。
- --hw 0:レスポンスのサイズが0(通常時)のものを非表示にし、反応があったものだけを表示します。
このコマンドを実行した結果command、というパラメータがヒットしました。
LFIによるファイル読み取り
特定したcommandパラメータを使用し、もう一度実行してみました。
http://192.168.2.182/secret/evil.php?command=../../../../usr/bin/id
しかし、結果として大量の文字が表示されただけで、コマンドの結果は表示されませんでした。
一番上に表示されたELFという文字からしてこれはバイナリファイルの中身が表示されただけで、idコマンドの実行結果が表示されたわけではないことが分かります。
しかし、指定したファイルの内容を表示できることはわかったので、次は攻撃者がよく狙う/etc/passwdファイルの中身を見ることができるか確認してみます。
http://192.168.2.182/secret/evil.php?command=../../../../etc/passwd
その結果、/etc/passwdの内容が表示されました。
ブラウザ上では見ずらいのでコマンドライン上で表示してみます。
curl "http://192.168.2.182/secret/evil.php?command=../../../../etc/passwd"
結果、/etc/passwdの内容が表示されました。これにより、evil.phpにはディレクトリトラバーサル(LFI)の脆弱性があることが確定しました。
さらにファイルの内容から、ログイン可能なユーザーとしてrootとmowreeが見つかりました。
SSH秘密鍵の窃取
LFIが可能であり、/etc/passwdが閲覧できたということは、権限が許す範囲であれば他のファイルも開けるということです。
しかし、いきなりピンポイントでflagファイルを見つけることは至難の業です。
そこで今回は攻撃者がサーバーに侵入した際に定石としてよく閲覧するファイルを探索してみます。
いろいろありますが、その中の一つとにSSHの秘密鍵が存在します。
ポートスキャンを実行した際にSSHサーバーが稼働していることが分かりました。
設定にもよりますが、もしかしたらこのSSHが自身(Webサーバー)からの接続を想定している可能性もあります。
通常、サーバー(A)に置かれた秘密鍵は、別のサーバー(B)に接続するためのものです。
しかし、攻撃対象の環境(VulnHubの演習など)が1台のサーバーで完結している場合、開発者がSSHサーバーの動作確認などのために「自分自身への接続設定(AからAへ)」を行い、その設定(公開鍵)をauthorized_keysに残したままにしている可能性もありえます。
もしそうであれば、SSH認証に公開鍵認証を使用していた場合、その秘密鍵を入手でき、かつパスフレーズが設定されていなければ、秘密鍵だけでこのサーバーで稼働しているSSHを経由してWebサーバーにアクセスできることになります。
秘密鍵を奪取
LFIが可能であるため、mowreeユーザーのSSH秘密鍵id_rsaの読み取りを試みます。
curl "http://192.168.2.182/secret/evil.php?command=../../../../home/mowree/.ssh/id_rsa"
探索の結果、秘密鍵の取得に成功しました。しかし、ファイル内にProc-Type: 4,ENCRYPTEDという記述があり、この秘密鍵がパスフレーズによって暗号化されていることが判明しました。
John the Ripperによるパスフレーズ解析
暗号化されたSSH秘密鍵(先ほどのProc-Type: 4,ENCRYPTEDがあるファイル)のパスフレーズをJohn the Ripper(john)で解析するには、まず鍵ファイルからjohnが読み取れる形式の「ハッシュ」を抽出する必要があります。
このためには ssh2john というツール(John the Ripperスイートに含まれています)を使用します。
# 見つけた秘密鍵をKaliにコピーします。
# 任意のディレクトリで、先ほど表示した秘密鍵の内容をコピペしてCtrl + D
cat > id_rsa
# 権限を付与 (Johnが読み取れるように)
chmod 700 test_rsa
# ハッシュ値を取得
ssh2john id_rsa > hash.txt
# ハッシュ値の解析
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
次に、抽出した `hash.txt` を `rockyou.txt` のワードリストで解析します。
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt
解析の結果、パスフレーズが「unicorn」であることが判明しました。
SSHによる侵入
窃取した秘密鍵 `id_rsa` と、特定したパスフレーズ `unicorn` を使用して、`mowree` ユーザーとしてSSHログインを試みます。
ssh mowree@192.168.2.182 -i id_rsa
パスフレーズの入力が求められ、「unicorn」と入力したところ、無事に `mowree` ユーザーとしてサーバーにログインできました。
4. 実験3:権限昇格
サーバー内部の探索
侵入後、権限昇格の足掛かりとなる不適切な設定ファイルを探します。今回は以下のコマンドを用いて一般ユーザーでも書き込み可能なファイル(特に重要な設定ファイル)を検索します。
find / -writable -type f 2>/dev/null | grep -v "/proc/" | grep -v "/sys/"
- find / -writable -type f:ルートディレクトリ `/` から、書き込み可能 (`-writable`) なファイル (`-type f`) を探します。
- 2>/dev/null:エラーメッセージ(権限がないディレクトリなど)を非表示にします。
- grep -v ...:仮想ファイルシステムである `/proc/` と `/sys/` を除外します。
コマンドの結果、驚くべきことに/etc/passwdファイルが一般ユーザーであるmowreeによって書き込み可能であることが判明しました。
/etc/passwd の脆弱性を利用した権限昇格
/etc/passwdに書き込みが可能ということは、root権限を持つ(ユーザーIDが0の)新しいユーザーを任意に追加できることを意味します。この脆弱性を使わない手はありません。
1. Kali側でパスワードハッシュを生成
新しく追加するユーザーのパスワードのハッシュを `openssl` で作成します。
openssl passwd -1 1234
$1$pcjEZ3oo$JFf4MoykNgCwfhNSf9wSz0
2. ターゲットサーバーで /etc/passwd に追記
echoコマンドを使用し、生成したハッシュを持つroot権限ユーザー (`evilroot`) を/etc/passwdに追記します。
echo 'evilroot:$1$pcjEZ3oo$JFf4MoykNgCwfhNSf9wSz0:0:0:root:/root:/bin/bash' >> /etc/passwd
cat /etc/passwdで確認すると、一番下にevilrootユーザーが追加されていることが確認できます。
3. root権限の奪取
suコマンドで、新しく作成したevilrootに切り替えます。
su evilroot
Password: 1234
idコマンドの結果、uid=0(root)となり、root権限の奪取に成功しました。
これにより、/rootディレクトリに配置された最終的なflagファイル (root.txt) を閲覧することが可能になりました。
5. 対策と考察
感想:
今回のペネトレーションテストでは、単一の脆弱性ではなく、複数の異なる種類の脆弱性(WebアプリケーションのLFI、弱いパスフレーズ、OSの不適切な権限設定)が連鎖することで、最終的にroot権限の奪取という最悪のシナリオに至るプロセスを実体験できました。
特に印象的だったのは、`evil.php` という怪しいファイルを発見した後、`wfuzz` を使って `command` というパラメータを特定する地道な探索が、`/etc/passwd` やSSH秘密鍵の漏洩という重大な結果につながった点です。
さらに、入手した秘密鍵がパスフレーズで暗号化(`ENCRYPTED`)されていたため一度は壁にぶつかりましたが、`ssh2john` と `rockyou.txt` による解析であっさりと `unicorn` というパスフレーズが特定できてしまい、パスフレーズが弱いことの危険性を痛感しました。
最後の決定打は、侵入後のサーバー探索で見つけた「`/etc/passwd` が一般ユーザーで書き込み可能」という、あり得ないほど脆弱な設定でした。これにより、苦労して手に入れた一般ユーザー権限から、いとも簡単にroot権限を持つユーザーを追加できてしまい、攻撃の容易さに驚くと同時に、設定ミスの恐ろしさを実感しました。
考察 (セキュリティの観点から):
今回の実験は、「セキュリティの連鎖(Security Chain)」と「多層防御」の重要性を示す典型的な例であったと考えます。
1. LFI(ローカルファイルインクルージョン)の危険性:
最初の侵入口となった `evil.php` の脆弱性は、ユーザーの入力を適切に検証(サニタイズ)せずに、ファイルパスとして利用したことが原因です。`../../../../`
のようなディレクトリトラバーサルを許した結果、本来アクセス不可能な `/etc/passwd` や `.ssh/id_rsa`
が読み取られました。これは、「ユーザーからの入力はすべて信頼しない」という原則が破られていたことを示しています。
2. 弱いパスフレーズの無意味さ:
SSH秘密鍵はパスフレーズで暗号化されていましたが、`rockyou.txt`
のような一般的な辞書ファイルで解析できる `unicorn` という単語では、防御として機能していませんでした。秘密鍵が漏洩した場合、パスフレーズは「最後の砦」です。この砦が弱ければ、暗号化している意味がありません。複雑で長いパスフレーズの使用を強制することが不可欠です。
3. OSの基本的な権限設定の不備(最小権限の原則違反):
最大の脆弱性は、`/etc/passwd`
が一般ユーザー(mowree)によって書き込み可能(`writable`)になっていた点です。これは「最小権限の原則」を完全に無視した設定ミスです。この設定一つで、攻撃者は簡単にroot権限を持つバックドア(`evilroot`
ユーザー)を作成できました。
結論:
Webアプリケーション(LFI)、運用(弱いパスフレーズ)、OS基盤(ファイル権限)という異なるレイヤーでそれぞれ脆弱性が存在したために、今回の侵入は成功しました。開発者やサーバー管理者は、単一の対策に依存するのではなく、各レイヤーで適切なセキュリティ対策(入力値の検証、強力なパスワードポリシーの強制、ファイルの権限の厳格な管理)を実施する「多層防御」の考え方が不可欠であると再認識しました。
まだコメントはありません。