Dr.セキュリティ®

脆弱性診断のやり方④
Webサイト(Webアプリケーション)

この記事を書いた人

Dr.セキュリティ®
代表技術者 冨田 圭介

DFプロ認定資格保有
① CDFP-B(基礎資格)
② CDFP-P(実務者資格)
脆弱性診断士資格保有
冨田 圭介

2種類の方法をご紹介

Webサイト(Webアプリケーション)に対するスーパー簡易的な脆弱性診断のやり方として、当記事では下記の2つの方法をご紹介します。

  • ①【素人向け】表層解析(脆弱性情報の検索)
  • ②【エンジニア向け】アクセス制御の不備の脆弱性診断
上記の①番は、Web開発で使用されることが多い下記のような物の脆弱性を、ざっくり簡易的に調べられる方法です。
  1. フレームワーク
  2. ライブラリ
  3. Wordpressやそのプラグイン
  4. その他のOSSやフリーウェア等

②番は、この記事を書いている時点(2024年10月)での最新版である「2021年版のOWASP Top 10」において、深刻度がランキング1位の脅威となった「アクセス制御の不備」に関する脆弱性に対するスーパー簡易的な診断方法です。

なお、①②のどちらもWebサイトの制作者本人に向けた内容となっています。当記事は、自分の制作物に脆弱性が潜在していないか不安を感じたときに、スーパー簡易的に診断できる方法の紹介を目的としています。他人のWebサイトを診断するようなシーンを想定していませんので、①②のどちらも制作者本人でなければ実行できないことをご了承下さい。

それでは以降で①②それぞれのやり方をご説明します。

①【素人向け】表層解析(脆弱性情報の検索)

概要

Webアプリケーション開発やWebサイト制作においては、開発・制作効率を高めるために様々なオープンソースソフトウェア(OSS)が活用されています。例えばフレームワーク、ライブラリ、Wordpressやそのプラグインなどです。このページでは便宜のために、以下でそれらのソフトウェアのことを全てまとめて「OSS等」と言います。

OSS等は開発が盛んなのでどんどんバージョンアップしていきますが、それが故に新しい脆弱性が発生する確率は高く、頻度も多く、それに伴ってOSS等の脆弱性を突くサイバー攻撃が起こる確率も高く、頻度も多いです。平たく言うと「攻撃者が好んで標的にする」という感じです。そのためOSS等を使用する際には脆弱性のリスクに気をつける必要があります。

ここではOSS等に脆弱性があるか否かを確認するために、脆弱性情報のデータベースを製品型番で検索してみる、という脆弱性診断の方法を説明します。
大まかな流れは次の通りです。

  1. OSS等のバージョンをメモする
  2. 脆弱性情報のデータベースを検索する
  3. 検索結果を確認する
  4. 検出漏れを防ぐためにWeb検索も併用する

Step.1 OSS等のバージョンの確認

開発に用いているOSS等やWebサイトで使用しているOSS等のうち、脆弱性診断したいものをリストアップし、それぞれのバージョンをメモに記して下さい。

Step2. JVN iPediaで検索

「JVN iPedia」とは、平たく言うと脆弱性の情報を無料で閲覧・検索できるサービスです。
【URL】https://jvndb.jvn.jp/

「脆弱性対策情報データベース検索」という部分(下の画像の赤枠部分)に、OSS等の名称を入れて検索すると、当該製品の脆弱性がJVNに登録されているか否かを確認できます。

Step3. JVNの検索結果を確認


上の画像のように、検索結果に「該当するデータがありません。」と表示された場合は、JVNのデータベースには当該OSS等の脆弱性情報が登録されていないことを示しています。この場合は「OSS等の脆弱性」は問題無さそうだと判断できますが、しかしこの段階ではまだ断定しません。(後述のStep4でもう少し検索してみます)

続いて、OSS等に脆弱性がある場合の例をご紹介します。

上の画像のように、検索結果に当該OSS等が表示される場合は、それ自体に脆弱性があることを示しています。(この例では Apache HTTP Server を検索しました)
各行の先頭列の「JVNDB-」で始まるリンク部分をクリックすると、その脆弱性の情報を閲覧できます。


上の画像は脆弱性情報の中にある、「影響を受けるシステム」の項目の部分です。
この例を見ますと、「2.4.0以上2.4.60未満」と表示されています。これはその文言のとおり、このプログラムのバージョンが上記の範囲である場合は脆弱性があることを意味しています。

Step1でメモしたバージョンが上記に該当する場合は「脆弱性がある」と判断し、その範囲外である場合は「脆弱性は無い」と判断します。

【補足】
脆弱性のページの中に「共通脆弱性識別子(CVE)」という項目がある場合は、そこに表示されているCVE識別番号を念の為メモしておくと良いです。そうする理由は、当該脆弱性に対する対処方法を探す(Web検索する)際に役立つことがあるからです。

【重要】けっこう間違えがちなこと

下記の2つのバージョンは、どちらが新しいバージョンですか?

  • 1.23.4
  • 1.5.67
この問いに対して、「1.5.67」と答える人が結構います。
それは誤りです。
正解は、1.23.4の方が新しいバージョンです。

間違える理由は、ピリオドを無視して連続する数値だと解釈しているからです。算数のように「左側が大きい桁で、右に向かって10の位が下がっていく。」というように解釈すると誤った答えとなります。
  • 1234
  • 1567
こう見ると1567の方が数値が大きいから、1.5.67の方が新しいバージョンだ、というように間違えてしまうわけです。

バージョンの数値は連続する数値ではありません。ピリオドで区切って解釈して下さい。
「1 . 23 . 4」は、1、23、4に分けて読んでください。

左側の1は、「メジャーバージョン」というバージョンを表す値です。
真ん中の23は、「マイナーバージョン」というバージョンを表す値です。
右側の4は、「パッチバージョン」というバージョンを表す値です。

このようにして「1.23.4」と「1.5.67」を比べると、どちらも左のメジャーバージョンは1で同じです。
続いて真ん中のマイナーバージョンの値を比べると、前者は23で、後者は5です。23の方が5よりも大きい、つまり新しいマイナーバージョンということになります。
よって「1.23.4」と「1.5.67」を比べると、「1.23.4」の方が新しいです。

Step4. Web検索してみる

JVN iPediaで型番を検索しても該当する製品がなかった場合でも、念の為Google等で「ソフトウェア名 + 脆弱性」をキーワードにして検索してみると良いです。
なぜそうするかと言うと、一般的な呼称のソフトウェア名と、正式なソフトウェア名が異なる場合があるからです。

JVNでは正式名称で登録されているため一般呼称で検索してもヒットしない可能性があります。一方、Googleの検索結果は検索キーワードに完全一致するものだけでなく、似たようなキーワードのWebページも検索結果の一覧に表示されるので、JVNに登録は無いけれど、実は脆弱性があるかも? と気付けるかも知れないからです。

脆弱性を検出した場合

ほとんどの場合はソフトウェアをアップデートすれば良いです。ただしその時点の最新版でもまだ改善されていないこともあり、そのようなときは設定の調整などが必要となります。アップデートするだけで良いのか否かを判断するのは難しいので、OSSの公式サイトや「フォーラム」を確認してみると良いです。エンジニアの方にわざわざ説明するまでもない気がしますが、フォーラムとはユーザーや開発者が参加するコミュニケーションの場であり、そこでは当該OSSに関する様々な情報の共有や共助がおこなわれていますので、脆弱性に関する情報も得られると期待できます。また、有名なOSSの脆弱性はIT系のニュースサイトや個人ブログなどでも話題になりやすく、それらに対処方法が書かれていることもあります。それらの情報を探したいときは、「CVE識別番号」を検索キーワードにすると良いです。

②【エンジニア向け】アクセス制御の不備の脆弱性診断

概要

2021年版のOWASP Top 10では、最も深刻な脆弱性として「アクセス制御の不備」がランキング1位となっています。

【補足】
OWASP Top 10とは、Webアプリケーションのセキュリティに関する重大な脅威のうち、深刻度が高いものから順に選ばれた10種類の脆弱性のランキングです。これは「OWASP」というWebセキュリティ関連の非営利組織が選定するもので、数年おきの頻度で公表されています。

ランキングの決め方は、多数の企業や団体から提供されたデータをもとにして、脆弱性の発生確率や「悪用されやすさ」、「ダメージの大きさ」などを評価して決められているそうです。

概要

アクセス制御の不備だけを診断すれば大丈夫というわけではありません。他にも発生確率や危険性が高い種類の脆弱性がランクインしています。特に3位の「インジェクション」は致命的な侵害に直結する強烈な脆弱性です。また5位の「セキュリティの設定ミス」も発生確率はやや高く、OWASPの統計では最大発生率が19.84%となっています。ほか2021年版で初登場10位となった「SSRF」は、本来は到達できないはずの領域にもリーチし得る危険性を持っており、今後は増加する可能性もあるとのとこで注目されています。

このように複数の種類の脆弱性があるなかで、今回ご紹介する「アクセス制御の不備」の診断だけで十分だとは言えません。しかしインジェクション攻撃の脆弱性診断を素人がやるのは危険ですし(ミスるとデータ破壊が起こり得ます)、その他のものは個別の環境毎に診断内容は大きく異なりますし、いずれもスーパー簡易的に脆弱性診断するのが難しいです。そのため当記事では、ランキング1位の「アクセス制御の不備」だけに絞ることとしました。これだけで十分ではないとしても、1位の脆弱性なのですから、これを検出するだけでもWebサイトの安全確保には相当に寄与できるはずです。

【予備知識①】アクセス制御の不備とは

大まかに言うと、
『特定のユーザーだけにアクセスを許可しているページやデータに関して、そのユーザー以外の者がアクセスできるようになってしまう脆弱性』 です。

例えば、とあるユーザーの個人情報が含まれるページを別のユーザーが閲覧できてしまうとか、Webサイトの管理者だけがアクセスできるページに攻撃者がアクセスできてしまう、というような脆弱性です。

【予備知識②】アクセス制御の不備が引き起こす問題

この脆弱性は、例えば下に挙げるような問題を引き起こします。

  • Webサイトの管理機能を攻撃者が利用できてしまい、情報漏洩する、Webページが改竄される、Webサイトを乗っ取られるなど。
  • 通販サイトや予約サイトなどといった会員制のWebサイトの場合、ユーザー情報や購入履歴・利用履歴などのページに他人がアクセスできてしまい、個人情報やプライバシーが情報漏洩する。
  • データベース関連の箇所でこの脆弱性がある場合、顧客情報などの営業秘密データに攻撃者がアクセスできてしまい、情報漏洩する、データを削除されるなど。
上記は極めて危険な例です。その他にも、例えば「数量限定の特売品を無限に購入できてしまう」とか、「虚偽の予約や注文により業務妨害される」というようなリスクもあります。

【予備知識③】アクセス制御の不備が生じる箇所

この脆弱性は、アクセスの許可・拒否などを制御する箇所において、「Webブラウザから送信される値」を未検証のまま使用している場合に発生します。ここで言うWebブラウザから送信される値とは下記のようなものです。

  • URLのクエリストリング
  • フォームからPOSTされたパラメータ
  • Cookieに保存された値
上記の例の①番は、例えば「sample.php?user_id=1001」というようにクエリストリングでuser_idの値を受け取り、その値に基づいて表示内容を切り替える、というような仕組みになっているプログラムにおいて発生し得ます。このuser_id=1001user_id=1002に書き換えてリクエストしたとき、別のユーザーの情報が表示されてしまうのがこの脆弱性です。

ほか、次のようなプログラムの場合でもこの脆弱性は発生し得ます。

  • 「sample.php?bool=false」というように、True/Falseの値でアクセス制御しているとき。
  • 「sample.php?role=2」というように、数値などで権限を分けて制御しているとき。(role=0は管理者、1は編集者、2は一般ユーザー、など。)
falseをtrueに書き換えるとか、2を1または0に書き換えるなどすれば、アクセス権限を詐称できてしまいます。(正確に言うと権限を「制御するための値」を詐称できてしまいます)

続いて②番(フォームからPOST)の場合。

このようにPOSTのパラメータの値を受け取ってアクセスを制御する、というような仕組みになっているプログラムにおいて脆弱性が発生し得ます。

最後、③番(Cookie)の場合も①②と同様で、Cookieに保存されている値に基づいてアクセス制御をおこなっているプログラムで脆弱性が発生し得ます。
要するに、クエリストリングやPOSTパラメータなど、ユーザー側で書き換えることができる箇所の値」に基づいてアクセス制御をおこなってはダメということです。もしどうしてもそのような値を使用しなければならない場合には、受け取った値を検証してセッション状態や権限に矛盾がないか判定するようにプログラミングする必要があります。

スーパー簡易的な診断方法

ソースコードを確認するのが一番簡単で手っ取り早いです。
具体的な手順は後述しますが、簡単に言うと次のような流れになります。

  1. 診断対象のソースコードをキーワード検索する。
  2. インクルードがある場合はそのソースコードもキーワード検索する。
  3. 検索で見つかった部分の処理内容を読み、アクセス権限を検証する処理がおこなわれているか否かを確認する。

通常、診断会社がおこなう脆弱性診断ではこのような検査はおこないません。診断会社の場合は「診断ツールを使用して、リクエスト&レスポンスの内容を解析する」という検査方法を用います。診断ツールの使い方は単純ではなく、しかも原理をきちんと理解したうえで作業しないとWebサイトのデータを破壊してしまうリスクがありますので、それは「スーパー簡易的」とは言えません。そのため当記事ではツールを使用せず、ソースコードを確認する方法を説明することとしました。脆弱性診断の専門知識がなくてもプログラマーなら誰でも簡単にできる方法ですので、ぜひお試し下さい。

Step1. ソースコードの内容を検索する

ここでは、Webアプリケーションにおいて断トツでシェアが多いプログラミング言語である「PHP」を例にして説明します。

  • $_GET
  • $_POST
  • $_COOKIE
これらのようなWebブラウザから送信された値が入る変数のことを、以下では「スーパーグローバル変数等」と言います。このスーパーグローバル変数等をキーワードにして、ソースコードを検索して見て下さい。

【参考例】
find . -name "sample.php" | xargs grep '\$_GET'

上記の参考例は、カレントディレクトリにある sample.php に対し $_GET という文字列で正規表現検索するコマンドです。LinuxのWebサーバーにおいてソースコードの内容を検索する場合は、このコマンドを参考にしてスーパーグローバル変数等が含まれているか否か検索してみて下さい。
サーバーにアップされているソースコードではなく、ローカルPCに保存しているソースコードを確認する場合には、普段からご使用されているエディターソフトに備わっている検索機能でスーパーグローバル変数等を検索して下さい。

そしてもし検索にヒットする箇所が有った場合は、その値がどのように使用されているかを次のStep.2以降で確認します。

もし検索にヒットする箇所が無い場合は、次のStep.2と3を飛ばして、Step.4へ進んで下さい。

Step2. 検証の有無のチェック

プログラムがスーパーグローバル変数等の値を受け取った後、その内容を検証してから使用しているのか、あるいは未検証のまま使用しているのかを確認して下さい。

【例1】
SELECT * FROM テーブル名 WHERE ID = '" . $_GET["user_id"] . "'

この例のようにスーパーグローバル変数等を未検証でSQL文に直接放り込んでいるような場合は、かなり高い確率でアクセス制御の脆弱性がありそうです。しかもそれだけでなく、より凶悪なSQLインジェクションの脆弱性もありそうです。

【例2】
if ( $_GET["role"] == "1" ) {

この例のようにスーパーグローバル変数等を未検証で条件分岐に使用している場合は、かなり高い確率でアクセス制御の脆弱性がありそうです。

【例3】
$argument = $_GET["role"];

この例のように一旦変数に代入していても、その変数が例1・2のように使用されている場合は未検証ですので、この場合も脆弱性がある可能性はかなり高いです。

Step3. 検証内容のチェック

function validation($arg){
    //検証内容の処理
    return $arg;
}
$argument = validation( $_GET["role"] );

このような形で、プログラムに渡されたスーパーグローバル変数等の内容が検証されている場合には、その検証内容をご確認下さい。
下記のようにアクセス権限の正当性がきちんと検証されていれば問題ありません。

  • 渡されたユーザーIDが、アクセス元のユーザーのIDと合致するか否かをきちんと検証している。
  • 渡されたBooleanやroleの値が、アクセス元のユーザーに設定されている権限と合致しているか否かをきちんと検証している。
もしこのような検証ではない場合。例えば数値型/文字列型の判定やデータサイズの判定などといった単純なバリデーションだった場合には、アクセス権限の面では未検証のままですので、脆弱性がある可能性が高いと考えられます。

Step4. インクルードされているファイル等も確認

診断対象のphpファイルを検索&確認した後は、そのphpファイルにインクルードされている他のphpファイルがあるか確認してください。

include("assing.php");

上の例のようにインクルードがある場合には、そのphpに対してもStep.1から3までのチェックをおこなって下さい。

【言葉の定義】

  • インクルードする側のphpを、以下では「インクルード元php」と言います。
  • インクルードされる側のphpを、以下では「被インクルードphp」と言います。

Step5. インクルード元phpのソースコード検索

Step.4では被インクルードphpをチェックしました。もしそこでスーパーグローバル変数等の値を代入した変数があり、かつそれを検証する仕組みになっていない場合には、その変数がインクルード元phpで使用されているかどうか確認して下さい。

例えば被インクルードphpにおいて、「$argument」という変数に未検証の値が代入されている場合は、インクルード元phpにおいて、SQL文やif文の中で「$argument」が使用されているか否かをご確認下さい。

SELECT * FROM テーブル名 WHERE ID = '" . $argument . "
if ( $argument == "1" ) {

このように、被インクルードphpでもインクルード元phpでも未検証のまま「$argument」が使用されている場合は、脆弱性がある可能性が高いと判断できます。
なお、インクルード元のphpは複数あることも多いかと思います(一つの被インクルードphpを複数のphpで共用するなど)。その場合は該当する全てのphpのソースコードを同様に確認して下さい。

難しそうに感じるかも知れませんが、実際にはとても簡単です。

Step.1~5までを文章で読むと難しそう&面倒くさそうと感じてしまうかも知れませんが、実際にやっていることは「ただのテキスト検索」ですので、とても簡単です。

  • $_GETなどのキーワードがphpに含まれているかを検索する。
  • インクルードしているphpも同様に検索する。
  • キーワードが含まれている場合は、その箇所の処理内容を読む。
ただこれだけのことですので、プログラマーならば誰でもサクッとできるはずです。

要注意事項

Step.2の説明において赤文字で強調しましたが、SQLに未検証の値が使用される場合は、アクセス制御の不備の問題だけでなく、より危険なSQLインジェクションの脆弱性がある可能性が高いです。

また、exec()など外部プログラムを使用する箇所で未検証の値が使用される場合は、これも非常に危険なOSコマンドインジェクションの脆弱性がある可能性が考えられます。

もしそういう安全性の低いプログラムになっている場合、セキュリティをあまり意識されずに作られたことが明白ですので、当該Webサイトには他の種類の脆弱性も沢山あるだろうと予測できます。ですので、なるべく早く当社のような専門会社による脆弱性診断サービスをご依頼頂いたほうが良いです。

また、既に不正アクセスや情報漏洩等があるかもしれないという場合には、被害確認等のためのデジタル・フォレンジック調査もご検討下さい。

関連ページ