はじめに
Fieldwork Studio は一般向けのクラフトワークショップを運営しています。スケジュールは簡単に閲覧・ダウンロードできる一方、保守用の診断情報には認可が必要なはずです。このアプリケーションの内部診断データを実際に公開しているレスポンスを確認することが、あなたの仕事です。
まず通常のサイトを利用します。次に3つの実際のレスポンスを比較し、意図的に条件を広くした Nuclei の初期チェックを実行します。スキャナーの検出結果をすべて確認済みの問題とみなすのではなく、調べたレスポンスに結び付いた結論を最後にまとめます。設定と識別情報はすべて合成されたものですが、HTTP リクエストとスキャナーの実行は実際に行われます。
必要なのは基本的なターミナル入力とパスの理解だけです。HTTP、JSON、スキャナーの出力は、登場するときに説明します。Kali の監査用コンテナーと対象コンテナーは分離されていますが、1つの VM カーネルを共有しています。用意された範囲だけを読み取り専用のリクエストで調査し、ワークショップのサイトとスケジュールを維持してください。読解と通常の入力ミスへの対応を含め、約50分を見込んでください。これは作者による見積もりです。
公開ワークショップのスケジュールを利用する
このステップでは、通常の公開アクセスで維持すべきものを確認します。Workshops を開いてください。ページには Fieldwork Studio のクラフトセッションが紹介されています。Get the workshop schedule をクリックし、fieldwork-schedule.csv をダウンロードします。このファイルには Printmaking と Bookbinding のワークショップ名、時刻、部屋が含まれています。この情報の公開は意図されたものです。

2つのセッションカードと緑色のスケジュールリンクが、通常の公開サービスです。診断情報を評価する間も、実際のワークショップ情報を維持してください。
Kali のターミナルである Auditor に切り替えます。開始ディレクトリは /home/labex/project です。ブラウザーの入口とこのターミナルは同じワークショップサービスにアクセスします。別々の対象マシンを表すものではありません。
cat はテキストファイルを表示します。セキュリティチェックを送信する前に、認可された範囲を読んでください。
cat scope.txt
認可されているのは、targets.txt 内のベース URL に対する読み取り専用の HTTP GET リクエストだけです。ベース URL はサイトを識別し、その末尾に診断用のルートを追加します。一覧を表示します。
cat targets.txt
http://workshop.test:8080/ の下に studio、archive、manual があるはずです。ポート 8080 はこのコースのサービスを識別します。すべてのサイト、設定、ワークショップデータを維持してください。行うのはアクセスの評価であり、アプリケーションの変更ではありません。
相対ファイルパスでエラーになる場合は、pwd で現在のディレクトリを表示してから、次のコマンドで戻ります。
cd /home/labex/project
Auditor を閉じたり再接続したりしても、サイトは再作成されません。ファイルはこのワークスペースに残ります。
判断する前にレスポンスを読む
このステップでは、認可された各サイトの診断エンドポイントを比較します。Auditor で続けてください。HTTP はこのサイトで使われるリクエストとレスポンスのプロトコルです。curl はリクエストを送信し、レスポンス本文を表示します。-i オプションを付けると、ステータスやコンテンツタイプなどのレスポンスヘッダーも表示されます。
curl -i http://workshop.test:8080/studio/maintenance/diagnostics
レスポンスは HTTP/1.0 200 OK で始まります。これはサーバーが要求されたリソースを正常に返したことを意味しますが、それだけでセキュリティ上の問題があるとは判断できません。Content-Type: application/json; charset=utf-8 は、本文が UTF-8 テキストでエンコードされた JSON であることを示します。JSON は中括弧の中で名前付きの値を表します。名前と文字列の値は二重引用符で囲み、数値は引用符で囲みません。
フラットなオブジェクトには service、visibility、database_file、request_count が含まれています。このアプリケーションでは、service は workshop-portal、visibility は internal、データベースファイルは絶対パス、リクエスト数は非負の整数です。ファイルパスは稼働中のサイト設定に由来します。公開ワークショップページと CSV ダウンロードは、その実際の SQLite データベースを読み取ります。SQLite は小さなデータベースをファイルに保存します。リクエストが届くとカウントは変化します。この組み合わせが scope.txt で示された診断レスポンスの契約です。脆弱性の普遍的な定義ではありません。
認証されていないリクエストが、これらの内部値を受け取りました。X-Audit-Event ヘッダーに注目してください。サーバーは実際のレスポンスごとに異なる識別子を付けます。最終評価のため、この識別子を非公開の場所に記録してください。内部値を要約にコピーせずに参照できる証拠になります。
2つ目のサイトと比較します。
curl -i http://workshop.test:8080/archive/maintenance/diagnostics
401 Unauthorized と、保守用の認証情報が必要であるという説明が返るはずです。この拒否は意図されたものです。認可範囲内の認証情報は与えられておらず、回避を試みてはいけません。curl -i は HTTP 401 を表示していても正常に完了できます。拒否レスポンスの配信が成功することと、認可が成功することは別です。
次に3つ目のサイトを調べます。
curl -i http://workshop.test:8080/manual/maintenance/diagnostics
HTTP 200 と JSON が返りますが、診断フィールドは example オブジェクトの中に入れ子になっています。これらはレスポンス形式の説明であり、このサイトのトップレベルの稼働中の診断オブジェクトではありません。単に internal という単語を探すのではなく、構造と意味を比較してください。このレスポンスのイベント識別子も控えます。
404 が表示されたら、URL を指定されたルートと慎重に比較し、修正したリクエストを再実行してください。Could not resolve host または Failed to connect は、目的のレスポンスを取得できなかったことを意味します。これを根拠に安全または公開されているとは判断できません。綴りと、このコースの正確なホスト名およびポートを確認してください。対象を公開ウェブサイトに置き換えてはいけません。
条件の広い Nuclei の検出結果を調べる
このステップでは、チェックが正しく実行されても、主張が広すぎる場合があることを確認します。Auditor で続けてください。Nuclei はテンプレートに基づくスキャナーです。テンプレートはリクエストと、検出結果を生成するレスポンス条件を記述します。検出結果はその条件に一致したことを意味します。それが意図した問題を裏付けるかどうかは、さらに判断が必要です。
用意された初期テンプレートを読みます。
cat too-broad.yaml
YAML ではインデントによって設定をグループ化します。この初期テンプレートは各ベース URL の診断ルートに1回の GET を送り、HTTP ステータス 200 だけに一致させます。{{BaseURL}} プレースホルダーは現在の認可済みベース URL に置き換えられます。診断オブジェクトの意味は調べません。
用意された一覧に対して初期テンプレートを実行します。-t はローカルテンプレートを選択し、-l は対象一覧を読み、-o は検出結果を保存し、-elog はリクエストエラーを保存します。-jsonl は1行に1つの JSON 検出結果を書き込み、-ot はその出力からエンコードされたテンプレートを省きます。準備用のフラグ -duc と -ni は、更新チェックと外部 Interactsh コールバックを無効にします。このテンプレートではどちらも不要です。隔離されたこの演習では、これらのフラグを付けたままにしてください。
nuclei -t too-broad.yaml -l targets.txt -duc -ni -nc -jsonl -ot -o broad-findings.jsonl -elog broad-errors.jsonl
-nc はターミナルの色コードを取り除きます。このコマンドは実際の読み取り専用リクエストを実行します。studio と manual はどちらも 200 を返したため、両方の検出結果が出るはずです。保護された archive ルートは一致しません。検出結果が表示されないだけでは、リクエストが正常に完了し、診断情報の公開条件に一致しなかったとは判断できません。
結果を判断する前に、ネイティブのリクエストエラーログを読みます。
cat broad-errors.jsonl
空のログは、この実行でリクエストエラーが記録されなかったことを意味します。接続に失敗しても Nuclei プロセスの終了ステータスがゼロになる場合があるため、終了ステータスと空の検出結果ファイルのどちらも、単独では十分ではありません。ログにエラーが含まれる場合は、結論を出す前に対象や接続の問題を修正してください。元のエラー証拠を残し、再試行では新しい出力ファイル名を使います。
検出結果を調べます。
cat broad-findings.jsonl
各行には matched-at URL と、リクエストおよびレスポンスの証拠が含まれています。manual の検出結果を、すでに読んだ入れ子のドキュメント例と比較してください。初期テンプレートのステータスマッチャーは記述どおりに動作しましたが、確認したい診断情報公開という観点では、これは誤検出です。studio のレスポンスは、定義された公開条件を満たしています。
これらの合成レスポンスには実際の秘密情報は含まれていません。実際の評価では、生の検出結果に機密情報が含まれる可能性があるため、非公開で扱う必要があります。外部スキャナーへのアップロードや、公開レポートへの貼り付けはしないでください。
証拠に結び付いた評価を保存する
このステップでは、スキャナーによる広い一致と自分の結論を分けます。Auditor で続けてください。サイトごとに1つのエントリーを持つ assessment.json を作成します。各エントリーには、調べた実際のレスポンスイベントと結論を記録します。上で学んだ3つの結果には、exposed、access-denied、documentation-example を使います。
以下は完全なシェルのヒアドキュメントです。cat > assessment.json はファイルを書き込み、> は内容を置き換えます。<<'JSON' は、JSON だけの行まで続くテキストをシェルにそのままコピーさせます。引用符付きの区切り文字は、テキスト内でのシェル展開を防ぎます。ブロックを実行する前に、各 REPLACE_... の値を、そのサイトの診断レスポンスにあった実際の X-Audit-Event に置き換えてください。JSON の二重引用符とカンマは維持します。
cat > assessment.json <<'JSON'
{
"studio": {"event_id": "REPLACE_STUDIO_EVENT", "conclusion": "exposed"},
"archive": {"event_id": "REPLACE_ARCHIVE_EVENT", "conclusion": "access-denied"},
"manual": {"event_id": "REPLACE_MANUAL_EVENT", "conclusion": "documentation-example"}
}
JSON
識別子を控えていなかった場合は、ステップ2の該当サイトの curl -i リクエストを再実行し、新しい識別子を使ってください。読み取りを繰り返すと別の実際のレスポンスが生成され、request_count が増えることがありますが、サイトのアクセスポリシーを修復したり変更したりはしません。
保存したファイルを表示します。
cat assessment.json
引用符、カンマ、イベントの値が誤っている場合は、修正したヒアドキュメント全体を再実行します。プレースホルダーの値をそのままコピーしてはいけません。このワークスペース内で、読み取り可能な通常ファイルとして assessment.json を提出してください。検証は結論を既存のレスポンスと照合します。不足している評価リクエストを生成することはありません。また、この小さな要約に診断ホストや生の本文をコピーする必要もありません。
結果は studio の公開を確認し、archive の実際の拒否を観察し、manual の紛らわしいドキュメント一致を説明します。他のすべてのルートや脆弱性をテストしたと主張するものではありません。次のガイド付き実験は新しい環境で始まり、条件の広いマッチャーを、移植性のあるネイティブ Nuclei チェックに置き換える方法を学びます。
まとめ
公開ワークショップのスケジュールを利用し、HTTP ステータスと JSON 構造を調べ、内部診断情報の公開を1件確認しました。実際の Nuclei 初期チェックを実行し、ドキュメントによる誤検出を説明しました。作成した評価では、通常の公開アクセスを維持しながら、各結論を既存のレスポンスに結び付けています。



