セキュリティ診断現場で見かける"ありがち脆弱性"トップ5 Web編

今回のブログでは、セキュリティ診断現場でよく見かける「ありがちな脆弱性」の上位5個を紹介していきます！

当社では、年間を通して多くのWEBアプリケーション診断を実施していますが、脆弱性によって「よく検出されるもの」と「あまり検出されないもの」があります。
XSSやSQLインジェクションなどの脆弱性の印象が強いWEBアプリケーションですが、実際の現場ではどのような脆弱性が検出されるのか、解説していきます。

### 想定読者

本記事は、WEBアプリケーション開発者や組織の防御を担当している方に、WEBアプリケーションで発生しやすい脆弱性とその原因、解決策を紹介する記事となります。また、普段WEBアプリケーション診断を実施している方やWEBアプリケーションセキュリティについて学習している方にも、読んでいただきたい記事となります。

### 脆弱性トップ5

それでは、脆弱性トップ5を紹介していきます！
よく検出される脆弱性の中でも特に検出が多い脆弱性は以下の通りです！

| 順位 | 脆弱性名 |
|:-:|:-|
| 1位 | クロスサイトスクリプティング（XSS） |
| 2位 | 認可制御不備 |
| 3位 | セッション管理不備 |
| 4位 | アップロード機能の不備 |
| 5位 | 詳細なエラー画面の表示 |

有名な脆弱性もありますが、現場ならではの脆弱性が多くランクインしています。
特に、2位以降の脆弱性は現場だからこそ検出される脆弱性の代表例とも言えます。

一方でSQLインジェクションやコマンドインジェクションのような脆弱性は、有名かつ明らかに危険度が多いことや自動ツールでの検出が用意であることから現場で検出されることは少ない傾向にあります。

ここからは、各脆弱性の概要と解説を行なっていきます！

### クロスサイトスクリプティング（XSS）

クロスサイトスクリプティング（XSS）とは、「**WEBアプリケーション内に悪意のあるスクリプトを注入し、ユーザのブラウザで実行させる攻撃**」です。
WEBアプリケーションが、ユーザ（攻撃者）からの入力を適切に処理（エスケープ）せずに、そのままHTMLとして表示すると、その入力内にあるスクリプトが実行されてしまいます。

例えば、攻撃者が以下のような入力を行ってきた場合を想定します。

```html
<script>alert(1)</script>
```

この入力がエスケープされずに、HTML内で表示された場合、ユーザのブラウザでスクリプトが実行され、アラートが表示されます。

![スクリーンショット 2025-04-05 8.55.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1664764/02436684-fed8-4445-9eb2-57d305834344.png)

アラートはXSSの発火を示す代表的な例ですが、XSSはアラートを表示させるだけでなく、以下のような攻撃を実行することも可能です。

| 狙い | 攻撃手法 |
|:- |:-|
| 機密情報の窃取　 | スクリプトにより、フィッシングページを表示させ、ユーザが入力した認証情報を窃取する。<br> ユーザのキーボード入力を監視し、入力された機密情報（クレジットカード情報や住所等）を取得する。|
| なりすまし | 認証済みのユーザにスクリプトを実行させ、ユーザのCookie（セッション情報）を取得する。 |
| WEBサイトの改ざん　　 | HTMLを書き換えて、フォームやリンク等、ページの内容を改ざんする。 |

複雑なスクリプトを作成することによって、機密情報の窃取やなりすまし、WEBページの改ざんを狙ってくるため、危険な脆弱性です。

**発生する原因**

では、なぜXSSが現場で多く検出されるのでしょうか。
それは以下のような原因が考えられます。

**1. 入力値のエスケープ漏れ**

XSSへの対策として、入力値のエスケープは非常に有名な対策ですが、多くのWEBアプリケーションでよく発生している事象として、「ほぼ全ての入力値はエスケープされていたが、一箇所だけエスケープが漏れていたことによって、XSSが発火した」というケースがあります。

:::note info
エスケープとは、特別な意味を持つ記号を無害化し、ただの文字として扱うことを指します。
例えば、ユーザから以下のような入力があったとします。
```html
<script>alert('XSS')</script>
```
上記の入力をそのまま出力してしまった場合、XSSが発生してしまいますが、エスケープ処理を実行することによって、以下のような形になります。
```html
&lt;script&gt;alert(&#039;XSS&#039;)&lt;/script&gt;
```
一見、本来の入力とは異なる文字に見えますが、WEB上には正常に表示されます。エスケープをすることによって、タグやシングルクォートがHTML内で特殊な記号として認識されなくなるため、脆弱性が発火することを防ぐことが可能です。
:::

XSSは、検索画面やコメント欄等の入力を反映する全ての画面で発生する可能性があります。手動で一つ一つエスケープを実装している場合、機能や画面が多くなれば多くなるほどエスケープ漏れが発生する確率が高くなります。

**2. 脆弱性の影響を軽視**

XSSが発生しやすい原因の2つ目として、脆弱性の影響が軽視されていることが挙げられます。実際に、現場で「クロスサイトスクリプティング（XSS）は特に緊急ではないですよね？」と、よく言われることがありますが、そんなことはありません。
確かに反射型のXSS（入力値が即座に反映され、スクリプトが保存されないタイプ）は、格納型のXSS（スクリプトが保存され、他のユーザが閲覧した時に実行されるタイプ）と比較し、危険度は劣ると思われていますが、その使い方次第では反射型のXSSでも認証情報の窃取やなりすましが可能です。

**対策**

XSSに対する対策としては、入力値に対するエスケープ処理を漏れがないように確実に実装することが重要です。しかし、機能や画面の多さによっては、全てを手動で実装することは難しいため、CSPによるXSS実行の防御やテンプレートエンジンによる自動エスケープなども非常に有効な対策となります。また、WAFを導入し、脆弱性の悪用を試みる攻撃を検知し遮断することでXSSが発生する可能性を軽減することも出来ます。
脆弱性の影響を軽視せずに、確実な対策を講じることが重要です。

### 認可制御不備

認可制御とは、「このユーザがこの操作を実行してもよいか」を制御するものです。
管理者ユーザと一般ユーザの違いを例にすると、WEBアプリケーションの管理画面へアクセスできるのは、管理者権限を持つユーザのみであり、一般ユーザは管理画面へアクセスすることはできません。このように「アクセスしようとするユーザが、当該画面へアクセスできるかどうか」を制御することが認可制御といいます。

例に挙げた管理画面の認可制御では、以下のようなコードが使用されます。

```php
<?php
if ($_SESSION['user_role'] !== 'admin') {
    echo "アクセス権限がありません。";
    exit;
}
```

上記のようなコードは基本的に、共通ファイルに記載し、管理者権限を必要とする各ページでは共通ファイルを読み込むことで認可制御を行います。
しかし、コードに不備があったりファイルの読み込みが行われていないページがある場合、認可制御の不備により一般ユーザでも管理者権限を必要とする画面や機能にアクセスすることが可能になります。

認可制御不備が悪用されると、以下のような影響があります。

:::note warn
一般ユーザの認証情報（権限）を窃取した攻撃者から、管理者の機能にアクセスされ、WEBアプリケーションの改ざんや情報漏えいに繋がる。
:::

:::note warn
他のユーザからプロフィール等にアクセスされ、住所やクレジットカード情報といった個人情報が公開される。
:::

認証情報を必要としない攻撃は、攻撃容易性が非常に高いため非常に危険です。

**発生する原因**

では、なぜ認可制御が現場で多く検出されるのでしょうか。
それは以下のような原因が考えられます。

**1. 見た目の制限で判断**

認可制御不備を報告するケースとして非常に多くみられるものが「リンクやボタンからはアクセスできないが、直接URLを入力したりファジングによってアクセスに成功する」というものです。
WEBアプリケーションの表示からボタンを削除したり、ボタンをクリックされたときにエラーメッセージを表示させる等、目で見える部分のみしかテストを行っていないと、制限できていると思っていても実は制御できていないといった状況に陥ってしまいます。

**2. 自動ツールでは検出が難しい**

認可制御が発生するもう一つの原因として、認可制御不備は自動ツールでは検出が難しい傾向にあることが挙げられます。これは自動ツールがロジックやルールを理解することが難しいためです。
そのため、WEBアプリケーションに対して自動ツールのみでテストを行っている場合は、認可制御不備の検出が出来ず、WEBアプリケーション診断時に検出することが多いです。

**対策**

認可制御不備に対する対策を行う際は、見た目による制御を行うのではなく、管理者権限を必要とする機能や画面に対して確実に認可制御を実装することが重要です。また、実装後は手動によるテストや外部ベンダーによるWEBアプリケーション診断を実施し、認可制御不備や実装漏れが本当に存在していないかどうかを確認することを推奨します。

### セッション管理不備

セッション管理不備とは、ユーザのログイン状態（セッション）の取り扱いに問題があることで発生します。
WEBアプリケーションでは、ログイン状態を維持するために「セッション」を使用しますが、このセッションが漏洩、推測されることで、第三者に乗っ取られてしまいます。
セッションが乗っ取られると、なりすましによる任意の操作が行われるため、非常に危険です。

では、セッションの管理不備とは具体的にどのようなものを指すのでしょうか。
よくあるものとしては、以下のような例が挙げられます。

| 不備内容 | リスク |
|:- |:- |
| セッションIDの固定化 | 攻撃者が発行したセッションIDが保持された状態でログインしてしまった場合、同じセッションIDで攻撃者からログイン後のページへアクセスされてしまいます。ログイン後、氏名や住所等の個人情報が盗み取られるほか、なりすましによる操作（掲示板への投稿や商品購入等）の恐れがあります。 |
| URL内のセッションID | リクエストが傍受された際に、セッションIDがURLに含まれていると、そのセッションIDでなりすましによる操作が行われてしまう恐れがあります。 |
| ログアウトによるセッション破棄の未実施 | ログアウト時にセッション破棄が行われない場合、セッションが有効なまま残り続けてしまうため、漏えいによるなりすましの恐れがあります。また、共有デバイスでは他の利用者から個人情報が閲覧される可能性があります。 |
| セッションIDが容易に推測可能 | セッションIDが容易に推測可能であることによって、セッションIDを取得せずになりすましによる操作が行える可能性があります。 |

セッションはWEBアプリケーションにおいて、非常に便利な機能の一つですが、取り扱いを間違えると上記のようなリスクにつながるため、適切な管理が重要です。

**発生する原因**

では、なぜセッション管理不備が現場で多く検出されるのでしょうか。
それは以下のような原因が考えられます。

**1. セッション管理の必要性を知らない**

セッション管理不備が発生する一番の原因としてセッションを管理する必要性を知らないことが挙げられます。そもそもセッションの破棄や変更処理が必要であることを知らないことで、処理が実装されていないケースが多いです。

例えばPHPでセッションを実装する場合、以下のようなコードを使用します。

```php
<?php

session_start();
```

上記は単純にセッションを開始しているコードですが、極端な話このコードを使用すればセッションを実装し、ログイン状態を保持することが可能となります。
セッション破棄や変更の重要性を知らずに、ログイン状態が保持されたことで満足してしまうと、セッション管理不備によってなりすましなどの被害が発生してしまいます。

**対策**

対策としては、セッションを使用する際は必要に応じた箇所（ログアウト時や再ログイン時等）でセッションの破棄、変更処理を確実に実装することが重要です。
また、現状の管理が適切であるかを確認するため、ベンダーによるWEBアプリケーション診断の実施を推奨します。

### アップロード機能の不備

普段私たちが使用しているSNSやECサイトでもファイル（アイコン）をアップロードすることが可能であり、この機能は、期待されたファイルタイプ（例：PNGやJPEGといった画像ファイル）のみアップロードできるように制限されています。
しかし、アップロードできるファイルタイプの制限に不備がある場合、マルウェアやWEBシェルによってサーバが侵害される恐れがあります。

アップロード機能の不備には、いくつかの段階的な制限があります。

| 有効性 | 内容 | 特徴と問題点 |
|:-:|:- |:- |
| ✕　　　　 | 無制限（ファイルの種類・拡張子・サイズ等に制限なし） | 最も危険 <br> マルウェアやWEBシェルをそのままアップロード可能|
| ✕ | 拡張子による制限  | 簡単にバイパス可能 <br> 例 : shell.php.jpg / shell.jpg（中身はPHP） |
| ✕ | Content-Typeによる制限 | クライアント側でContent-Typeを偽装できるため、簡単にバイパス可能 |
| 〇 | MIMEタイプによる制限 | 正確にファイルを識別、判定できる |

現場では「無制限」又は「拡張子による制限」で実装されていることが多いです。
細かい話をすると、アップロード機能の不備は、「アップロードされたファイルにアクセスできるかどうか」や「業務上アップロードされたファイルをどう取り扱うのか」で危険性は変わってきますが、あらゆる状況を想定し、確実な制限を推奨します。

**発生する原因**

では、なぜアップロード機能の不備が現場で多く検出されるのでしょうか。
それは以下のような原因が考えられます。

**1. 拡張子チェックのみで安全だと認識している**

先ほど問題点でも記述しましたが、拡張子による制限は比較的簡単にバイパスすることが可能です。しかし、WEBアプリケーションの開発者や運用者がバイパス可能であることを知らず、拡張子による制限のみで安全だと認識されていることで、検出が多くなっています。


**2. 悪意のあるファイルのアップロードを想定していない**

ファイルアップロード機能の不備を報告するもう一つの理由として、悪意のあるファイルがアップロードされることを想定していないことが挙げられます。その場合、当然制御を行う必要性もないと判断してしまうため、無制限にファイルがアップロードされてしまいます。

**対策**

ファイルアップロード機能の不備を発生させないためには、MIMEタイプによってアップロード可能なファイルを制限することが最も有効です。
攻撃者によって悪意のあるファイルをアップロードされ、仮にそのファイルが実行された場合、マルウェア感染や不正アクセスに繋がる恐れがあります。悪意あるファイルのアップロードを想定し、確実な対策を実施することが重要です。

### 詳細なエラー画面の表示

詳細なエラー画面の表示とは、WEBアプリケーションの処理中にエラーが発生した際、スタックトレースやSQL文、内部パス等の詳細情報が画面上に表示されてしまう脆弱性です。

よく見られるエラー文としては、以下のようなものがあります。

```
ERROR: syntax error at or near "'"
LINE 1: SELECT * FROM users WHERE username = '';
```

```
Warning: include(../etc/passwd): failed to open stream: 
No such file or directory in /var/www/html/include.php on line 8
```

上記のエラーメッセージは、想定外の入力値が適切に処理されていないことで出力されてしまっています。内容からSQLインジェクションやディレクトリトラバーサル等の脆弱性が存在する可能性を示唆しており、攻撃者にとって大きなヒントを与えてしまっています。

**発生する原因**

では、なぜ詳細なエラー画面の表示が現場で多く検出されるのでしょうか。
それは以下のような原因が考えられます。

**1. 想定外の入力による例外処理が不十分**

WEBアプリケーションに対するファジングでは、本来想定されていない入力を行うことが非常に多いです。特に、ドロップダウンやラジオボタン等の固定値を送信する機能による入力を想定していた場合、それ以外の入力値が想定されておらず、エラーメッセージが表示される原因になります。

**2. 開発時の設定が本番環境でも残っている**

WEBアプリケーションを開発する上で、エラーメッセージは非常に有益な情報となります。そのため、開発時はエラーメッセージの出力を行う実装をしている場合があります。その設定が本番公開となった後も残っている場合、詳細なエラーメッセージが表示されてしまうことがあります。

**対策**

詳細なエラー画面に対する対策として、ユーザの入力を正しく検証し、処理することも大切ですが、万が一想定されていないエラーが発生した際に対応できるように例外処理（エラーハンドリング）を実装することが重要です。データベースや外部APIとの接続時、ファイルに対する書き込み時等、想定されていないエラーが発生しやすい機能を把握し、漏れなく実装していく必要があります。
また、詳細なエラー画面に限った話ではないですが、開発時の設定や実装を決して残さないように細心の注意を払うことが大切です。確認不足により残ってしまった設定やコメント、機能が大きな被害に繋がる可能性があります。

### まとめ

ここまでセキュリティ診断現場で見かける"ありがちな脆弱性"の上位5個を紹介してきました！

今回紹介したWEBアプリケーションの脆弱性の特徴として「想定外であること」と「見落とし」が原因であることが挙げられます。
WEBアプリケーションの各機能には様々な攻撃手法が存在し、すべてを開発者や運用者が把握することは現実的に難しいです。十分に対策できていると思われた機能でも想定外の方法で悪用され、被害が発生する場合があります。
また、人間が一番の脆弱性とも言われるように、「見落とし」というのは避けられるものではありません。手動で機能を実装した場合、気を付けていたとしても脆弱性が存在してしまうことがあります。
そのため、自動ツールや手動によるテスト、セキュリティベンダーによるWEBアプリケーション診断を実施し、脆弱性に確実に対処していくことが重要です。

最後まで閲覧していただき、ありがとうございました！
WEBアプリケーションのセキュリティ強化の参考になれば嬉しいです！