P438〜の練習問題02-1、02-2、02-3のWriteupです。
02-1
省略
02-2
(1)
Drupageddonとは、Drupal 7 コアに存在した重大な SQLインジェクション脆弱性です。
SQLインジェクションってのは、超簡単に言えばデータベースを操作できるコマンドを普通の入力に混ぜて送ると、データベースが操作できちゃう。見ちゃいけない情報が見れちゃう。みたいなやつです。
SQLインジェクション自体は昔からありますし、数ある攻撃手法の中で一番有名(たぶん)だといえるくらい有名。
対策も簡単。
プレースホルダーを使ったり、入力値を検証したりORMを使ったり...いろんな対策方法があります。
Drupageddonはプレースホルダーの展開処理に不備があったようです。
このDrupageddonの何がヤバいかっていうとその影響範囲。
特別な権限なしに攻撃者は任意のSQL文を実行でき、データベースの読み取り・改ざんはもちろん、管理者アカウントの作成や、最終的には任意のPHPコード実行(RCE)までつなげることができました。
Drupalセキュリティチームは、パッチ公開からわずか7時間以内に自動化された攻撃が観測されたと警告を出しました。そのため「パッチを当てていないサイトは、たとえ後から更新しても、既に侵害されている前提で対応すべき」という異例の勧告(バックドアの有無を確認し、必要ならサイトを完全に再構築すること)が出され、これが大きな話題になりました。
7時間ルールってやつですね。
(2)
runコマンドを実行する前に、wiresharkを開いて、パケットを観察できるようにしましょう。
手順1:Wiresharkの表示フィルタでノイズを削る
キャプチャ全体にはARP(IPからMACアドレスを引くための名前解決)や、TCPの[SYN]/[ACK]単体のような、通信の中身を持たないパケットが大量に混ざります。まずはアプリケーション層のリクエストだけに絞り込みます。
何もしなかったらパケットがいっぱいで見にくい。
今回のキャプチャからは
-
POST /?q=user/login HTTP/1.1(長さ3405バイト) -
POST /?q=user/login HTTP/1.1(長さ440バイト)
の2件のHTTPリクエストが残るはずです。ARPやTCPハンドシェイクは「通信を成立させるための準備」であって攻撃の中身ではないので、肝心なのはここだけ。
手順2:TCP会話(コネクション)の単位で数える
次に、メニューの統計(Statistics)→ 会話(Conversations)→ TCPタブを開くと、このキャプチャ内で何本のTCPコネクションが張られたかが一覧できます。今回のキャプチャでは次の3本が確認できるはずです。

| コネクション | 送信元ポート | 宛先ポート | 役割 |
|---|---|---|---|
| ① | 34573 | 80 | 1回目のPOST(3405バイト)を送るための接続 |
| ② | 36267 | 80 | 2回目のPOST(440バイト)を送るための接続 |
| ③ | 47596 | 4444 | Meterpreterのリバースシェル通信 |
3つめはポート番号が今までと毛色が違い、宛先が80番ではなく4444番です。Metasploit側のshow optionsを見るとLPORT 4444(ペイロードのリスンポート)となっており、これが一致します。
手順3:中身を確認する(Follow HTTP Stream / TCP Stream)
各パケットを右クリック→「Follow」→「HTTP Stream」(または「TCP Stream」)を選ぶと、リクエストの生データが読めます。
SQLインジェクションを使い、Drupalのフォームキャッシュ(cache_formテーブル)に悪意あるシリアライズ済みPHPペイロードを書き込むリクエストです。データ量が大きいのは、注入するSQL文+シリアライズされたペイロード分のデータを一度に送り込んでいるためです。
1回目より明らかに小さいリクエストです。これは、①で仕込んだ「毒入りのフォームキャッシュ」を実際に呼び出させるためのトリガーにあたります。
③のポート4444の通信:
ここでPHPコードの実行に成功した対象サーバーが、Metasploitのペイロード(Meterpreterステージャ)の指示通り、攻撃者のLHOST:LPORT(192.168.56.101:4444)に向けて自分から接続しにいく通信です。
まとめ
「3段階の通信で構成されている」という構造で捉えて説明するのが答えなんでしょうか(わからん)
「ツール側のログとパケットキャプチャを両方見て、片方だけでは分からない意味を補い合う」というのが、この狙いだと思います。
(3)
- SQLiで書き換えたパスワード(または既知の
admin/dragon)で管理画面にログイン - 「PHP filter」モジュールを有効化する(Drupal 7標準機能、デフォルトでは無効なことが多い)
- 新しいコンテンツ(ページ)を作成し、本文の入力形式を「PHP code」にして、リバースシェルのPHPコードを書く
- 攻撃側でリスナー(
nc)を待ち受けておく - 作成したページを閲覧(アクセス)した瞬間にPHPコードがサーバー側で実行され、シェルが返ってくる
02-3
(1)
echo '<?php system("cat /etc/passwd");?>' > malicious
ポイントとしては、シングルクォーテーション ’ で囲むこと
内容に<> " " が含まれています。もしダブルクオートで囲んでしまうと、シェルは中の`"cat /etc/passwd"`部分を「文字列の終わり」と誤解して構文が壊れてしまいます。またクォートなしで書くと、`<`や`>がリダイレクト演算子として解釈されたり、ダブルクォートの対応がずれたりして意図通りの中身になりません。 シングルクォートで囲む最大のメリットは、**中に書いた文字がほぼすべてそのままリテラルとして扱われる**ことです(例外は'自身のみ)。<`や`>、"`はシングルクォートの中では特別な意味を持たず、ただの文字として保存されます。
(2)
まず実際に試す手順は次の通りです。
bash
mv malicious malicious.php # もしくは新規に同内容でmalicious.phpを作成
python3 -m http.server 8000
ブラウザでhttp://localhost:8000/malicious.phpにアクセスすると、/etc/passwdの中身が画面に表示されるのではなく、malicious.phpというファイル自体をダウンロードしようとするダイアログが出てきます。
理由は、python3 -m http.serverが「ただの静的ファイル配信サーバー」であり、PHPを解釈・実行する機能を一切持っていないからです。
PHP対応のWebサーバー(Apache+mod_phpやNginx+php-fpm)はリクエストされたファイルの拡張子が.phpだと分かると、そのファイルの中身をPHPインタプリタに渡して実行し、実行結果(今回ならcat /etc/passwdの出力を含むHTML)をレスポンスとして返します。
一方、Pythonのhttp.serverは.phpという拡張子を特別扱いする仕組みを持っていません。リクエストされたファイルを中身を一切解釈せず、そのままバイト列としてクライアントに返すだけです。つまりmalicious.phpにアクセスすると、サーバーは<?php system("cat /etc/passwd");?>というPHPのソースコードの文字列そのものを返してきます(実行はされません)。
ではなぜ「テキストとして表示」ではなく「ダウンロードしようとする」のかというと、これはHTTPレスポンスのContent-Typeヘッダーが関係しています。http.serverは、返すファイルのContent-Typeを拡張子から推測する仕組み(Python標準ライブラリのmimetypesモジュール)を使っています。しかしmimetypesのデフォルトの対応表には、そもそも.htmlや.txt、.css、.jpgのような一般的なWeb向け拡張子は登録されていますが、.phpはプログラミング言語のソースコード用の拡張子であり、Web標準のコンテンツタイプとしては登録されていません。対応する型が見つからない場合、http.serverは既定値であるapplication/octet-stream(「中身不明のバイナリデータ」を意味する汎用MIMEタイプ)を返します。
ブラウザはContent-Type: application/octet-streamを受け取ると、「これはブラウザ内で表示できる種類のコンテンツではない」と判断し、画面に表示する代わりにファイルとして保存するかどうかをユーザーに確認するダイアログを出します。これが「ダウンロードを試みる挙動」の正体でしょう。
この違いはLFIやRFIを使う上で重要で、攻撃者がpython3 -m http.serverのような簡易サーバーで悪意あるPHPファイルを配信しても、それ自体は実行されず、あくまで「素材」を配っているだけ。
実際にコードが実行されるのは、脆弱なターゲット側のアプリケーションが、そのファイルをincludeやrequire(あるいはLFIの脆弱性経由)で自分のPHP実行環境に取り込んだときです。つまり「配信するサーバー」と「実行するサーバー」が別物である、という構造を、この設問は体感させようとしているのだと思います。
(3)(4)
省略
できないなら多分写し間違いでしょう。




