• 診断項目 No.109/127
  • フォーム・パスワード入力
  • 重大度 最重要(critical)

機密情報をURL・GETフォームへ含めないとは?URLが漏れる場所・対象パラメータ・対策方法

機密情報をURL・GETフォームへ含めないとは、パスワード・トークン・APIキー・セッションIDをクエリ文字列に載せないことです。URLが残る場所、診断で検出するパラメータ名、送り方の変え方と設定例を解説します。

結論(機密情報をURL・GETフォームへ含めない)

機密情報をURL・GETフォームへ含めないとは、パスワード、アクセストークン、APIキー、セッションID、カード番号のような機密情報を、URLのクエリ文字列やGET送信のフォーム項目に載せないことです。URLはブラウザ履歴、サーバーやCDNのアクセスログ、Refererヘッダー、画面共有などに複製されるため、HTTPSで通信していても漏えいします。OWASP ASVS 5.0.0 V14.2.1は、機密データをHTTPメッセージ本文かヘッダーで送るよう求めています。

この記事のポイント

  • URLは共有される前提のもので、履歴・アクセスログ・解析タグ・Referer・スクリーンショットなど多くの場所に残ります。
  • HTTPSは通信路上を暗号化するだけで、端末やサーバーで記録されるURLは平文です。
  • 診断ではpassword・secret・access_token・api_key・phpsessid・cvvなど代表的な名前との完全一致で検出し、値は収集・表示しません。
  • パスワードはPOST本文、セッションIDはCookie、APIの認証情報はAuthorizationヘッダーやサーバー側中継で送ります。
  • URLに載せていたAPIキーやトークンは漏えい済みとみなし、再発行と旧キーの無効化を行います。
診断項目名機密情報をURL・GETフォームへ含めない
項目IDdata.sensitive-url-parameters
分類フォーム・パスワード入力
重大度・配点の重み最重要(critical) 重み 5
関連する標準・ガイドラインOWASP ASVS 5.0.0 V14.2.1(機密データはHTTPメッセージ本文またはヘッダーで送り、URLとクエリ文字列にAPIキーやセッショントークン等を含めない/L1)、RFC 9110 17.9(Disclosure of Sensitive Information in URIs)、CWE-598(Use of HTTP Request With Sensitive Query String)、OWASP WSTG-SESS-04(Exposed Session Variables:GETによるセッションID・認証情報の送信を確認)、IPA「安全なウェブサイトの作り方」1.4(セッションIDをURLパラメータに格納しない)

機密情報をURL・GETフォームへ含めないとは

機密情報をURL・GETフォームへ含めないとは、パスワード、アクセストークン、APIキー、セッションID、カード番号のような機密情報を、URLのクエリ文字列(? 以降)や、GETで送信するフォームの項目に載せないことです。

URLは「共有されるもの」として設計されており、ブラウザ履歴、ブックマーク、サーバーやCDNのアクセスログ、解析ツール、Refererヘッダー、メールやチャットへの貼り付けなど、多くの場所に複製されます。機密情報をURLのクエリに含めると、HTTPSで通信していても、これらの複製先から漏えいします。

セキュリティAIチェッカーのこの項目は、診断で巡回・発見したURLと、GET送信のフォームの項目名に、代表的な機密情報の名前が含まれていないかを確認します。値は収集・表示しません。

URLが残る場所

場所内容
ブラウザ履歴、アドレスバーの候補、ブックマーク、同期されたクラウド履歴
サーバー側Webサーバー、リバースプロキシ、WAF、CDN、ロードバランサーのアクセスログ
第三者アクセス解析タグ、広告タグ、外部埋め込み(Refererとして)
人画面共有、スクリーンショット、問い合わせ時のURL貼り付け

なぜ機密情報をURLに含めてはいけないのか

標準の考え方

RFC 9110の17.9節は、URIは機密リソースを指す場合でも保護の対象ではなく共有されるものであり、機密情報・個人識別情報を含めるのは賢明でないと述べています。GETフォームのクエリに機密データが入る場合、本文で送るPOSTが好まれるとも説明しています。

OWASP ASVS 5.0.0 V14.2.1(L1)は、機密データをHTTPメッセージ本文かヘッダーで送り、URLとクエリ文字列にAPIキーやセッショントークンなどを含めないことを求めています。IPA「安全なウェブサイトの作り方」1.4も、セッションIDをURLパラメータに格納しないよう求めています。

Refererと現在のブラウザ既定値

主要ブラウザの既定のReferrer-Policyは strict-origin-when-cross-origin で、別オリジンへのリクエストにはオリジン(https://example.lg.jp/)だけが送られ、パスやクエリは送られません(MDN)。ただし、サイトが unsafe-url や no-referrer-when-downgrade を明示している場合、または同一オリジン内の通信では、クエリを含む完全なURLが送られます。既定値に頼らず、そもそもURLに機密情報を載せないことが基本です。

URLの機密情報についてよくある誤解

  • 「HTTPSならURLも暗号化されるので安全」:通信路上では暗号化されますが、端末やサーバーで記録されるURLは平文です。
  • 「ワンタイムだから問題ない」:パスワード再設定リンクのように、URLにトークンを含めざるを得ない用途もあります。その場合は短い有効期限、1回限りの使用、使用後の無効化、ページの Referrer-Policy: no-referrer などで露出を抑えます。本項目は token 単体の名前を対象外とし、access_token などの認証トークン名に絞っています。

パスワード欄を含むフォームの送信方法は「パスワードをPOSTで送信」、セッションIDのURL埋め込みは「セッションIDをURLへ含めていない」、Refererの送り方は「Referrer-Policy」で確認します。このページは「URLとGETフォームの項目名に機密情報の名前がないか」に絞って解説します。

機密情報をURL・GETフォームへ含めないの診断基準(セキュリティAIチェッカー)

取得対象

外部診断強化モジュールが、次のURL候補とHTMLを使います。HTMLから抽出するURLと巡回結果は同一オリジンに限ります(入力URLとリダイレクト経路のURLは、別オリジンであっても対象です)。

  • 入力URL、最終URL、リダイレクト経路のURL
  • トップページと追加ページ(トップページを含め最大3ページ)の最終URL
  • それらのHTML内の <a>・<link>・<script>・<img>・<iframe> の href/src、<form> の action、location=・fetch(・axios.get/post( に書かれたURL
  • Ver2巡回で確認したページとAPI候補

機密情報とみなす名前

機密情報とみなすパラメータ名・項目名は、次の名前と大文字小文字を区別せず完全一致するものです。

password、passwd、pwd、secret、access_token/accesstoken、refresh_token/refreshtoken、id_token/idtoken、api_key/api-key/apikey、authorization、session_id/sessionid、phpsessid、jsessionid、aspsessionid、cvv、card_number/cardnumber

検出の手順

  1. 各URL候補のクエリパラメータ名を調べ、上記に一致する名前の種類数を数えます。
  2. 各ページの <form ...>〜最初の </form> の組(閉じタグのないフォームは対象外)のうち、method が post でないもの(未指定はGET)について、内部の <input>・<select>・<textarea> の name 属性が上記に一致する件数を数えます。

判定条件

判定条件得点への影響
○ 問題なし(pass)URLにもGETフォームにも該当名がない重み5を満点で加算
△ 要確認(warn)使用しない—
× 要改善(fail)URLの該当パラメータ名、またはGETフォームの該当項目が1件以上ある重み5に対して0点
対象外(na)使用しない(URLは常に存在するため必ず判定)—

根拠には「URLに機密名のパラメータがn種類、GETフォームに機密名の項目がm件」と件数だけを表示し、値は表示しません。

判定の範囲と限界

  • 名前の完全一致で判定するため、pw、pass、key、token、mail などの短い名前や独自の名前は対象外です(誤検知を避けるため)。パスワード欄を含むGETフォームは、名前に関係なく「パスワードをPOSTで送信」で別途検出されます。
  • 調べるのはクエリパラメータ名(? 以降)だけです。/menu.do;jsessionid=... のようにパスへ埋め込む形式は本項目では数えず、「セッションIDをURLへ含めていない」が検出します。
  • 認証後の画面、JavaScriptが実行時に生成するURL、メール本文のリンクは確認できません。

自治体サイトでの判定例

状況判定
公式サイトのページURLが /soshiki/kikaku/12345.html 形式で、検索フォームは q だけ○
地図アプリの埋め込みURLに ?api_key=... が付いた同一オリジンの中継URLがある×
旧システムへのリンクに ?PHPSESSID=... が付いている×(session.id-in-url も不合格)
/app/menu.do;jsessionid=... の形式だけ本項目は○のまま、session.id-in-url が不合格

機密情報をURLに含めるとどんなリスクがあるか

  • アクセスログ経由の漏えい:ログを閲覧できる運用者・委託先、ログ転送先のクラウドサービス、ログファイルの誤公開から、APIキーやトークンが第三者に渡ります。APIキーが漏れると、利用料金の不正発生や、APIで扱うデータの取得・改ざんにつながります。
  • セッションハイジャック:URLのセッションIDが他人に渡ると、ログイン状態を乗っ取られます。IPAの「安全なウェブサイトの作り方」は、URLパラメータのセッションIDがRefererで外部サイトへ送られる危険を説明しています。
  • 共有による拡散:住民が問い合わせでURLを貼り付けた、職員がマニュアルにスクリーンショットを載せた、といった通常の行為で機密情報が広がります。
  • 検索エンジンへの登録:リンクとして公開ページに書かれたURLは、検索エンジンにクロールされ、キャッシュや検索結果に残ることがあります。

機密情報をURLに含めないための対策方法(PHP・Apache・nginx)

1. 送り方を変える

情報推奨される送り方
パスワードPOSTの本文(forms.password-submit-method)
セッションIDSecure・HttpOnly・SameSite 属性付きCookie
APIの認証情報Authorization ヘッダー、またはサーバー側で保持し中継
地図・翻訳など外部APIのキーサーバー側の中継(プロキシ)でヘッダーに付与し、ブラウザに渡さない。ブラウザで使う必要があるキーは提供元のリファラー・ドメイン制限を必ず設定
<?php
// APIキーをサーバー側だけで保持し、ヘッダーで送信する中継の例
// MAP_API_KEY は .env を読み込むライブラリやサーバー設定(SetEnv 等)で環境変数に設定しておく
$key = getenv('MAP_API_KEY');
$ch = curl_init('https://api.example.com/v1/geocode');
curl_setopt_array($ch, [
  CURLOPT_HTTPHEADER => ['x-api-key: ' . $key, 'Content-Type: application/json'],
  CURLOPT_POST => true,
  CURLOPT_POSTFIELDS => json_encode(['q' => $_POST['q'] ?? '']),
  CURLOPT_RETURNTRANSFER => true,
]);
echo curl_exec($ch);

getenv() は .env ファイルを自動では読み込みません。.env を使う場合は読み込みの仕組みを用意したうえで、ファイルは公開ディレクトリの外に置くか、.htaccess で <Files ".env"> Require all denied </Files> として直接取得を拒否します。

2. セッションIDをURLへ出さない設定

; PHP(php.ini または .user.ini)
session.use_only_cookies = 1
session.use_trans_sid = 0
session.cookie_secure = 1
session.cookie_httponly = 1
session.cookie_samesite = "Lax"

session.use_only_cookies = 1 と session.use_trans_sid = 0 はPHPの既定値で、PHP 8.4以降は逆の設定(前者の無効化、後者の有効化)が非推奨です。

Java(Tomcat等)では web.xml の <session-config><tracking-mode>COOKIE</tracking-mode></session-config> でURL書き換えを無効化できます。

3. Referrer-Policyを設定する

<IfModule mod_headers.c>
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
add_header Referrer-Policy "strict-origin-when-cross-origin" always;

パスワード再設定ページなど、URLにトークンを含むページは no-referrer にします。

4. 漏えい済みの情報を無効化する

URLに載せていたAPIキーやトークンは、すでにログ等に残っていると考え、キーの再発行(ローテーション)と旧キーの無効化を行います。セッションIDの場合は全セッションを破棄し、再ログインを求めます。

修正後の確認方法

# 公開HTMLから機密名パラメータを探す
curl -s https://www.example.lg.jp/ | grep -oiE '[?&;](password|passwd|pwd|secret|access_token|api_?key|apikey|phpsessid|jsessionid|session_?id)=' | sort | uniq -c

# アクセスログを確認(サーバー上)
grep -iE '[?&](password|api_?key|access_token)=' /var/log/httpd/access_log | wc -l

修正後はセキュリティAIチェッカーで再診断し、この項目が○になることを確認します。

サイトを壊さないための注意点

  • APIキーをURLから外すと、外部サービス側がクエリでしかキーを受け付けない場合に動作しなくなります。提供元の仕様(ヘッダー認証の可否)を先に確認してください。
  • session.use_trans_sid = 0 にすると、Cookieを無効にしている利用者はセッションを維持できなくなります。現在の主要ブラウザ環境ではCookieが前提であり、案内文の用意で対応するのが一般的です。
  • キーのローテーションは、新キーの設定→動作確認→旧キー無効化の順に行い、停止時間を作らないようにします。

よくある質問(FAQ)

HTTPSならURLに機密情報を含めても安全ですか?

安全ではありません。URLは通信路上では暗号化されますが、ブラウザ履歴、Webサーバー・CDNのアクセスログ、解析ツールなどには平文で記録されます。

URLやGETフォームのどのパラメータ名が機密情報として検出されますか?

password、passwd、pwd、secret、access_token、refresh_token、id_token、api_key、authorization、session_id、phpsessid、jsessionid、aspsessionid、cvv、card_number などと、大文字小文字を区別せず完全一致する名前です。pw、pass、key、tokenのような短い名前は誤検知を避けるため対象外です。

パスワード再設定リンクのようにURLにトークンが必要な場合は?

用途上やむを得ない場合は、短い有効期限、1回限りの使用、使用後の無効化、ページの Referrer-Policy: no-referrer などで露出を抑えます。本項目は token 単体の名前を対象外とし、access_token などの認証トークン名に絞っています。

地図などの外部APIキーはどう扱えばよいですか?

サーバー側の中継(プロキシ)でヘッダーに付与し、ブラウザに渡さない方法が基本です。ブラウザで使う必要があるキーは、提供元のリファラー・ドメイン制限を必ず設定します。

URLに載せていたAPIキーはどうすればよいですか?

すでにログ等に残っていると考え、キーの再発行(ローテーション)と旧キーの無効化を行います。新キーの設定、動作確認、旧キー無効化の順に進めると停止時間を作らずに済みます。

機密情報をURL・GETフォームへ含めていないかは、セキュリティAIチェッカーでどう判定されますか?

巡回・発見したURLのクエリパラメータ名、またはGET送信フォームの項目名に機密名が1件でもあれば「× 要改善」(重み5に対して0点)、なければ「○ 問題なし」です。URLは常に存在するため、対象外にはなりません。

セキュリティAIチェッカーを利用する

この項目を含む127項目を、URLを入れるだけで無料診断します。

参考資料