結論(エラー応答のデバッグ情報)
エラー応答のデバッグ情報とは、エラー時の画面に表示されるPHPの警告文、スタックトレース、サーバー内部のファイルパス、SQLエラー文、フレームワークのデバッグ画面などの開発時向けの詳細情報です。本番で表示されると、攻撃者がシステム構成や脆弱な箇所を推測しやすくなります。利用者には汎用的なエラーページを返し、詳細はアクセス制御されたログだけに記録します。
この記事のポイント
- エラー詳細からは、言語・フレームワークとバージョン、内部の絶対パス、SQL文の断片、設定値などが読み取れます。
- PHPマニュアルは、display_errorsをインターネットに接続された本番システムで使うべきではないと明記しています。
- セキュリティAIチェッカーは存在しないURLのエラー応答に、PHPエラー・内部パス・SQLエラー・JavaScriptスタック・フレームワーク詳細エラーのいずれかがあれば×と判定します。
- 根拠欄には一致した種類だけを示し、実際のパスやエラー文は表示しません。
- 表示を止める前に、log_errorsとログの保存先・閲覧権限を整えておくのが安全です。
| 診断項目名 | エラー応答のデバッグ情報 |
|---|---|
| 項目ID | response.debug-details |
| 分類 | HTTP応答・エラー処理 |
| 重大度・配点の重み | 重要(high) 重み 4 |
| 関連する標準・ガイドライン | OWASP ASVS 5.0.0 V16.5.1(予期しないエラーやセキュリティ上重要なエラーでは汎用メッセージを返し、スタックトレース・クエリ・秘密鍵・トークン等の内部データを露出しない)、V13.4.2(本番環境で全コンポーネントのデバッグモードを無効化)、V13.4.6(バックエンドの詳細なバージョン情報を露出しない)/OWASP WSTG-ERRH-01(Testing for Improper Error Handling)/CWE-209(Generation of Error Message Containing Sensitive Information)/IPA「安全なウェブサイトの作り方」1.1 SQLインジェクション(エラーメッセージをそのままブラウザに表示しない) |
エラー応答のデバッグ情報とは
エラー応答のデバッグ情報とは、エラー時の応答に表示される PHP の警告文、スタックトレース、サーバー内部のファイルパス、SQL エラー文、フレームワークのデバッグ画面などの「開発時向けの詳細情報」のことです。
Warning: include(menu.php): Failed to open stream ... in /home/cityxx/public_html/404.php on line 3
本番サイトでこうした情報が表示されると、攻撃者はシステム構成や脆弱な箇所を推測しやすくなります。セキュリティAIチェッカーは、存在しないURLへのリクエストで返るエラー応答の本文に、こうした詳細情報が含まれていないかを確認します。
エラー詳細から読み取られる情報
OWASP Error Handling Cheat Sheet は、未処理のエラーが攻撃の初期段階(偵察)で攻撃者を助けると説明し、利用者には汎用的な応答を返し、詳細はサーバー側のログに記録するよう推奨しています。エラー詳細からは次のような情報が得られます。
- 使用言語・フレームワーク・ライブラリとそのバージョン(既知脆弱性の検索に直結)
- ドキュメントルートやユーザー名を含む絶対パス(
/home/<アカウント>/public_html/…) - SQL 文の断片やテーブル名(SQL インジェクションの足掛かり)
- 設定値、環境変数、場合によっては接続文字列や API キー
デバッグ情報はどこから出るのか(主な発生源)
| 環境 | 典型的な表示 |
|---|---|
PHP(display_errors=On) | <b>Warning</b>: … in <b>/var/www/html/x.php</b> on line <b>12</b>、Fatal error: Uncaught …、Stack trace: |
| PDO/DB | SQLSTATE[42000]、PDOException、You have an error in your SQL syntax、Oracle の ORA-00942 |
| ASP.NET | Server Error in '/' Application.、Exception Details:(いわゆるイエロースクリーン) |
| Java(Tomcat 等) | at org.apache.catalina…(StandardWrapperValve.java:199) 形式のスタック |
| Python(Django) | Traceback (most recent call last)、DEBUG = True の説明文 |
| Node.js | at handler (/app/server.js:10:5) 形式のスタック |
PHP マニュアルは display_errors について、開発を支援する機能であり、インターネットに接続された本番システムでは決して使うべきではないと明記し、本番サイトではエラー表示の代わりにエラーログを使うよう強く勧めています。
要件の根拠
| 出典 | 内容 |
|---|---|
| OWASP ASVS 5.0.0 V16.5.1 | 予期しないエラーやセキュリティ上重要なエラーでは汎用メッセージを返し、スタックトレース・クエリ・秘密鍵・トークン等の内部データを露出しない |
| OWASP ASVS 5.0.0 V13.4.2 | 本番環境で全コンポーネントのデバッグモードを無効化する |
| OWASP ASVS 5.0.0 V13.4.6 | バックエンドの詳細なバージョン情報を露出しない |
| CWE-209 | 機微な情報を含むエラーメッセージの生成 |
| IPA「安全なウェブサイトの作り方」1.1 | エラーメッセージをそのままブラウザに表示しない(SQLインジェクション対策) |
よくある誤解
- 「404ページは静的だから関係ない」:CMS やフレームワークでは404もアプリケーションが生成しており、デバッグモードが有効だとルーティング表やスタックが表示されます(Django の
DEBUG=True時の404画面など)。 - 「エラーは滅多に起きない」:攻撃者は意図的に不正な入力でエラーを起こします。本番でエラー詳細が出る設定であること自体が問題です。
エラー応答のデバッグ情報の診断基準(セキュリティAIチェッカー)
取得方法
- 診断対象オリジンの
/miniparse-ver2-not-found-<タイムスタンプ>を GET で1回取得します(最大3回リダイレクト追従、本文は最大500KB)。 - 能動的に500エラーを起こすような不正入力は送信しません。404等の処理経路で詳細情報が出るかを見る、受動的な確認です。
検査する5種類のパターン
エラー応答の本文に対し、次の5種類のパターン(大文字小文字を区別しない)を検査します。
| ラベル | 主な検出パターン |
|---|---|
| PHPエラー | PHP Warning/Notice/Fatal error/Parse error、<b>Warning</b>: 等の HTML 形式(Warning・Notice・Fatal error・Parse error・Deprecated)、Stack trace:、Uncaught <型名> |
| 内部パス | /var/www/、/home/<名前>/…/<ファイル>.php などスクリプト拡張子(php・inc・phtml・py・rb・pl・cgi・jsp・java)で終わるパス(名前は64文字まで、名前より後ろは200文字まで。直前が英数字・_・.・"・'・=・/・- のものは除く)、C:\inetpub\・C:\xampp\・C:\Users\ |
| SQLエラー | SQLSTATE[、syntax error … SQL(同一行で200文字以内)、PDOException、ORA- に続く5桁番号、You have an error in your SQL syntax |
| JavaScriptスタック | at 関数名 (ファイル:行:列) 形式(関数名は200文字まで、括弧内は改行を含まず400文字まで) |
| フレームワーク詳細エラー | Traceback (most recent call last)、DEBUG = True、Server Error in '…' Application、Exception Details:、at java./javax./jakarta./org.apache./org.springframework. で始まるスタック行 |
「/home/」を誤検知しない工夫
/home/ については、/home/kurashi/ のようなサイト内のURLパス(自治体サイトで「ホーム」配下のディレクトリとして使われることがある)を誤検知しないよう、スクリプトファイル名まで続くサーバー上のパスに限定しています。
さらに、直前の文字が引用符・=・/・英数字などの場合は一致させないため、href="/home/…/x.php" のような属性値、https://…/home/…/x.php のようなURLの途中、JSONの "file":"/home/…" は対象外です。エラー文の in /home/…/x.php on line 3 や <b>/home/…/x.php</b> のように、空白や > の直後から始まるパスが一致します。
判定条件
| 判定 | 条件 | 根拠表示 |
|---|---|---|
| ○ 問題なし(pass) | 一致なし | 代表的なスタックトレース・内部パス・SQLエラーはありません。 |
| △ 要確認(warn) | この項目では使用しない | ― |
| × 要改善(fail) | 1種類以上一致 | 露出兆候: PHPエラー、内部パス(値は非表示) |
| 対象外(na) | エラー応答を取得できない | エラー応答を取得できませんでした。 |
根拠表示には一致した種類のみを示し、実際のパスやエラー文は表示しません。診断結果自体が情報漏えい源にならないようにするためです。
得点への影響
重み4。○は4点、×は0点(△は使用しない)。対象外は分母から除外します。
自治体サイトでの判定例
| エラー応答の内容 | 判定 |
|---|---|
404ページに <b>Warning</b>: include(menu.php): Failed to open stream … in <b>/home/cityxx/public_html/404.php</b> on line <b>3</b> | ×(PHPエラー・内部パス) |
ASP.NET の既定エラー画面 Server Error in '/' Application. The resource cannot be found. | ×(.NET のバージョン情報も表示されることが多い) |
| 「ページが見つかりません」とだけ表示する静的404 | ○ |
検出の限界
- 判定は文字列パターンの一致によるため、404ページの本文やリンクの表示文字列として、空白や
>の直後に/home/<名前>/….php(または.cgiなど)と書かれている場合や、インラインスクリプトにUncaught …という文言がある場合も一致します。 - 逆に、JSON形式のエラー応答で引用符の直後に置かれた
/home/…のパスは内部パスとして検出しません(/var/www/は前後の文字に関係なく一致します)。×になったときは、エラーページのソースで該当箇所が本当にエラー出力かを確認してください。 - 取得するのは存在しないURLの応答1件だけで、500エラーやフォーム送信時のエラー画面は確認しません。
関連する診断項目
- 「下層・エラー応答のバージョン/デバッグ情報」は、巡回した下層ページ全体について、Server ヘッダーのバージョン表記や代表的なデバッグ文字列を確認します。
- 同じ存在しないURLのステータスコードは「存在しないURLのステータス」、ヘッダーは「エラー応答のヘッダー整合性」で評価します。
エラー応答にデバッグ情報が出るとどんなリスクがあるか
攻撃シナリオ
- 攻撃者が存在しないURLや不正なパラメータを送り、エラー画面を表示させる。
- 表示された内部パスからホスティング事業者・アカウント名・CMS の種類を、スタックトレースからフレームワークとバージョンを特定する。
- 該当バージョンの既知脆弱性を検索し、標的を絞った攻撃を行う。SQL エラーが出る場合は、エラーベースの SQL インジェクションでデータを抽出する。
想定される被害
- 既知脆弱性を突いた改ざん・不正侵入の成功率上昇
- SQL エラー経由のデータベース内容の漏えい
- 環境変数やデバッグ画面に秘密情報(DB パスワード、API キー)が含まれる場合、直接の認証情報漏えい
エラー応答のデバッグ情報を非表示にする設定方法(PHP・Apache・nginx・IIS・Django・Next.js)
基本方針
- 本番環境ではデバッグモード・エラー表示をすべて無効化し(ASVS V13.4.2)、エラーはアクセス制御されたログへ記録する。
- 利用者には汎用的なエラーページ(ステータスコードは正しく)を返す(ASVS V16.5.1)。
- 最後の砦となる例外ハンドラーを用意し、未処理例外でも詳細が漏れないようにする。
PHP(共有ホスティング)
; .user.ini(LiteSpeed/CGI/FPM 環境。mod_php なら php.ini)
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /home/example/logs/php_error.log
.htaccess の php_flag display_errors off は mod_php 環境でしか使えず、CGI/FPM/LiteSpeed では 500 エラーの原因になります。環境に合った方法で設定してください。
Apache の既定エラー表示
ServerSignature Off
ServerTokens Prod
ErrorDocument 404 /errors/404.html
ErrorDocument 500 /errors/500.html
ServerTokens はサーバー設定ファイル(httpd.conf 等)でのみ有効です。
nginx
server_tokens off;
error_page 404 /errors/404.html;
error_page 500 502 503 504 /errors/50x.html;
proxy_intercept_errors on; # 背後アプリの詳細エラーを差し替える場合
IIS/ASP.NET
<system.web>
<customErrors mode="RemoteOnly" defaultRedirect="/errors/500.html" />
<compilation debug="false" />
</system.web>
<system.webServer>
<httpErrors errorMode="DetailedLocalOnly" />
</system.webServer>
Java(Tomcat)
web.xml に <error-page> を定義して全例外を汎用ページへ送り、Tomcat の ErrorReportValve で showReport="false" showServerInfo="false" を設定します。
Python(Django)
settings.py で DEBUG = False とし、ALLOWED_HOSTS を設定します。環境変数で切り替える場合は、本番で既定値が False になるようにします。
Next.js(Vercel)
本番ビルド(next build → next start、または Vercel デプロイ)では、サーバーエラーの詳細はクライアントに送られず、ダイジェストのみが表示されます。app/error.tsx と app/global-error.tsx に汎用メッセージを用意し、console.error の詳細はログ基盤側で確認します。開発サーバー(next dev)を公開しないでください。
CMS(WordPress)
// wp-config.php
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false);
@ini_set('display_errors', '0');
WP_DEBUG_LOG を使う場合は、ログファイル(既定は wp-content/debug.log)が公開領域から取得できないよう設定してください。
サイトを壊さないためのガードレール
- 表示を止めるとログが唯一の手掛かりになります。先に
log_errorsとログの保存先・ローテーション・閲覧権限を整えてから、表示を無効化します。 - ログファイルを公開ディレクトリに置かないでください(「代表的な管理ファイルが公開されていない」)。
設定後の確認方法
# 存在しないURLのエラーページに内部情報が無いこと
curl -s https://www.example.lg.jp/no-such-page-$(date +%s) | grep -Ei "warning|stack trace|sqlstate|/var/www|/home/|traceback|exception"
# 何も表示されなければ代表的な露出は無い
よくある質問(FAQ)
エラー画面にスタックトレースやパスが出ると、なぜ危険なのですか?
攻撃者が使用言語・フレームワーク・バージョン、ホスティング事業者やアカウント名を特定し、既知脆弱性を検索して標的を絞れるからです。SQLエラーが出る場合は、エラーベースのSQLインジェクションでデータを抽出される足掛かりにもなります。
PHPのエラー表示を本番で止めるにはどうすればよいですか?
display_errors と display_startup_errors を Off にし、log_errors を On にしてログの保存先を指定します。LiteSpeed・CGI・FPM環境では .user.ini、mod_php なら php.ini で設定します。.htaccess の php_flag は mod_php 環境でしか使えず、それ以外では500エラーの原因になります。
404ページは静的だからデバッグ情報とは関係ないのでは?
CMSやフレームワークでは404もアプリケーションが生成しており、デバッグモードが有効だとルーティング表やスタックが表示されます。DjangoのDEBUG=True時の404画面などが例です。
エラー応答のデバッグ情報は、セキュリティAIチェッカーでどのように確認していますか?
存在しないURLを1回GETで取得し、その本文にPHPエラー、内部パス、SQLエラー、JavaScriptスタック、フレームワーク詳細エラーの5種類のパターンがあるかを調べます。1種類でも一致すれば×、一致がなければ○です。能動的に500エラーを起こす不正入力は送りません。
エラー応答のデバッグ情報が×になったのに、エラー出力ではない場合がありますか?
あります。文字列パターンの一致で判定するため、404ページの本文や表示文字列に空白や > の直後から /home/名前/….php のようなパスを書いている場合や、インラインスクリプトに Uncaught という文言がある場合も一致します。エラーページのソースで該当箇所が本当にエラー出力かを確認してください。
Next.jsの本番環境ではエラー詳細は表示されますか?
本番ビルド(next build → next start、またはVercelへのデプロイ)では、サーバーエラーの詳細はクライアントに送られず、ダイジェストのみが表示されます。開発サーバー(next dev)を公開しないことが重要です。
この項目を含む127項目を、URLを入れるだけで無料診断します。
参考資料
- OWASP ASVS 5.0.0 V16 Security Logging and Error Handling
- OWASP ASVS 5.0.0 V13 Configuration
- OWASP Error Handling Cheat Sheet
- OWASP WSTG-ERRH-01 Testing for Improper Error Handling
- PHP Manual: Runtime Configuration(display_errors 等)
- CWE-209: Generation of Error Message Containing Sensitive Information
- IPA「安全なウェブサイトの作り方」