SLL #17|ZAPの指摘をNginx設定で修正し、再スキャンでゼロにしてみた

SLL #17 ZAPの指摘をNginx設定で修正し、再スキャンでゼロにしてみた のアイキャッチ画像。Beforeの警告アイコン群から歯車を経て、Afterの緑のチェックマーク付きシールドに変化する図解。「Phase6「Security」」のラベル付き。 Docker

個人学習プロジェクト 「Security Learning Lab(SLL)」 の学習記録です。

今回は、前回OWASP ZAPで検出された5件の指摘をNginxの設定変更で解消し、再スキャンでアラートがゼロになるまでを実践した内容についてまとめます。

学習時間

約1.5時間

今日やったこと

  • EC2へのSSH接続がタイムアウトし、ルーター交換でグローバルIPが変わっていたことが原因と判明。セキュリティグループのSSH許可IPを「マイIP」で更新して解決
  • Docker Composeの構成を確認し、Nginxコンテナがイメージのデフォルト設定をそのまま使っていることを再確認
  • ホスト側に nginx/default.conf を作成し、server_tokens off と3つのセキュリティヘッダ(X-Content-Type-Options、X-Frame-Options、Content-Security-Policy)を追加
  • docker-compose.ymlに volumes を追加し、設定ファイルをコンテナ内のNginx設定ディレクトリ(confディレクトリ配下のdefault.conf)に読み取り専用でマウント
  • docker compose up -d でNginxコンテナだけが再作成されることを確認し、curl -I でヘッダの付与とバージョン表示の消失を確認
  • ZAPで再スキャンし、5件が1件(CSPのディレクティブ定義漏れ)に減ったことを確認
  • CSPに form-action と base-uri を追加して docker compose restart web、再スキャンでアラート0件を確認
  • 修正後のHTMLレポートを出力し、修正前のレポートと並べて保存

学習内容

マウントで設定をコンテナに持ち込む

コンテナは使い捨てのため、中の設定ファイルを直接書き換えても、コンテナを作り直した瞬間に元に戻ってしまう。ホスト側にファイルを置き、docker-compose.ymlの volumes でコンテナ内の決まった場所に重ねて見せるのがマウント。置かれているファイルを書き換えるのではなく、Nginxが読みに来る場所に「読んでほしいファイルを新たに置く」という考え方で、コンテナを何度作り直しても同じ設定が反映される。末尾の :ro は読み取り専用の指定で、必要最小限の権限だけを渡す基本に沿ったもの。

server_tokens offの効果

Nginxはレスポンスヘッダの Server と、404などのエラーページ本文の2箇所にバージョンを名乗っている。server_tokens off はその両方からバージョン番号を消す。「Nginxであること」までは隠せないが、「どのバージョンか」が分からなければ既知の脆弱性を狙い撃ちしにくくなる。この1行で前回のLow 2件(Serverヘッダ、Banner Leak)が同時に解消した。

add_headerのalways

Nginxの add_header は、既定では200番台などの正常応答にしかヘッダを付けない。末尾に always を付けると404などのエラー応答にも付くようになる。前回のBanner Leakが /robots.txt の404で検出されていたように、診断ツールはエラーページも見ているので、always がないと再検出される。

default-srcを引き継がないCSPディレクティブ

CSPの default-src は「リソースをどこから読み込むか」の既定値で、script-src や img-src などは未指定ならこれを引き継ぐ。一方で frame-ancestors(どこに埋め込めるか)、form-action(フォームをどこに送るか)、base-uri(基準URLの差し替え防止)は読み込みとは別種の制御のため引き継がれず、明示的に書かないと未設定扱いになる。form-action 'self' は、ページが改ざんされてもフォームの送信先を攻撃者のサイトに向けられないようにする、出口側の防波堤。

Composeの差分検知とrestart

docker-compose.ymlを変更して up -d すると、Composeは変更があったサービスだけを再作成し、変更のないサービス(今回はMySQL)には触れない。一方、マウントしたファイルの中身だけを変えた場合はComposeから見て設計に変更がないため、docker compose restart web で明示的に再起動して設定を読み直させる必要がある。

困ったこと・つまずいたこと

SSH接続がタイムアウトした

  • 何に困ったか:1週間ぶりにSSH接続を試みたところ「Operation timed out」で接続できなかった
  • どう解決したか:直前にルーターを交換しており、グローバルIPが変わったことでセキュリティグループの「自分のIPのみ許可」から外れていた。EC2コンソールでSSHルールのソースを「マイIP」で更新し、旧IPの行を削除して解決。実務で定番の「接続元IPが変わった」問い合わせを自分で体験する形になった

修正後のスキャンで新しい指摘が出た

  • 何に困ったか:5件は消えたが、代わりに「CSP: CSP重要ディレクティブの定義漏れ」というMediumの指摘が新たに出た
  • どう解決したか:アラートの詳細を確認し、form-action が default-src にフォールバックしないディレクティブだと分かった。CSPに form-action 'self'; base-uri 'self' を追記して再スキャンし、0件になった

今日の学び・気づき

  • 「検出→修正→再診断→クリア」を自分の環境で一周できた。仕事で提供している再診断サービスの流れが、手を動かすことで具体的なイメージになった
  • 修正によって前回の指摘が消えても、修正内容に対して新たな指摘が出ることがあると体験した。「CSPが無い」が解消されたら次は「CSPの中身」を見られる、という診断の階層構造を実感した
  • マウントは「置かれているものを書き換える」のではなく「読み込んでほしいものを新たに置く」仕組みだと理解できた。設定の正本をホスト側に持つことで、コンテナを使い捨てにできる
  • 設定を1行足すだけで直る項目でも、always の有無やフォールバックの仕様のような細部を知らないと、ツールには「未対応」と判定される。対策の「つもり」と実際の効き目は別物だと感じた
  • ルーター交換でSSHが繋がらなくなったのは、セキュリティグループが正しく機能している証拠でもあった。不便さと安全性は表裏一体だと改めて思った

今日の達成

Zero Alerts
ZAPの指摘5件をNginx設定の修正で解消し、再スキャンでアラート0件を達成した。

次回やること

  • Burp Suiteを導入し、ZAPとの違いを比べながら手動診断の基本を学ぶ

今日のひとこと

直近でWi-Fiルーターを交換していたので、SSH接続できなかったときは少し焦った。それはさておき、検出した問題を修正するまでの作業を実施! 実際にセキュリティチェックして、修正対応を行うまでの流れを経験すると、自分の仕事への理解が一段深まったように感じる。少し感動すら覚えた。知識だけでなく、実践を通じて学ぶことの大切を痛感する。

タイトルとURLをコピーしました