Loading
BLOG 開発者ブログ

2025年12月16日

WEB開発者のための脆弱性診断入門

優れた開発者は、自身のソフトウェアが安全に稼働するところまで責任を持つべきでしょう。
しかし残念ながら、脆弱性は開発中の試験では見落とされやすく、完成後に発覚しがちです。
この問題を解決する近道は、開発者に攻撃側の視点を少しだけ取り入れるところにあります。

本記事の内容は、自身で開発しているWEBアプリケーションに対する試験の一環として行うことを前提としています。
自身で管理する以外の対象へ許諾なしに診断を行うと不正アクセスと見做され、法律違反となりますので絶対に行わないでください。

WEB開発者のための脆弱性診断入門

目次

はじめに

こんにちは。アイソルートのhirokawa.yです。
今年もいつの間にか年の瀬になり、いよいよ寒くなってきましたね。皆さんも体調には気をつけてください。
実はサイバーセキュリティの世界でも、年末年始は特に警戒が必要な時期と言われています。

参考:2024年度 年末年始における情報セキュリティに関する注意喚起 | 情報セキュリティ | IPA 独立行政法人 情報処理推進機構

最近でもReact2Shellと呼ばれる重大な脆弱性が公表されており、その対応に追われている人も多いのではないでしょうか。
この件に限らず、自分の開発したアプリケーションをサイバー攻撃の被害から守るには日頃からの予防が大切です。
そこで今回は、WEB開発者が行うべき脆弱性診断の入門編をお届けします。

この記事は アイソルート Advent Calendar 15日目の記事です。

脆弱性診断が必要な理由

ソフトウェア開発では、不具合を早く見付けられるに越したことはありません。
完成してから発見したバグは、たとえ些細なものでも修正の影響範囲が大きくなってしまうからです。
学生の頃、試験終了の5分前に「あれ、解答欄がズレてる…」と気が付いたときの状況に似ています。

ところが、セキュリティの問題は完成した後に発見されることが多いのです。
理由は単純で、開発中に行う試験は機能テストを重点的に実施しているからです。
つまり「想定した入力をすれば、正しい結果が返ってくるか」を確認するわけです。

しかし、サイバー攻撃で用いられるのは開発者が想定していないような複雑な手口です。
開発中の試験で、そのような突飛なテストを行うのは現実的ではありません。
だからこそ、専門家による攻撃者目線での脆弱性診断が必要とされています。

一般的に、第三者による診断では「ブラックボックス診断」という手法が使われています。
システムの仕様を一切知らない状態で、外から見える情報だけを頼りに推測を重ねて穴を見つける方法です。
実際の攻撃者も同じ条件のため、サイバー攻撃の手口が複雑化するのは当然と言えます。

こうしてみると、脆弱性診断士は開発者よりも不利な条件で脆弱性を見つけなければなりません。
裏を返せば、開発者自身が脆弱性を発見できるなら、それが一番の近道なのです。
今回は忙しい人でも出来る簡単な診断の方法を紹介するので、一緒にやってみてください。

 診断環境の準備

まずは、診断を行うための環境として定番のKali Linuxを用意します。
お使いの環境がWindows 11の場合、次のコマンドを実行することでWSLのKali Linuxを導入できます。

$ wsl --update --pre-release
$ wsl --install kali-linux

 

また、WEBアプリケーションの診断を行うために定番のOWASP ZAPを用意します。
無償で制限なくアクティブスキャンを行うことが出来るため、今回の用途には十分です。
次のコマンドをKali Linuxのターミナルで実行してください。

$ sudo apt update
$ sudo apt install zaproxy firefox-esr

 

最後に、診断を実施する対象となるサービスを用意する必要があります。
ここでは、DVWAという非常に脆弱な「やられアプリ」を使用します。もちろん、ご自身のアプリを使っても構いません。
Dockerで簡単にデプロイできるため、次のコマンドもKali Linuxのターミナルで実行してください。

$ sudo apt update
$ sudo apt install docker.io docker-compose
$ git clone https://github.com/digininja/DVWA.git
$ cd DVWA
$ sudo docker compose -f compose.yml up -d

 

スキャンの手順

第三者が所有するサービスに対して脆弱性診断を行う際は、規約に基づいて細心の注意を払う必要があります。
しかし、自身で開発しているアプリに対する診断であれば、自己責任の下で自由に行うことができます。
もし壊してしまっても復旧できるように、事前にバックアップを取ることだけは決して忘れないでください。

アプリを徹底的にスキャンする際の手順は、大まかに以下のような流れになります。
1. 診断対象を設定して他のURLをスキャンしないように制限する
2. 診断対象のファイルやディレクトリを探索する
3. 発見したパスに対してアクティブスキャンを実行する

開発環境とはいえ、意図しない対象をスキャンしないように設定することが大切です。
それでは、心構えが出来たところで、次のコマンドでZAPを起動しましょう。

$ zaproxy

ZAPが起動すると、最初にセッションの保存方法を訊かれるため、任意の名前でセッションを保存します。
次回起動するときは、保存したセッションを使用して続きからスキャンを再開することができます。

次に、アドオンを更新するか訊かれるため「Update All」をクリックして最新版に更新します。
今回の診断ではアクティブスキャンという自動診断の機能を使うため、スキャンルールを最新にしておくことが重要です。

ZAPのメイン画面が開いたら、ツールバーにあるFirefoxのアイコンをクリックすることでブラウザが開きます。
開いたブラウザでWEBアプリにアクセスすると、その通信の内容をZAPで確認することができます。
早速「http://localhost:4280」にアクセスして、先ほど用意した「やられアプリ」を開いてみましょう。

(おっと、ログインが必要なアプリですね…)

左側パネルの「Sites」にURLが、下側パネルの「History」に通信内容が、それぞれ表示されます。
そして、確認したいURLを選ぶことで、中央パネルに通信内容が表示されます。

ブラウザを使って軽くサイトを観察したら、本格的なスキャンに進む前に診断対象の絞り込みをしましょう。
まず、メニューバーから「Edit」→「ZAP Mode」→「Protected Mode」を選択します。
このモードにすることで、コンテキストに登録していないサイトがスキャンから保護されるようになります。

次に、「Sites」内の「http://localhost:4280」を右クリックして「Include in Context」→「New Context」を選択します。
コンテキストに追加すると、設定画面が表示されます。
殆どはデフォルトで構いませんが、あらかじめ認証情報を登録しておきましょう。
先ほど偵察したようにログインが必要なアプリでは、認証を成功させないと肝心な部分のスキャンが行えません。

メニューから「Authentication」へ進み、認証方式に「Form-based Authentication」を選択します。
ユーザ名とパスワードを入力してPOSTするサイトであれば、基本的にこれを選べば間違いありません。
その後、ログイン処理を行うURLと、実際にPOSTするパラメータを入力します。

URL:http://localhost:4280/login.php
パラメータ:username={%username%}&password={%password%}&Login=Login

次に、メニューから「Users」へ進み、ユーザ名とパスワードの組を追加します。
「Add」をクリックしてDVWAのデフォルトユーザを入力します。
このとき、必ず「Enabled」にチェックを入れてください。

ユーザ名:admin
パスワード:password

これで準備は完了です。いよいよスキャンを開始しましょう。
最初にパス探索を行う必要がありますが、これには2種類の方法があります。
静的リンクを辿る「Spider」と、ブラウザ操作によって動的リンクを辿る「AJAX Spider」です。

どちらを使えば良いかというと、サイトの実装方法にも依りますが、両方とも実行しておくのが確実です。
まずは「Contexts」内の「http://localhost:4280」を右クリックして「Spider」を選択します。
使用するユーザに先ほど登録した「admin」を選んだら「Start Scan」でパス探索を行います。

続けてもう一度「Contexts」内の「http://localhost:4280」を右クリックし、今度は「AJAX Spider」を選択します。
使用するユーザに「admin」を選んだら「Start Scan」でパス探索を行います。

上手くパスを検出できたら、それらに対してスキャンを実施します。
「Contexts」内の「http://localhost:4280」を右クリックし、「Active Scan」を選択します。
先ほどと同様に使用するユーザに「admin」を選び、「Show Advanced Options」にチェックを入れます。
「Policy」タブで「Attack Threshold」を「Low」に、「Attack Strength」を「High」にしてからスキャンを開始します。

進捗バーが100%になったら、レポートを出力して結果を確認しましょう。
・メニューバーから「Report」→「Generate Report」を選択
・「Scope」でスキャンしたURL(http://localhost:4280/login.php)を選択
・「Template」で出力形式を「Traditional HTML Report」を選択

(SQLインジェクションが見つかった!)

おわりに

この記事で紹介したアクティブスキャンは、攻撃手法を全く知らなくても診断を行うことが可能です。
このような診断方法では、想像以上に多くの検出事項が上がってくる場合もあります。
プロの脆弱性診断士であれば、攻撃の原理を理解し、その実現性を立証した上で報告することが求められます。

その一方で、WEBアプリケーションの開発者が気を付けなければならないのは、
利用している言語やフレームワークが提供している安全機能を正しく理解し、実装することです。
ZAPで検出された箇所とソースコードを照らし合わせて、見直しをしてみてください。

「この前提で、こう使えば安全」という条件を理解せず、「どんな場合もこの関数を使えば良い」
という思い込みで開発をしていると、知らないうちに脆弱性を作り込んでしまっている場合があります。
開発者が攻撃側の視点をほんの少し持つことで、そういったミスに対する気付きを得ることが出来ます。
その気付きによって、ソフトウェア開発の品質は格段に上がることでしょう。

また、今回の方法で検知できるのは基本的に「入力を変えると、挙動が変わる」脆弱性に限られます。
例えば、冒頭で挙げたReact2Shellのような、加工したリクエストによって引き起こされるサーバ内部処理の過程で
任意のコマンドが実行できる脆弱性は、レスポンス自体は正常に見えるため、今回のスキャンでは検知できません。
(と言いつつも、React2Shellは影響度合いが大きいため特別な対策が施され、既に検知可能になっています。)

当然、紹介した以外にも脆弱性を発見する様々な方法があり、それぞれに長所と短所があります。
その多くは専門知識を必要とするものですので、高度な診断が必要な場合はご相談ください。
その中で、開発者が取り入れやすい手法があれば、またご紹介していきたいと思います。

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

hirokawa.yのブログ