OWASP ZAPで検出された脆弱性をゼロにする
大学のとある講義でログイン機能があるwebサイトを自作してレポートを書くという課題が課されました。
レポートには脆弱性検査の結果も書かなければならないため、OWASP ZAPでスキャンします。
サンプルのレポート的には検査した結果を書くぐらいで十分だと思うのですが、どうせなので検出された脆弱性をがんばって潰していきます。
目次
検証環境
- Windows 10 Home 64bit
- XAMPP/7.0.9
- PHP/7.0.9
- phpMyAdmin/4.5.1
- Apache/2.4.23
- MariaDB/10.1.16
サイト構成
脆弱性対策(1回目)
とりあえずリスクが高いものから対策していきます。
SQLインジェクション
' AND '1'='1' -- を入力したら同じ値が返ってきたというもの。
とりあえずその通りに入力してみます。
私の想定通りの動きをしています。
一応プレースホルダを使ってSQLインジェクションの対策はしています。
「Data was returned for the original parameter.」とありますし、入力した文字列がそのまま表示されているのがダメということでしょうか。
とりあえず「このユーザーは登録されていません」と表示するようにしておきます。
X-Frame-Optionsヘッダーの欠如
クリックジャッキングの対策が出来てないよというもの。
正直に申し上げますと、全く考えていませんでした。以後気を付けます。
以下の一文をhttpd.confに追記しておきます。
Header set X-FRAME-OPTIONS "DENY"
PHPで直接書く方法もあるようです。この場合は全てのページに追記する必要があります。
<?php header("X-FRAME-OPTIONS: DENY"); ?>
こちらを参考にさせて頂きました。
www.deep-blog.jp
アプリケーションエラーの開示
エラーが発生したファイルの場所とかが見えてしまうというもの。
ひとまずphpのエラー文を表示しないようにしてみます。
検証のためにDB接続の際に必要な情報が入っているdbconnect.phpの名前を変えてエラーになるようにしておきます。
見事にエラーが表示されます。
PHPのエラーを表示させないために全ページに以下を追記します。
ini_set('display_errors', 0);
表示されなくなりました。
0の部分を1に変えると表示されるようになるので、弄るときはこの部分を変えれば良さそうですね。
また、php.iniを書き変える方法もあります。
display_errors = Off
ディレクトリブラウジング
ディレクトリの一覧を表示できてしまうというもの。
現状index.phpが存在しないのでlocalhost/sec_db/kadai/にアクセスするとディレクトリの一覧が表示されます。
httpd.confのIndexsを削除します。
Options Indexes FollowSymLinks Includes ExecCGI ↓ Options FollowSymLinks Includes ExecCGI
403が表示されるようになりました。
ついでにapacheのバージョンも表示しないようにしておきます。
httpd.confに追記。
ServerTokens Prod
バージョンが表示されなくなりました。
どうせなのでindex.phpも作っておきます。login.phpに飛ばすだけですが。
<?php header("Location: login.php"); ?>
パラメータ改ざん
パラメータを改ざんすることでエラーページが表示されるというもの。
既に「アプリケーションエラーの開示」の対策でエラーページは表示されなくなっているはずなので一旦保留します。
2回目のスキャンでまた出れば対策します。
X-Content-Type-Optionsヘッダの設定ミス
古いバージョンのIEやChromeを使っているとContent-Typeの値に関わらず勝手に解釈してしまうというもの。
以下の一文をhttpd.confに追記しておきます。
Header set X-Content-Type-Options nosniff
PHPで直接書くときはこちら。X-Frame-Optionsのときと同じで全てのページに追記する必要があります。
<? header("X-Content-Type-Options: nosniff"); ?>
こちらを参考にさせて頂きました。
qiita.com
なんというか、この通りに全部やっておけばよさそうですね。
ついでに盛り込んでおきます。
# バージョン情報の隠蔽 ServerTokens Prod Header unset "X-Powered-By" # httpoxy 対策 RequestHeader unset Proxy # クリックジャッキング対策 Header append X-Frame-Options SAMEORIGIN # XSS対策 Header set X-XSS-Protection "1; mode=block" Header set X-Content-Type-Options nosniff # XST対策 TraceEnable Off
ブラウザによるパスワードのオートコンプリート
入力フォームでオートコンプリートが有効になっているというもの。
全く気にしていませんでした。今思えばたしかに大事なような気がします。
ただ、現行のブラウザではautocomplete 属性を"off"にしていても機能しないことがあるようです。
developer.mozilla.org
とはいえ、何もしなければOWASP ZAPで検出されてしまうので対策しておきます。
全ての入力フォームにAUTOCOMPLETE='OFF'を追加するだけです。
<input type="text" name="user" AUTOCOMPLETE='OFF' placeholder="ユーザー名">
これで1回目のスキャンで検出された全ての脆弱性(ブラウザ以外)の対策が終わりました。
ちゃんと対策できているのか確認するために再度スキャンしてみます。
スキャン結果(2回目)
完全勝利。
正直1回で全部消えるとは思っていませんでした。
なんだか呆気ないですね。
まとめ
最初は全部やるのめんどくさいな~とか思っていましたが、いざやってみると案外面白いもので結構楽しみながらやっていました。
今後は最初から脆弱性を意識して、1回目のスキャンでゼロになるようにしていきたいと思います。