連日投稿28日目。今週はこちらで事前に決めたロードマップ従って進めます。
今回の目的
いくつかの脆弱性についてここまで学習してきたので、
- 「で、この脆弱性が見つかったらどんな攻撃が来るの?」
- 「実際のハッキングって、こんな脆弱性1つ突く単発ケースで終わる?もっと連続性ない?」
を、深堀りする。ます今回はコマンドインジェクションで足がかかりをつかみます。
この連日投稿チャレンジについて
目的: セキュリティエンジニアとしての技術力向上
手段: シェルスクリプト作成を通じて学習
実施する事: 自動化,監視,ツール開発基礎学習など
目次
実行結果
DVWAの「Command Injection」ページで、IPアドレスを入力するとpingが実行される機能を発見。ここに 8.8.8.8; ls
と入力してみた。
**結果 (抜粋):
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
...
help
index.php
source
って感じで、ping
の結果の後ろに、見慣れたファイル名が表示された。明らかに ls
コマンドが実行されてる。
続けて、現状把握のためにいくつかコマンドを連結して投入。
先ほどの例に倣い、8.8.8.8 ; whomai ; pwd でやってみる。
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 packets received, 0% packet loss
...
www-data
/var/www/html/vulnerabilities/exec
Webサーバーの実行ユーザーで、脆弱なファイルがあるディレクトリにいることが分かった。こうやって情報抜き取るんだね~
実行中の気づき
このパターン前にも見たな...
day23の記事でも書いたプリペアドステートメント(SQLの命令とデータを分離してサーバに渡す方法)的なやり方をやれば解決するんじゃない?
というわけでソースコードを見てみる。
$userInput = $_GET['ip'];
$command = 'ping -c 4 ' . $userInput; // うわぁ、やってる...
echo shell_exec($command);
DVWAのlevelをLowに設定しているので、まあこんなもんよね。
ユーザーが入力した文字列を、何のチェックもせずに ping
コマンドの後ろにくっつけている。なので ;
とか |
を入れたら、別のコマンドとして実行されちゃう。
PHPでは、平文をそのまま渡すのではなくて、escapeshellarg関数でこれを回避できるらしい。
↓参考にさせていただきました。
https://tomoyuking.com/php/escapeshellarg/
「;」と「&&」の使い分け
じゃあlevelをMediumに引き上げると、これはどう対策されているのか。
ソースコードを覗いてみたら、;
だけでなく &&
も禁止文字リストに入っていた。
;
は分かる。 &&
は? こいつ誰??
調べてみたら、&&
は「前のコマンドが成功したら、次を実行する」というシェルの機能らしい。
んで、;
は、「前のコマンドが成否に関係なく、次も実行する」って意味だったらしい。知らんかった...
例えば、「ping
が成功してネット接続を確認できたら &&
マルウェアをダウンロードする」みたいな、より確実で静かな攻撃ができる。
※何が静か??
→失敗してエラーログが大量に出てこない。これは結構おっきい気づきだった。
ブラックリストは意味がないのか?
引き続きMediumレベルの対策(;
と &&
を消す)を見て考える。
これって典型的な「ブラックリスト方式」だ。
でも、禁止されてない |
を使えば簡単にすり抜けられる。
じゃあ |
も禁止リストに追加する?
そしたらまた別の記号...例えば改行コード\n
(phpだと%0a
らしい) とかを探してくるだけ。完全ないたちごっこ。
ホワイトリスト方式も完璧じゃない?
じゃあ「ホワイトリスト方式」で「許可する文字(数字とドットだけ)を正規表現で確認して、それ以外は全部エラーにする」でいいんじゃね?
と、思ったけど「もし自分が攻撃者だったら、これはこれで別の方法考えるよな~」と。
何か抜け道を考えてみる。
二次注入(Second-Order Injection)なんてもんがあるらしい。
もっと手の込んだ方法になるけど、直接的な攻撃がダメなら、別のシステムに悪意のあるデータを「植え付け」て、後から実行させれば良いのかなと。
完全な推論で書いているので、実績があるかわからん。
例えば、
-
準備段階: 攻撃者は、自分のDNSサーバーに特殊な逆引きレコードを登録する。IPアドレス
1.2.3.4
のホスト名を聞かれたら、「device-ok;reboot;
」という悪意のある文字列を返すように設定しておく。 -
植え付け段階: 攻撃者は、今回検証している「安全な」サイトのping実行ページに行き、自分のサーバーのIP
1.2.3.4
を入力する。サイト側はこれを安全なIPと判断し、ping 1.2.3.4
を実行する。 -
潜伏段階:
ping
コマンドは、当然IPアドレスの逆引きを行って、ホスト名を表示しようとする。ここで、攻撃者のDNSサーバーから悪意のある文字列device-ok;reboot;
を受け取る。そして、PING device-ok;reboot; (1.2.3.4)
という実行結果が、サーバーのどこかのログファイルに「無害なログ」として書き込まれる。 -
実行段階: ここに、別の脆弱なシステムが登場する。例えば、社内向けの管理画面に「pingのログを整形して表示する」という機能があったとする。もしこの機能が、ログファイルをただ
source
コマンドなどで実行するだけの雑な作りだったら...?# 要するにこう #!/bin/bash # This script generates the daily report # Read the log file and execute its contents source /var/log/ping_report.log
管理者がそのページを開いた瞬間、ログに記録されていた
reboot
コマンドが実行され、サーバーは再起動してしまう。
いや、こんな事起こり得るかな...
でも、直接的な攻撃がダメでも、相手方のセキュリティスキル次第では悪用されうるって事は過大評価ではないとおもう。
ただこれはもう、単体のページだけ見てても絶対に見つけられない。システム全体を俯瞰して、データの流れを追わないとダメだな~。実際にできるのか知らんけど。
まとめ
サイバーキルチェーンに則った最初の足がかりを掴めた気はする。「なぜこの脆弱性が生まれるのか」「攻撃者ならどう考えるか」という背景を深く考察できたのが、今日の最大の収穫だった。
特に、;
と &&
の違いから攻撃者の慎重さを想像したり、ブラックリストの限界を見たり、一つ一つの発見が次の思考に繋がる感覚が面白い。
ただ脆弱性を突くだけじゃなく、その裏側にある人間の思考や設計思想にまで考えるのが、結構面白いポイントだなと感じる。