結論から書きます。本番環境しかなく、ステージング(本番とは別の試験用環境)がなくても、セキュリティ診断はできます。 大事なのは「本番で診断してよいか」を一括で決めることではなく、手法ごとに「本番に触れるか」「触れるなら書き込むか」で分けることです。
- 本番に一切触れない診断:ソースコード、設定、依存関係、データベースの構造とアクセス制御のポリシーを読む。
- 本番に読み取りだけで触れる確認:攻撃をしないパッシブスキャン、ヘッダーとTLSの確認、テスト用アカウントでの読み取りによる認可の確認。
- ステージングか書面の合意が要る試験:能動的なスキャン、ファジング、負荷試験、データを書き込む試験。
小さな会社やスタートアップでは「本番しかない」はごく普通の状態です。それを理由に診断を先送りするのは得策ではありません。本記事では、この3つの分け方を判断表にし、本番で何かを確かめる前に書面で決めること、テスト用アカウントの作り方、バックアップに頼れない理由、そして「いっそ検証用の環境を立てた方が安い」場面までを順に説明します。
判断表:手法ごとに「本番に触れるか」で分ける
本番への影響は手法によって大きく違うので、まず表で分けてから、必要なものだけを選びます。 上の段ほど本番への影響が小さく、下の段ほど準備が要ります。
| 手法 | 本番に触れるか | 主なリスク | 必要なもの |
|---|---|---|---|
| ソースコードレビュー | 触れない | ほぼなし(コードの共有範囲の管理のみ) | リポジトリの読み取り権限 |
| 設定レビュー(ホスティング・認証・環境変数の名前) | 触れない(設定画面を読むだけ) | 管理画面の権限を広く渡しすぎること | 閲覧専用の権限、または画面の書き出し |
依存関係の監査(npm audit など) | 触れない | ほぼなし | lockfile |
| DBの構造とポリシーのレビュー | 触れない(マイグレーションを読む) | ほぼなし。本番との差分があれば見落とす | マイグレーション、またはデータ抜きのスキーマ |
| パッシブスキャン(ZAP ベースライン) | 読み取りで触れる | クローラーがGETで状態を変える処理を踏む/アクセス増 | 対象URL・時間帯の合意 |
| ヘッダー・TLSの確認 | 読み取りで触れる | ほぼなし(数件のリクエスト) | 対象URL |
| テスト用アカウントでの認可確認(読み取りのみ) | 読み取りで触れる | 他の顧客のデータを実際に見てしまう可能性 | テスト用アカウント・テスト用テナント、書面の合意 |
| 能動的なスキャン(ZAP フルスキャンなど) | 書き込みを含めて触れる | 不要なデータの作成、性能低下、通知の誤送信 | ステージング、または書面の合意と停止条件 |
| ファジング | 書き込みを含めて触れる | 想定外の入力によるエラーやデータ破損 | ステージングが原則 |
| 負荷試験 | 触れる | サービス停止、従量課金の急増 | ステージングが原則 |
| データを書き込む試験(権限昇格・改ざんの確認) | 書き込む | 顧客データの変更、戻せない副作用 | ステージング、またはバックアップと書面の合意 |
この分け方は、米国国立標準技術研究所(NIST)の情報セキュリティ試験の手引き SP 800-115 の考え方に沿っています。同書は、試験の手法を選ぶときに、本番で行うか、似た構成の本番以外の環境で行うかを検討すべきだとし、判断の材料として「本番への影響(サービス停止を起こしうる手法は本番以外で)」「機微な個人情報が見えてしまう可能性(本物の代わりに試験用のデータを使う)」「本番とそれ以外の環境がどれだけ同じ構成か」を挙げています。最後の点は見落とされがちで、同書自身が、試験環境と本番環境には実際には差があり、本番以外で試すと脆弱性を見逃すことがあると書いています。つまり「本番しかない」ことは、欠点であると同時に、見ている環境と守りたい環境が一致しているという利点でもあります。
① 本番に一切触れない診断で、どこまで分かるか
重大な欠陥の多くは、本番にリクエストを1件も送らずに見つかります。 特に、誰がどのデータを見てよいかという認可の欠陥は、コードとポリシーを読めば見つかる種類の問題です。
本番に触れない診断で読むものは次のとおりです。
- ソースコード:APIやサーバー処理が、リクエストに含まれるID(URLのパラメータ、送信データ)を、ログイン中のユーザーの持ち物かどうか確かめてからデータベースに渡しているか。管理者だけが使える処理に、管理者かどうかの確認があるか。
- データベースの構造とアクセス制御のポリシー:Supabase なら
supabase/migrationsのSQLに、全テーブルのRLS(行ごとのアクセス制御)が定義されているか、条件が行を所有者やテナントに絞っているか、書き込み時の条件があるか。本番とマイグレーションがずれている疑いがあるなら、データを含めないスキーマだけを書き出してもらえば足ります。 - 設定:ホスティングの環境変数の「名前」の一覧(値は不要)、認証の設定(メール確認の有無、パスワードの条件、外部ログインのリダイレクト先)、ストレージの公開設定。
- 依存関係:lockfile を対象にした既知の脆弱性の確認。
ここで強調したいのは、この段階は本番に触れないぶん、本番環境の状態を直接は確かめていないということです。マイグレーションに書かれていないポリシーを誰かが管理画面から手で変えていれば、コードだけでは分かりません。だから読む診断の結果は「この設計なら、本番でもこうなるはず」という仮説として扱い、必要なものだけを②の読み取りの確認で裏付けます。
Next.js × Supabase の構成で、ツールで見つけられる範囲と人が読む必要がある範囲の境目は、セキュリティ監査は何を見るのか — 自動化で足りる範囲と、監査が要る範囲で詳しく扱っています。
② 本番に「読み取りだけ」で触れる確認
データを書き換えないリクエストに限れば、本番に対しても確認できます。 ただし「読み取りだから無害」とは限らないので、手法ごとの注意点を押さえておきます。
パッシブスキャン:攻撃はしないが、クローラーは動く
OWASP ZAP のベースラインスキャンは、公式ドキュメントによれば、対象に対して既定で1分間クローラー(スパイダー)を走らせ、その後パッシブスキャンの完了を待って結果を報告します。実際の攻撃は行わないため実行時間は長くても数分で、CI/CD に組み込んで本番サイトに対して実行することも想定されていると書かれています。見つかるのは、セキュリティ関連のヘッダーの欠落、Cookie の属性、情報の漏れといった、応答を観察すれば分かる種類の問題です。
一方で、注意点が1つあります。クローラーはページ内のリンクを順にたどってリクエストを送ります。ZAP 自身も、モードの説明で、クローラーによる巡回を能動的なスキャンやファジングと並べて「潜在的に危険な操作」に分類しています。GETリクエストでログアウト、削除、メール配信の停止などが実行される作りになっていれば、クローラーがそれを踏みます。 本番で使うなら、次のように絞ります。
- 対象のURLを決め、対象外のパス(管理画面、外部サービスへの転送など)を明示する。
- ログインした状態での巡回は、②の後半の認可確認とは分けて、必要性を検討してから行う。
- 巡回時間は既定の短さのまま使い、アクセスの少ない時間帯に実行する。
これと対になるのが、同じ ZAP のフルスキャンです。こちらは公式ドキュメントで「実際の攻撃を行い、長時間かかることがある」と明記されており、本番に対して気軽に実行するものではありません(③で扱います)。ZAP の使い方そのものはWebアプリ脆弱性診断のやり方 — OWASP公式手法とZAP・SASTで自動化する実践ガイドにまとめています。
ヘッダーとTLSの確認
応答ヘッダー(Strict-Transport-Security、Content-Security-Policy、X-Content-Type-Options など)や証明書・TLSの設定の確認は、数件のリクエストで済み、本番への影響はほとんどありません。ここは本番で確かめるのが最も確実な項目です。CDN やホスティングの設定によって、コードに書いたヘッダーと実際の応答が違うことがあるからです。
テスト用アカウントでの認可の確認(読み取りのみ)
認可の欠陥(他人のデータを見られる問題)を本番で確かめるときは、自分たちで作ったテスト用のデータだけを対象にします。 OWASP の Web Security Testing Guide は、IDOR(IDを書き換えると他人のデータに届く欠陥)の確認について、少なくとも2人(多くの場合はそれ以上)のユーザーを用意し、それぞれが別のデータを持つ状態で、片方からもう片方のデータへのアクセスを試すのが最善の方法だとしています。
本番でこれを行うときの原則は次の3つです。
- IDを推測して数字を順に変えない。 他の顧客のデータに届いてしまえば、それ自体が情報の漏れになります。使うのは、テスト用アカウントBで自分たちが作ったデータのIDだけです。
- 読み取りのリクエスト(一覧・詳細の表示)に限る。 更新・削除のAPIは、書面で合意していない限り試しません。
- 結果の記録に個人情報を含めない。 万一テスト用以外のデータが返ってきたら、その場で止め、内容を保存せずに連絡します(停止条件として書面に入れておきます)。
アカウントの作り方は、後の節で説明します。
③ ステージングか書面の合意が要る試験
データを書き込む、大量のリクエストを送る、想定外の入力を投げる——この3つのどれかに当たる試験は、本番で気軽に行いません。 行うならステージングを用意するか、対象・時間帯・停止条件を書面で合意します。
- 能動的なスキャン:入力欄やパラメータに攻撃用の文字列を送り込みます。フォームが送信されれば、問い合わせメールが大量に届いたり、ダミーの注文やアカウントが作られたりします。
- ファジング:大量の想定外の入力を送ります。例外処理の甘い箇所でエラーが連続し、データが壊れることもあります。
- 負荷試験:サービス停止の危険に加え、従量課金のサービス(サーバーレス関数、データベース、メール送信、外部API)の請求が急に増える可能性があります。
- 書き込みを伴う認可の確認:「他人のデータを更新できるか」「一般ユーザーが管理者に昇格できるか」は、実際に書き込まないと確かめられないことがあります。成功した時点で、本番のデータが変わっています。
NIST SP 800-115 も、ペネトレーションテストのような手法はサービスの停止や機微なデータの露出を招きうるとし、サービス停止を起こしうる手法は本番以外の環境で行うべきだとしています。本番でどうしても行う場合は、同書が勧めるように、業務への影響が小さい時間帯に限定します。
ただし、書き込みの試験が必要になるのは、①と②で「怪しい」と分かった箇所の裏付けに限られることが多いです。最初から全部を本番で試す必要はありません。
本番で何かを確かめる前に、書面で決めること
本番にリクエストを送る診断は、送る前に「何を・いつ・どこから・どこまで」を書面にし、双方の責任者が確認します。 NIST SP 800-115 は付録で、この文書を Rules of Engagement(実施ルール、ROE)としてひな形を示しています。そこに挙がっている項目を、小規模なWebアプリ向けに置き換えると次のようになります。
- 対象のURL・API:診断してよいドメインとパス。対象外のもの(除外リスト)も明記する。 同じドメインにある管理画面や、外部の決済・メール配信サービスは、多くの場合対象外です。
- 実施する日時:開始と終了の日時。アクセスの少ない時間帯を選ぶ。
- 送信元のIPアドレス:診断者がどこからリクエストを送るか。監視やログで診断のアクセスと本物の攻撃を区別するために必要です。
- 使うテスト用アカウント:アカウントとテナントの一覧と、それぞれの役割。
- 許可する操作と禁止する操作:「読み取りのみ」「フォーム送信は禁止」「ファイルのアップロードは禁止」など。使ってよいツールも書く。
- 試験を止める条件:エラー率の上昇、応答の遅延、テスト用以外のデータが見えた場合など。止めた後の再開の手順も。
- 問題が起きたときの連絡先:双方の担当者と、夜間・休日でもつながる連絡手段。
- データの扱い:診断で得た情報(見つかった脆弱性、応答の記録)の保管場所、共有範囲、廃棄の時期。NIST SP 800-115 は、試験の結果は攻撃者に悪用されうる情報なので機微な情報として扱うよう求めています。
- 報告の形と時期:重大な問題が見つかったら即時に連絡するのか、最終報告でまとめるのか。
- 署名:同書は、少なくとも試験チームの責任者と、依頼する組織の経営側の責任者が、範囲と境界を理解したことを署名で示すよう求めています。
社内の開発者が自分たちのアプリを確かめる場合でも、この一覧を短く書いておく価値があります。誰がいつ何を送ったかが残っていれば、障害が起きたときに「診断のせいか、本物の攻撃か」をすぐに切り分けられるからです。外部に依頼する場合、システムを管理する側の明確な許可がない試験は、不正アクセスとみなされうる行為でもあります。また、利用しているクラウド事業者が侵入テストについての方針を定めていることもあるので、あわせて確認しておきます。
テスト用アカウントとテスト用テナントを安全に作る
テスト用アカウントは、本物の顧客と同じ手順で作り、本物の顧客と見分けがつくようにし、終わったら無効にします。 管理画面やデータベースを直接書き換えて作ると、本物のユーザーと違う状態のアカウントになり、確認の意味が薄れます。
作り方の要点は次のとおりです。
- 本物の利用者と同じ登録手順で作る。 招待制なら招待から。そうすれば、登録の流れに潜む問題も一緒に確かめられます。
- 会社が管理するメールアドレスを使う。 診断者の個人アドレスではなく、終わったら止められるアドレスにします。
- 認可を確かめる最小の組み合わせを用意する。 同じテナントに一般ユーザー2人、別のテナントに1人。役割(管理者・編集者・閲覧者など)がある場合は、確かめたい役割ごとに1人ずつ。WSTG の「少なくとも2人」を、テナントの境界と役割の境界の両方に当てはめた形です。
- テスト用のデータだけを入れる。 本物の顧客名や連絡先を写さず、明らかに架空と分かる値を使います。
- 一覧に残す。 作ったアカウントとテナントのIDを書面の一覧に記録し、分析・請求・メール配信の対象から外します。売上や利用者数の集計にテスト用のデータが混ざらないようにするためです。
- 管理者権限のアカウントを診断者に渡さない。 管理者として何ができるかを確かめたい場合も、そのための専用アカウントを作り、期間を限って使います。
- 終わったら無効にする。 診断が終わった日に、アカウントの無効化とテスト用データの削除を行い、記録します。
なお、テスト用アカウントの作成そのものは本番への書き込みです。ただしそれは、本物の利用者が毎日行っているのと同じ操作を、あなたの管理のもとで行うものです。診断ツールが予測できない書き込みを行うのとは、性質がまったく違います。
書き込みを伴う試験の前に:バックアップは「戻せば済む」を保証しない
バックアップは最後の保険であって、試験で書き込んだデータだけを取り消す手段ではありません。 書き込みを伴う試験を本番で行うなら、バックアップの有無を確かめたうえで、「戻すことになったら何を失うか」を先に理解しておく必要があります。
Supabase を例にすると、公式ドキュメントには次のように書かれています。
- 有料プランのプロジェクトは毎日自動でバックアップされます。より細かく戻したい場合は、ポイントインタイムリカバリ(PITR:秒単位で任意の時点に戻せる機能)を有料の追加機能として有効にできます。無料プランでは、CLI の
db dumpで定期的に書き出し、別の場所に保管することが推奨されています。 - 復元中はプロジェクトにアクセスできず、停止時間はデータベースの大きさに比例して長くなります。
- データベースのバックアップには、Storage に保存したファイル本体は含まれません。 データベースにあるのはファイルの情報だけです。
ここから分かるのは、復元が「プロジェクト全体を過去の時点に戻す」操作だということです。試験の開始後に本物の顧客が登録や注文をしていれば、戻した時点でそれも消えます。だから書き込みを伴う試験を本番で行うなら、最低限次を確かめます。
- 直近のバックアップ(またはPITR)がいつの時点まで戻せるか。
- 復元にかかる時間の見込みと、その間サービスが止まることを関係者が了承しているか。
- 試験で作るデータを、復元ではなく個別に削除する手順が決まっているか。
3番目が本命です。バックアップからの復元は、個別の削除で片付かなかったときの最後の手段として位置づけます。
レート制限とWAF:診断のアクセスを止めるか、通すか
レート制限やWAF(攻撃的なリクエストを遮断する仕組み)がある場合は、診断のアクセスを通すかどうかを、目的に合わせて決めて書面に書きます。 どちらが正しいかは、何を確かめたいかで変わります。
- アプリそのものの欠陥を見たい場合:診断者の送信元IPアドレスだけを、診断の期間に限って許可リストに入れます。WAF に遮られたままだと、WAF の手前で止まって、アプリに残っている欠陥が見えません。WAF は防御の層の1つにすぎず、迂回されることもあるため、アプリ自体の欠陥は把握しておくべきです。
- 実際の防御の状態を見たい場合:WAF もレート制限も有効のまま行います。「攻撃者から見えている状態」を確かめられます。
許可リストに入れる場合は、WAF やレート制限そのものを止めないこと、対象を診断者のIPアドレスと期間に限ること、終わったら外したことを記録することを守ります。一時的な例外が消し忘れられて、そのまま残るのはよくある事故です。
また、パッシブスキャンや読み取りの確認でもリクエストは増えます。レート制限に引っかかって正規の利用者まで遮断されないよう、ツールのリクエスト間隔を空ける設定も事前に決めておきます。
「ステージングを立てる」方が安く済むこともある
書き込みを伴う試験が必要なら、本番で慎重に行うより、診断の期間だけ検証用の環境を立てて終わったら消す方が、安く済むことがあります。 環境を「ずっと持ち続ける」ことと「一時的に立てる」ことは、別のものとして考えてください。
Supabase と Vercel の構成なら、選択肢は次のとおりです。
- Supabase のブランチ:公式ドキュメントによれば、ブランチは本番とは別のインスタンスと認証情報を持つ独立した環境で、本番のマイグレーションを適用して作られます。既定では本番のデータやストレージのファイルを持ち込まず、必要なデータは seed ファイルで入れます。プレビュー用のブランチは、プルリクエストのマージやクローズで自動的に削除されます。
- Vercel のプレビュー環境:Vercel は、本番とは別にプレビュー環境を標準で持っており、本番用以外のブランチに push するとプレビューのデプロイが作られます。プレビュー用の環境変数がブランチ側の Supabase を指していれば、本番とつながらない試験環境ができます。逆に、プレビューの環境変数が本番のデータベースを指したままだと、「プレビュー」での試験が本番への書き込みになります。 環境変数の向き先は、試験の前に必ず確かめてください。
- 手元の環境:Supabase のローカル開発環境は、Docker でデータベースや認証を手元に立ち上げます。外部に公開しない確認であれば、ここで十分なこともあります。
費用は利用中のプランや稼働時間によって変わるので、ここでは金額を示しません。比べるべきは、一時的な環境の費用と、本番で書き込みの試験を行うための準備(書面、バックアップの確認、個別削除の手順、立ち会い)と、事故が起きたときの損失です。マイグレーションがリポジトリで管理されていれば、検証用の環境は再現しやすく、この比較は環境を立てる側に傾きやすくなります。逆に、マイグレーションがなく管理画面から手でテーブルを作ってきたアプリでは、本番と同じ環境を作ること自体が大仕事になります。その場合は、まずスキーマをマイグレーションとして書き出すことが、診断より先にやるべき改善になります。
検証用の環境で試すときも、SP 800-115 が指摘するとおり、本番との差で脆弱性を見逃すことがあります。検証用の環境での結果は、本番の設定(環境変数の名前、認証の設定、ストレージの公開設定)と突き合わせて確認します。
まとめ:本番しかないなら、この順番で進める
要点を整理します。
- 本番しかなくても診断はできる。 手法を「本番に触れない」「読み取りだけで触れる」「ステージングか書面の合意が要る」に分ければ、本番を壊さずに進められる範囲がはっきりします。
- まず、本番に触れない診断から始める。 コード、設定、依存関係、データベースの構造とポリシーを読むだけで、認可の欠陥のような重大な問題の多くは見つかります。
- 本番への読み取りの確認は、範囲を絞って行う。 パッシブスキャンは攻撃をしませんが、クローラーは動きます。認可の確認は、自分たちで作ったテスト用のデータだけを対象にします。
- 本番にリクエストを送る前に、実施ルールを書面にする。 対象、時間帯、送信元IP、テスト用アカウント、停止条件、連絡先、データの扱い、署名。
- 書き込みを伴う試験は、ステージングか書面の合意で。 バックアップからの復元は顧客の書き込みも消すので、「戻せば済む」は成り立ちません。一時的に検証用の環境を立てる方が安く済むこともあります。
本番環境しかない状態での診断を外部に頼みたい場合は、セキュリティ診断・監査で、本番に触れない診断から始める進め方をご相談いただけます。どこまで本番に触れるかは、最初に書面で決めてから進めます。Next.js と Supabase の構成で、RLS やテナントの分離まで踏み込んで確かめたい場合は、Next.js × Supabase 専門のセキュリティ監査の方が合っています。