土日の勉強ノート

AI、機械学習、最適化、Pythonなどについて、技術調査、技術書の理解した内容、ソフトウェア/ツール作成について書いていきます

徳丸本:OWASP ZAPの自動脆弱性スキャンをやってみる

ハッキング・ラボのつくりかた 完全版 仮想環境におけるハッカー体験学習」と「体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践」(通称:徳丸本)を参考に、セキュリティの勉強を進めています。

今回は、徳丸本の 7章の「脆弱性診断入門」の OWASP ZAP の自動脆弱性スキャンについて、実際にやっていきたいと思います。

それでは、やっていきます。

参考文献

はじめに

「セキュリティ」の記事一覧です。良かったら参考にしてください。

セキュリティの記事一覧
・第1回:Ghidraで始めるリバースエンジニアリング(環境構築編)
・第2回:Ghidraで始めるリバースエンジニアリング(使い方編)
・第3回:VirtualBoxにParrotOS(OVA)をインストールする
・第4回:tcpdumpを理解して出力を正しく見れるようにする
・第5回:nginx(エンジンエックス)を理解する
・第6回:Python+Flask(WSGI+Werkzeug+Jinja2)を動かしてみる
・第7回:Python+FlaskのファイルをCython化してみる
・第8回:shadowファイルを理解してパスワードを解読してみる
・第9回:安全なWebアプリケーションの作り方(徳丸本)の環境構築
・第10回:Vue.jsの2.xと3.xをVue CLIを使って動かしてみる(ビルドも行う)
・第11回:Vue.jsのソースコードを確認する(ビルド後のソースも見てみる)
・第12回:徳丸本:OWASP ZAPの自動脆弱性スキャンをやってみる ← 今回
・第13回:徳丸本:セッション管理を理解してセッションID漏洩で成りすましを試す
・第14回:OWASP ZAPの自動スキャン結果の分析と対策:パストラバーサル
・第15回:OWASP ZAPの自動スキャン結果の分析と対策:クロスサイトスクリプティング(XSS)
・第16回:OWASP ZAPの自動スキャン結果の分析と対策:SQLインジェクション
・第17回:OWASP ZAPの自動スキャン結果の分析と対策:オープンリダイレクト
・第18回:OWASP ZAPの自動スキャン結果の分析と対策:リスク中すべて

徳丸本の環境構築については、以下の第9回でやりました。

daisuke20240310.hatenablog.com

この環境を使ってやっていきます。

日本語化や、Firefox でセキュリティ警告が出る対策などを追記しました。

あと、徳丸本のサポートML は以下です。困ったときは、ここを見ると、解決できるかもです。

https://groups.google.com/g/wasbook-readers

脆弱なサンプルアプリケーション(Bad Todo)の準備

徳丸本では、脆弱性を診断する対象として、Bad Todo という Webアプリケーションを用意してくれています。

これは、脆弱性仮想マシン(wasbook)の中に含まれていて、目次(https://example.jp/)の「7 Bad Todo(脆弱性診断サンプルアプリケーション)」をクリックすることで、Bad Todo にアクセスすることが出来ます(https://example.jp/todo/)。

では、早速アクセスしてみます。以下のようにトップページが表示されます。ログインをクリックします。

Bad Todoのトップページ
Bad Todoのトップページ

最初は、ユーザが登録されていないので、以下のように「こちら」をクリックします。会員登録とありますが、あくまでローカルの環境なので、どこかに登録した内容が通知されることはありません。

ログイン画面
ログイン画面

会員登録の画面になるので、なんでもいいので、適当に、ユーザID(daisuke)、パスワード(useruser)、メールアドレス(daisuke@gmail.com)と、適当な画像をアイコン画像として登録します。アイコン画像を登録せずに進んだら、「アイコン画像を登録してください」と出て、先に進めなかったので、登録が必要です。入力できたら「確認」をクリックします。

会員登録の画面
会員登録の画面

「入力を確認してください」と出るので、「登録」をクリックします。

入力確認の画面
入力確認の画面

「登録しました。」「続いて ログイン してください。」と出るので、「ログイン」をクリックします。

今決めた ユーザID とパスワードを入力して、「ログイン」をクリックします。

ログイン画面
ログイン画面

2件の Todo が登録されていますが、追加で1件登録します。

名前やその他を適当に入力し、添付ファイルも適当に用意したものを指定して、「登録」をクリックします。

todo新規登録の画面
todo新規登録の画面

これで準備は完了です。

いったんは、「公開」で登録しましたが、思い直して、非公開に変更しました。

「一覧」から、todo の「pentest」をクリックします。「編集」ボタンをクリックすると編集画面に遷移します。公開のところのチェックを外して、「更新」ボタンをクリックします。

編集の画面
編集の画面

※2024/8/18:追記

この時点で、データベースを保存しておきます。そうすると、データベースが壊れたときに、この状態に戻すことが出来ます。保存方法と復旧方法は後述します。

OWASP ZAPによる自動脆弱性スキャン

OWASP ZAP で、脆弱性診断を行うには、設定が必要なようです。

自動脆弱性スキャンの設定

これから自動脆弱性スキャンの設定を行っていきますが、設定の中には、一度設定すれば、OWASP ZAP を終了しても維持されるものと、毎回設定しなければならない設定が存在します。(自分用ですが)毎回しなければならない設定には黄色い下線を付けています。

OWASP ZAP に、たくさんのアクセスログがたまってる場合は、見にくいので、クリアしておくと見やすくなります。クリアする方法は、下図のアイコンをクリックするだけです。

アクセス履歴をクリア
アクセス履歴をクリア

では、Bad Todo にアクセスします。以降の図では(間違えて)ログインした状態になっていますが、ログインしていない状態で設定していきます。左側のペイン(子ウィンドウ)に todo というフォルダが出来ていると思います。この todo を右クリックして、コンテキストに含める→新規コンテキストをクリックします。

新規コンテキストの作成
新規コンテキストの作成

Regex のところに、https://example.jp/todo.* となっていることを確認して、OK をクリックします。左のペインのコンテキストに、「todo」が追加されたと思います。何か操作を間違えた場合は、この todo のコンテキストを右クリック、削除してから、最初から設定しなおすことが出来ます。

新規コンテキストの設定確認
新規コンテキストの設定確認

次に、OWASP ZAP のウィンドウの左上の「標準モード」を「プロテクトモード」に変更します。この設定は OWASP ZAP を終了させても維持されています。

プロテクトモードに変更
プロテクトモードに変更

プロテクトモードに変更することにより、脆弱性診断を設定したコンテキストにのみ対象とすることが出来るようです。

続いて、セッションID名を設定します。ツール→オプション... で、Httpセッションをクリックし、追加をクリックします。トークン名に、「TODOSESSID」を入力して追加をクリックします。この設定も OWASP ZAP を終了させても維持されています。

セッションID名の設定
セッションID名の設定

さらに、アンチ CSRF トークンを設定します。同じく、ツール→オプション... で、アンチCSRF トークンをクリックし、追加をクリックします。トークン名に、「todotoken」を入力して追加をクリックします。この設定も OWASP ZAP を終了させても維持されています。

アンチCSRFトークンの設定
アンチCSRFトークンの設定

まだまだ設定が続きます。次は、自動ログインの設定です。Bad Todo にログインします。ログインすると、OWASP ZAP の左側のペインの todo フォルダに、POST:logindo.php というのが見つかると思います。この POST:logindo.php を右クリック→Flag as Context→todo : Form-based Auth Login Request をクリックします

この設定は、OWASP ZAP の自動脆弱性スキャンが、ログインする POSTリクエストを特定するために設定するのだと思います。

自動ログイン設定
自動ログイン設定

すると、たくさんの項目があるダイアログが開くので、Username Parameter * のところを、「userid」を選択し、Password Parameter * のところを、「pwd」を選択し、OK をクリックします

自動ログインの設定
自動ログインの設定

次に、左側のペインの todo フォルダの、先ほどの POST より下に、GET:todolist.php が見つかると思います。この GET:todolist.php を選択して、右側のレスポンスのペインから、<a href="logout.php" class=""> を探して、ドラッグして選択します。選択できたら、それを右クリックして、Flag as Context→todo : 認証ログイン表示をクリックします

この設定は、OWASP ZAP の自動脆弱性スキャンが、ログインが成功したかどうかを判定できるようにするために設定するのだと思います。

ログイン状態を検出させる設定
ログイン状態を検出させる設定

すると、以下のように、上で設定したダイアログに、追加で、Regex pattern used to identify Logged in messages に、\Q<a href="logout.php" class="">\E が設定されます。まだ OK は押さずに、続いて設定します。

ログイン状態を検出させる設定の確認
ログイン状態を検出させる設定の確認

左側のペインの、今設定していた 2: 認証 のすぐ下の 2: ユーザ を選択します。

書籍では、自動的にログインしたユーザが登録されているような記述になっているのですが、実際にやってみると、ユーザは登録されていませんでした。なので、自分で登録します。

右上の追加をクリックし、ユーザ名を入力(たぶん任意だが、念のためログインするユーザID と同じにしておく)し、Username にログインするユーザID、パスワードにログインパスワードを入力して、追加をクリックします。

ユーザ追加
ユーザ追加

左側のペインの、2: ユーザ のすぐ下の 2: 強制ログインユーザ を選択します。すると、上で追加したユーザが表示されていることを確認して、OK をクリックして設定を閉じます。

強制ログインユーザの確認
強制ログインユーザの確認

これで設定は終わりました。

自動脆弱性スキャンのクローニング

自動スキャンを行うにあたり、対象サイトを自分で巡回する必要があるようです。そうすることにより、OWASP ZAP が、対象サイトのページに遷移するの URL と、パラメータを記憶するようです。

あまり分かってませんが、とにかく、ポチポチとリンクをクリックして巡回してみます。最初なので、Todo の登録や、マイページのプロフィールの変更などはせずに、あくまでリンクを辿るだけにしてみます。

一通り巡回が終わったら、OWASP ZAP の左上のコンテキストの「todo」を右クリックして、Export URLs for Context(s) をクリックして、任意の場所にクローニング結果を保存しておきます。

クローニング結果の保存
クローニング結果の保存

私の結果を貼っておきます。

https://example.jp/todo
https://example.jp/todo/export.php
https://example.jp/todo/icons
https://example.jp/todo/icons/_64_66ba0e1aac3d2-2024-08-03_15h28_57.png
https://example.jp/todo/import.php
https://example.jp/todo/index.html
https://example.jp/todo/inquery.php
https://example.jp/todo/login.php?url=todolist.php
https://example.jp/todo/logindo.php
https://example.jp/todo/mypage.php?rnd=66bb61e9e988a&id=3
https://example.jp/todo/newtodo.php?rnd=66bb61e042f60
https://example.jp/todo/todolist.php
https://example.jp/todo/todolist.php?key=pen
https://example.jp/todo/todolist.php?rnd=66bb61ef5761c

このファイルはインポートすることが出来ます。再診断するときに、また巡回するのは大変なので、このファイルをインポートします。インポート→Import a File Containing URLs で、ファイルを選択すればインポートできます。

これで、ようやく自動診断が出来るようになりました。

後ろの方で述べてますが、この時点で、セッションを保存するといいかもしれません。うまくいけば、再診断するときに、保存したセッションを使えば、同じ状態の診断が出来るかもしれません。

自動脆弱性スキャンの自動クローニング(スパイダー)

徳丸本でも言及がありますが、クローニングについては、OWASP ZAP のスパイダーという機能を使って、自動で巡回させることが出来ます。ただし、スパイダーは万能というわけではないので、漏れがないようにするには、自分で巡回するのが確実とされています。

では、スパイダーを使ってみます。スパイダーを実行するタイミングは、手動で巡回するタイミングと同じです。

todo フォルダを右クリックして、攻撃→スパイダー... をクリックします。

スパイダーの実行
スパイダーの実行

確認画面が出るので、ユーザを選択して、スキャン開始をクリックします。

スパイダー実行の確認
スパイダー実行の確認

結構時間がかかります。スパイダーの実行が完了したら、手動で巡回した場合と同様に、OWASP ZAP の左上のコンテキストの「todo」を右クリックして、Export URLs for Context(s) をクリックして、クローニングの結果を保存しておきます。

スパイダーで巡回した結果です。手動より、多くの URL が検出できています。比較してみたところ、手動で巡回した URL は全て含まれていました。

https://example.jp/todo
https://example.jp/todo/
https://example.jp/todo/addtodo.php
https://example.jp/todo/attachment
https://example.jp/todo/attachment/66bdf1b17f4a1-shindan.txt
https://example.jp/todo/attachment/memo.txt
https://example.jp/todo/changeicon.php?id=3
https://example.jp/todo/changeicondo.php
https://example.jp/todo/changemail.php?id=3
https://example.jp/todo/changemaildo.php
https://example.jp/todo/changepwd.php?id=3
https://example.jp/todo/changepwddo.php
https://example.jp/todo/confirmuser.php
https://example.jp/todo/css
https://example.jp/todo/css/common.css
https://example.jp/todo/delfile.php
https://example.jp/todo/editdone.php
https://example.jp/todo/editlist.php
https://example.jp/todo/edittodo.php?item=3&rnd=66c198e796e0c
https://example.jp/todo/export.php
https://example.jp/todo/exportdo.php
https://example.jp/todo/icons
https://example.jp/todo/icons/_64_66bdf1306124b-2024-08-03_15h28_57.png
https://example.jp/todo/icons/_64_elephant.png
https://example.jp/todo/icons/_64_ockeghem.png
https://example.jp/todo/import.php
https://example.jp/todo/importdo.php
https://example.jp/todo/index.html
https://example.jp/todo/inquery.php
https://example.jp/todo/inquerydo.php
https://example.jp/todo/login.php?url=todolist.php
https://example.jp/todo/logindo.php
https://example.jp/todo/logout.php
https://example.jp/todo/mypage.php?id=3&rnd=66c198e883080
https://example.jp/todo/newtodo.php?rnd=66c198e883080
https://example.jp/todo/newuser.php
https://example.jp/todo/quit.php?id=3
https://example.jp/todo/quitdo.php
https://example.jp/todo/resetpwd.php
https://example.jp/todo/resetpwddo.php
https://example.jp/todo/todo.php?item=3&rnd=66c198e807b94
https://example.jp/todo/todolist.php
https://example.jp/todo/todolist.php?key=ZAP
https://example.jp/todo/todolist.php?rnd=66c198e883080

自動脆弱性スキャンの実行

自動診断を実行する前に、強制ログインモードを選択しておきます。下図のように、ツールバーのカギのアイコンをクリックして、カギがかかった状態にします

カギがかかった状態にしたままだと、OWASP ZAP を普通に使うときに、挙動がおかしくなるので、自動診断が終わったらカギのかかってない状態に戻します。

強制ログインモードを選択
強制ログインモードを選択

では、自動診断を実行します。

左側のペインの todo フォルダを右クリックして、攻撃→動的スキャン... をクリックします。

自動脆弱性スキャンの実行
自動脆弱性スキャンの実行

スキャン内容の確認の画面になります。ユーザーが空欄になっているので、先ほど設定したユーザを選択して、スキャンを開始をクリックします。これで、自動脆弱性スキャンの実行が開始されます。

自動脆弱性スキャンの開始
自動脆弱性スキャンの開始

画面の下の方に、現在の進捗状況が表示されます。

自動脆弱性スキャン中の画面
自動脆弱性スキャン中の画面

進捗が 100% になると、スキャンが完了しています。アラートをクリックして、一番左にある的(マト)のようなアイコンをクリックして、赤くします。これにより、今回のコンテキストのアラートだけが表示されるようになります。25件が検出されたようです。

自動脆弱性スキャンの診断結果
自動脆弱性スキャンの診断結果

自動脆弱性スキャンの結果

25件のアラートが、どういう内容で、どうやって、この脆弱性が見つかったのかは、まだ分かっていませんが、とにかくレポートを生成させてみます。コンテキストで「todo」を選択した状態で、レポート→Generate Report ... をクリックします。

レポートの生成
レポートの生成

すると、確認画面が出るので、Generate Report をクリックします。

レポート生成の確認画面
レポート生成の確認画面

生成された HTML ファイルをダブルクリックして、表示してみます。立派なレポートが出来ていました。

レポートのトップページ
レポートのトップページ

このレポートは、いろいろ見てみたのですが、今回の診断結果の詳細が書かれているというよりは、今回検出した脆弱性について、たくさん解説してくれているというレポートでした。それはそれで必要ですが、具体的にどの診断で、どういう脆弱性だったかは、レポート見るだけでは分からないものでした。

よって、結果の分析には、OWASP ZAP が起動した状態で、アラートを詳しく見る必要があるようです。脆弱性スキャンを毎回やるのは大変なので、現在の状態を保存しておきたいところです。

OWASP ZAPの状態(セッション)の保存方法と復元方法

OWASP ZAP は、セッションという形で、状態を自動で保存してくれています。「ファイル→セッションデータを開く...」で、保存したセッションを指定すると、脆弱性スキャンが完了した状態に復元してくれます。

自動でセッションを保存した場合のセッションの置き場所は、デフォルトでは ~/.ZAP/sessions/ に保存されています。

明示的に、自分でセッションを保存する場合は、「ファイル→セッションデータをファイルに保存」で保存できます。

Bad Todoのデータベースが壊れたときの復旧方法

OWASP ZAP の自動脆弱性スキャンを行うと、たまに、フリーズして動かなくなる時があります。再起動してみると、データベースが壊れているときがありました。

そこで、データベースの復旧方法をここにメモしておきます。

Bad Todoのデータベースのエクスポート

まず、既存のデータベースをエクスポートします。私の場合、既に壊れた後だったので、もう一度、OVAファイルをインポートして、別の wasbook を起動して、そこからデータベースをエクスポートしました。

Bad Todo で使われているデータベースは MySQL で、root のパスワードは、wasbook でした。

以下の1コマンドでエクスポートできます。(MySQL の)root のパスワードを聞かれるので、wasbook と入力してください。

$ mysqldump -u root -p todo > ./todo.db

この出力した todo.db がデータベースファイルで、後でインポートするときに使います。

Bad Todoのデータベースのインポート

ちょっと面倒ですが、既存のデータベース(todo という名前です)を削除して、同じ名前(todo)で新規にデータベースを作成し、そこにインポートする、という流れになります。

MySQL にログインして、既存のデータベース(todo)の削除、新規データベース(todo)の作成を行います。

$ mysql -u root -p

> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| phpmyadmin         |
| roundcube          |
| todo               |
| wasbook            |
+--------------------+

> drop database todo;

> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| phpmyadmin         |
| roundcube          |
| wasbook            |
+--------------------+

> create database todo;

> exit

最後に、エクスポートしたデータベースファイルをインポートします。

$ mysql -u root -p todo < todo_org.db

Bad Todoのデータベースの復旧の手順は以上です。

おわりに

今回は、自動脆弱性スキャンをやってみました。設定項目が多くて大変でしたが、実際に設定してみると、何となく何を設定しているのかは理解できた気がします。

実際に見つかった脆弱性については、今後、内容の分析と、再現、対策を行っていきたいと思います。

今回は OWASP ZAP のロゴを使わせていただきました。OWASP ZAP は自動スキャンなど高機能ですが、なかなか扱いが難しいです。普段の解析は Burp Suite の方がやりやすいです。

最後になりましたが、エンジニアグループのランキングに参加中です。

気楽にポチッとよろしくお願いいたします🙇

今回は以上です!

最後までお読みいただき、ありがとうございました。