自分のWebサイトのセキュリティを診断する!まず確認したい4つのレイヤと実践手順

Webサイトのセキュリティ診断に役立つ情報。攻撃者の視点で自分のサイトの安全性を確認する方法を解説します。ネットワークからWebアプリケーションまで、4つのレイヤに分けてチェックすべき点と具体的な実践手順を紹介。

※本記事は広告を含みます

はじめに

どうも、職業エンジニアです。

最近は、外部サービスからの個人情報漏洩やセキュリティ事故のニュースを目にする機会が増えていますね。増えすぎい!

「サービス側で漏洩が起きたら、ユーザー側ではどうしようもない」と感じる一方で、「自分で運営しているWebサイトやサーバーの安全性は、本当に大丈夫なんだろうか?」と気になったことはないでしょうか。

自分のサイトの安全性を確認する方法の一つが、攻撃者の視点に立って、外部からどのように見えるのかを調べることです。ポートスキャンや脆弱性診断ツールを使えば、設定ミスや公開すべきでない情報が見つかることもあります。

ただし、闇雲にツールを動かしても、何を確認しているのか分からなければ、診断結果を正しく判断できません。

そこで今回は、Webサイトのセキュリティを確認するために、診断対象を次の4つのレイヤに分けて、基本的な確認方法を紹介していこうと思います。

🟣
この記事で扱うのは、主に自分で管理しているWebサイトやVPSを対象とした基本的なセキュリティチェックです。本格的なペネトレーションテストや、あらゆる脆弱性の検出を保証するものではありません。
💡
実際に手を動かしてみたところ、だいたい2時間ほどで確認&是正まで終わりました。もちろんサイトの状態によって所要時間は変わるので、参考まで。

セキュリティ診断で確認したい4つのレイヤ

Webサイトのセキュリティは、ネットワークからWebアプリケーションまで、複数の観点から確認する必要があります。

この記事では、診断対象を整理しやすくするため、次の4つに分けて解説します。

レイヤ 主な対象 確認したいリスク 代表的な診断ツール・手法
1. ネットワーク/ポート IPアドレス、公開ポート、ファイアウォール SSHやDB管理ポートの意図しない外部公開 nmap
2. 通信の暗号化 TLS、証明書、暗号スイート 古いTLSプロトコル、証明書の設定不備 SSL Labs、testssl.sh
3. Webサーバー/ミドルウェア Nginx、Apache、OS、公開ファイル 設定ファイルやバックアップの露出、不要なHTTPメソッド curl、設定監査
4. Webアプリケーション HTML、JavaScript、API、認証、HTTPヘッダー XSS、SQLインジェクション、認証不備、ヘッダー設定の問題 OWASP ZAP、ブラウザの開発者ツール

下層のネットワークや通信設定に問題があれば、アプリケーション側で安全なコードを書いていても、攻撃を受ける可能性があります。

反対に、ネットワークを適切に制限していても、Webアプリケーションに入力値検証や認証処理の不備があれば、情報漏洩などにつながるおそれがあります。

それぞれのレイヤで何を確認し、何が分かるのかを意識しながら診断を進めることが大切です。

⚠️
診断ツールによっては、多数のリクエストを送信したり、通常とは異なる入力値を送ったりします。対象サーバーの負荷やサービスへの影響を考慮し、VPS・クラウド事業者の利用規約も確認してください。

必ず自分が管理している、または明示的な許可を得ているシステムだけを対象にします。第三者のサーバーに対して無断で診断を実施してはいけません。

1. ネットワーク/ポートの確認(レイヤ1)

まずは、ネットワークポートスキャナの Nmap を使って、外部からサーバーのどのポートにアクセスできるのかを確認します。

Webサイトを公開しているサーバーでは、HTTPやHTTPSだけでなく、SSHやデータベースなどの管理用ポートが意図せず公開されていないかも確認したいところです。

Step 1:Nmapをインストールする

Nmapは、手元のPCなど診断元となる端末にインストールします。
Ubuntu/Debian、macOS、WindowsのWSLでは、次のようにインストールできます。

# Ubuntu / Debian
sudo apt update
sudo apt install -y nmap

# macOS(Homebrew)
brew install nmap

# バージョン確認
nmap --version

Windowsでは、WSLを利用する方法のほか、公式サイトで配布されているWindows版を利用する方法もあります。

Step 2:公開ポートをスキャンする

まずは、自分が管理するサーバーのポートを調べます。

# TCP SYNスキャン
sudo nmap -sS -T3 <診断対象のIPアドレス>

各オプションの意味は次のとおりです。

  • -sS:TCP SYNスキャンを使用して、ポートの状態を確認します。

  • -T3:Nmapのタイミング設定を標準的な速度にします。

このコマンドでは、Nmapが既定で選択する代表的なTCPポートがスキャン対象になります。すべてのポートを調べるわけではありません。

すべてのTCPポートを確認したい場合は、次のように指定できます。

sudo nmap -sS -T3 -p- <診断対象のIPアドレス>

ただし、スキャン対象や実行環境によっては負荷や検知のリスクがあります。必要な範囲から始め、対象環境に応じて実施してください。

CloudflareなどのCDNを利用している場合

Cloudflareなどのリバースプロキシを経由するドメインをスキャンすると、オリジンサーバーではなく、CDN側のIPアドレスが診断対象になることがあります。

オリジンサーバー自体の公開ポートを確認するには、対象サーバーのIPアドレスを指定します。

ただし、オリジンIPを指定したスキャンは、Cloudflareの保護を経由しない確認になります。公開IPを直接指定したアクセスを許可しているか、診断元のIPアドレスがファイアウォールで制限されていないかなど、事前に構成を確認してください。

Step 3:スキャン結果を読む

Nmapの結果では、主に STATE 列を確認します。

状態 意味 確認ポイント
open ポートでサービスが待ち受けている そのサービスを外部公開する必要があるか確認
closed ポートには到達できるが、待ち受けサービスがない 不要なサービスが停止しているか確認
filtered ファイアウォールなどの影響でポートの状態を判定できない 意図した通信制限が適用されているか確認

例えば、Webサイトの公開に必要なポートは、一般的に次の2つです。

  • 80/tcp:HTTP

  • 443/tcp:HTTPS

ただし、HTTPからHTTPSへのリダイレクトに80番ポートを使用しない構成や、別のポートを利用する構成もあります。自分のサイトの構成に合わせて判断してください。

重要なのは、単に開いているポートを減らすことではなく、必要なサービスだけが意図した範囲に公開されていることです。

Webサイトの公開に必要なポートだけが開いており、不要なポートが外部に公開されていなければ、ひとまず問題ありません。

例えば、HTTPとHTTPSだけを公開しているサーバーでは、次のような結果になります↓

見覚えあるやつら
見覚えあるやつら

Step 4:SSHなどの管理ポートを確認する

SSHを利用してサーバーを管理している場合は、標準ポートの22番を確認します。

sudo nmap -p 22 <診断対象のIPアドレス>

結果の判定基準(どうなっていればOKか)

スキャン結果の STATE に応じて、想定通りの防御状態になっているかを確認します。

  • filtered または closed の場合(最も安全 / ベストプラクティス)

    • 判定: OK

    • ファイアウォール(ufw, クラウドのセキュリティグループ等)により外部からのアクセスが遮断されている(filtered)、または22番ポートで待受を行っていない(closed)状態です。

    • SSHのポート番号を標準(22番)から変更している場合も、22番は closed になります。外部からの無差別なブルートフォース攻撃をそもそも届かせない理想的な状態です。

  • open の場合

    • 診断元の端末からSSHポートへ到達できる状態です。

    • 運用に応じた判定:

      • 自宅やオフィスの固定IPのみ許可している場合: 許可されたIPからスキャンしていれば open になるのが正常です。念のため、許可していない別のネットワーク(スマホのテザリング等)からスキャンして filtered になるかを確認しましょう。

      • インターネット全体に全開放している場合: 直ちに不正侵入されるわけではありませんが、攻撃者から常にパスワード総当たりや既知の脆弱性スキャンに晒されるリスクがあります。

open の場合に確認すべき対策

SSHポートを外部に公開せざるを得ない場合でも、以下の要件を満たしていれば安全性を高められます。

  1. パスワード認証の無効化: PasswordAuthentication no に設定し、公開鍵認証のみを許可していること。

  2. root直接ログインの禁止: PermitRootLogin no に設定していること。

  3. 接続元IPアドレスの制限: ファイアウォールで管理者のIPのみに絞り込むこと(可能であれば最善)。

  4. ブルートフォース対策: Fail2ban などを導入し、連続失敗したIPを自動BANする仕組みを整えていること。

ℹ️
デフォルトの22番から別のカスタムポートに変更している場合は、その変更後のポート番号も指定してスキャンを実行し(例: sudo nmap -p <変更後のポート> <IP>)、想定通りのアクセス制御(特定IPのみ許可など)が効いているかを確認してください。
💡
SSHポートの対策についてはこちらの記事でも解説しています。
WEB公開したらやっておきたいSSHセキュリティ|公開鍵認証・fail2ban・SSHポート変更

Step 5:稼働中サービスの情報を確認する

開いているポートで、どのようなサービスが稼働しているかを調べるには、-sV オプションを利用します。

sudo nmap -sV -p 80,443 <診断対象のIPアドレス>

このオプションでは、応答内容などからサービスの種類やバージョンを推定します。

Webサーバーのバージョン情報が外部に表示される場合、攻撃者が既知の脆弱性を調査する手がかりになる可能性があります。

Nginxであれば、server_tokens off; を設定することで、エラーページなどに表示されるバージョン情報を抑制できます。

ただし、バージョン情報を隠すことは補助的な対策です。情報が表示されていないからといって安全とは限りません。OSやミドルウェアの更新を継続し、既知の脆弱性が残っていないか確認することが重要です。

こんな感じで結果出力されていればOKです↓筆者は最初やったときにバージョン情報が出力されていたので、上記の対応でバージョン情報を消しています。

バージョンでがち
バージョンでがち

2. 通信の暗号化を確認する(レイヤ2)

次に、HTTPS通信の暗号化設定を確認します。

TLSの設定が適切でない場合、古いプロトコルや弱い暗号スイートが許可されていたり、証明書の設定に問題があったりする可能性があります。

ここでは、ブラウザから利用できる Qualys SSL Labs の「SSL Server Test」を使用します。

Step 1:SSL Server Testを実行する

  1. Qualys SSL Labs:SSL Server Test を開きます。

  2. Hostname に診断対象のドメイン名を入力します。

  3. 結果を公開一覧に掲載したくない場合は、Do not show the results on the boards にチェックを入れます。

  4. Submit を押して診断を開始します。

診断には数分程度かかることがあります。

なお、CloudflareなどのCDNを利用している場合、通常はCDN側のTLS設定が診断対象になります。オリジンサーバーとの通信設定まで同じ診断で確認できるとは限らないため、どの区間を調べているのかを意識してください。

Step 2:診断結果を確認する

結果では、次の項目を確認します。
出力結果はこんな感じ↓マスクしていますが、Serverと出ている箇所にリンクがあるので、それぞれの出力はそちらから確認可能です。

TLSバージョンで古いの切ったらB→A+に。
TLSバージョンで古いの切ったらB→A+に。

1. 総合評価(Grade)

SSL Labsでは、TLSの設定などをもとにグレードが表示されます。

AやA+は一つの目安になりますが、グレードだけでサイト全体の安全性を判断することはできません。

ただ、評価が低い場合はプロトコルの設定、証明書、暗号スイートなどの詳細を確認し見直したほうが良いでしょう。

2. 対応プロトコル(Protocols)

現在の一般的なWebサイトでは、TLS 1.2とTLS 1.3を利用できることが望ましいです。

一方、TLS 1.0やTLS 1.1などの古いプロトコルは、互換性の要件がなければ無効化を検討します。

Cloudflareを利用している場合は、管理画面の「SSL/TLS」からエッジ証明書の設定を確認し、必要に応じて最低TLSバージョンを引き上げます。

筆者がチェックをかけたときは、ここのバージョンが引っかかってB判定になっていました!

3. 証明書と暗号スイート

証明書の有効期限や証明書チェーン、利用されている暗号スイートも確認します。

証明書の期限切れや不適切な暗号設定があると、HTTPS通信の信頼性に影響する可能性があります。

4. HTTP Strict Transport Security(HSTS)

HSTSは、ブラウザに対してHTTPSでのアクセスを強制するための仕組みです。

SSL Labsの評価にも関係しますが、HSTSを設定するだけでA+評価になるわけではありません。

HSTSを有効にする場合は、対象のドメインやサブドメインがHTTPSに対応していることを確認してください。includeSubDomains や preload を設定する場合は、特に慎重な検証が必要です。


3. Webサーバー/ミドルウェアを確認する(レイヤ3)

このレイヤでは、Webサーバーの設定や公開ディレクトリを確認します。

例えば、設定ファイルやGitリポジトリ、バックアップファイルなどが誤って公開されていると、認証情報やソースコードが漏洩するおそれがあります。

ここでは、curl を使ってHTTPレスポンスを確認する方法を紹介します。

Step 1:隠しファイルやバックアップファイルへのアクセスを確認する

次のコマンドでは、HTTPステータスコードを表示し、レスポンス本文を画面に出さずに確認できます。

# Gitリポジトリの管理ファイル
curl -sS -o /dev/null -w "%{http_code}\n" \
  https://<あなたのドメイン>/.git/HEAD

# 環境変数ファイル
curl -sS -o /dev/null -w "%{http_code}\n" \
  https://<あなたのドメイン>/.env

# バックアップファイル
curl -sS -o /dev/null -w "%{http_code}\n" \
  https://<あなたのドメイン>/index.html.bak

結果の目安は次のとおりです。

ステータスコード 確認ポイント
403 Forbidden アクセスが拒否されている
404 Not Found リソースが見つからないと応答している
200 OK 本文を確認し、意図したファイルが公開されていないか調べる
その他 リダイレクト、認証、CDNなどの挙動も含めて確認する

ここで注意したいのは、ステータスコードだけでは情報漏洩を判定できないということです。

例えば、WordPressでは存在しないURLにアクセスしてもトップページが返され、200 OK になる場合があります。Cloudflareのチャレンジ画面などが返される場合もあります。

200 OK になった場合は、レスポンスの内容まで確認してください。反対に、403 や 404 が返っていても、ほかのURLから同じ情報にアクセスできる可能性があります。

.env や .git/HEAD などの内容が実際に取得できた場合は、機密情報やソースコードの漏洩につながるおそれがあるため、公開ディレクトリやWebサーバーのアクセス制御を見直しましょう。

Step 2:不要なHTTPメソッドが許可されていないか確認する

HTTPには、GET や POST 以外にも複数のメソッドがあります。

アプリケーションによって必要なメソッドは異なりますが、利用していないメソッドを許可する必要があるかは確認しておきたいところです。

例えば、TRACE メソッドの応答は次のコマンドで確認できます。

curl -i -X TRACE https://<あなたのドメイン>/

403 Forbidden や 405 Method Not Allowed などが返れば、TRACEが拒否されていることを示す一つの材料になります。

ただし、400 Bad Request などの応答だけでは、どの層が拒否したのか分からない場合もあります。必要に応じてWebサーバーやアプリケーションのログも確認してください。

また、PUT、DELETE、OPTIONS などのメソッドは、APIなどで正当に使用されることがあります。単純にすべてを禁止するのではなく、アプリケーションで必要なメソッドを整理し、不要なものが許可されていないか確認するのが基本です。

Step 3:Nginxで隠しファイルへのアクセスを制限する

Nginxを利用している場合、ドットから始まるファイルやディレクトリへのアクセスを制限する設定を検討できます。

# 隠しファイル・ディレクトリへのアクセスを拒否
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}

この設定は、.git や .env などへのアクセスを制限するための一例です。

ただし、Nginxの既存の location 設定との優先順位や、サイトの構成によっては、想定どおりに適用されない場合があります。

また、Let's EncryptのHTTP-01認証などで利用される /.well-known/ も対象になり得るため、利用している機能に応じて例外設定を検討してください。

設定を変更したら、まず構文を確認します。

sudo nginx -t

問題がなければ設定を再読み込みします。

sudo systemctl reload nginx

最後に、実際に対象URLへアクセスし、意図したとおりに拒否されることも確認しましょう。


4. Webアプリケーション/HTTPヘッダーを確認する(レイヤ4)

最後は、Webアプリケーションの基本的なセキュリティ設定を確認します。

HTTPレスポンスヘッダーには、ブラウザの動作を制限したり、情報の送信範囲を制御したりするための設定があります。

ただし、ヘッダーが適切に設定されているからといって、XSSやSQLインジェクションなどの脆弱性がないことを保証できるわけではありません。ここでは、あくまで基本的な設定確認を行います。

Step 1:HTTPレスポンスヘッダーを確認する

次のコマンドで、レスポンスヘッダーを表示します。

curl -I https://<あなたのドメイン>/

-I はHEADリクエストを送信し、レスポンスヘッダーを確認するためのオプションです。

CDNやWebサーバー、アプリケーションなど、どの層がヘッダーを付与しているかは構成によって異なります。実際にブラウザへ返されるレスポンスを確認しましょう。

Step 2:主要なセキュリティヘッダーを確認する

1. Strict-Transport-Security(HSTS)

HSTSは、ブラウザにHTTPSでの接続を強制するためのヘッダーです。HTTPSからHTTPへのダウングレード攻撃などのリスクを軽減できます。

設定例は次のとおりです。

Strict-Transport-Security: max-age=31536000; includeSubDomains

max-age は有効期間を秒数で指定します。上記の例では1年間です。

includeSubDomains はサブドメインにも適用する指定です。すべての対象サブドメインがHTTPSに対応していることを確認してから設定してください。

preload はHSTSプリロードリストへの登録に関連する指定です。付けるだけで自動的に登録されるわけではなく、登録要件や運用上の影響も確認する必要があります。

なお、HSTSはHTTPS接続で受け取ったヘッダーに基づいて機能するため、HTTP接続そのものをサーバー側で遮断する設定とは異なります。

2. X-Frame-Options

X-Frame-Options は、Webページがほかのサイトのフレーム内に埋め込まれることを制限し、クリックジャッキングのリスクを軽減するためのヘッダーです。

例えば、自サイト内での埋め込みだけを許可する場合は、次のように設定します。

X-Frame-Options: SAMEORIGIN

埋め込みを一切許可しない場合は、DENY を指定できます。

Content-Security-Policy(CSP)の frame-ancestors ディレクティブで同様の制御を行う方法もあります。CSPを利用している場合は、そちらの設定も確認しましょう。

3. X-Content-Type-Options

X-Content-Type-Options は、ブラウザがContent-Typeを無視してファイルの種類を推測する動作を抑制するためのヘッダーです。

一般的な設定例は次のとおりです。

X-Content-Type-Options: nosniff

これにより、特定の状況で発生するMIMEスニッフィングに関連したリスクを軽減できます。ただし、すべてのスクリプト実行やコンテンツ関連の脆弱性を防ぐものではありません。

4. Referrer-Policy

Referrer-Policy は、別のページへ遷移した際に、遷移元のURL情報をどこまで送信するかを制御するヘッダーです。

一般的な設定例は次のとおりです。

Referrer-Policy: strict-origin-when-cross-origin

この設定では、同一オリジンへの遷移ではパスなどを含むリファラが送信されます。一方、異なるオリジンへのHTTPS遷移では、原則としてオリジン部分のみが送信されます。

HTTPSからHTTPへの遷移ではリファラが送信されません。

URLに機密情報を含めないことも重要ですが、リファラに含める情報を適切に制御することで、意図しない情報の送信を抑えられます。

Step 3:Webアプリケーション自体も確認する

HTTPヘッダーの確認だけでは、アプリケーションの脆弱性までは十分に調べられません。

もう一歩踏み込んで確認したい場合は、OWASP ZAPなどのWebアプリケーション診断ツールを利用する方法があります。

OWASP ZAPでは、Webサイトを巡回してリクエストやレスポンスを調べ、設定に応じて受動的な診断や能動的な診断を行えます。

ただし、能動的な診断では実際に攻撃を模したリクエストを送信します。本番環境で実施すると、データの変更やサービスへの影響が発生する可能性もあります。

最初はローカルの検証環境で試し、認証が必要なページやAPIも含めて、対象範囲と実行内容を把握しながら進めるのがおすすめです。


まとめ

今回は、自分で運営するWebサイトのセキュリティを確認するために、4つのレイヤに分けて基本的な診断方法を紹介しました。

  1. ネットワーク/ポート: Nmapを使い、外部からアクセスできるポートと稼働中のサービスを確認する

  2. 通信の暗号化: SSL Labsなどを使い、TLSプロトコルや証明書、暗号化設定を確認する

  3. Webサーバー/ミドルウェア: curlや設定ファイルを使い、公開ファイルや不要なHTTPメソッドへのアクセスを確認する

  4. Webアプリケーション: HTTPセキュリティヘッダーを確認し、必要に応じてOWASP ZAPなどで診断する

セキュリティ診断は、一度実施すれば終わりというものではありません。ソフトウェアの更新や構成変更に伴って、新たなリスクが生まれることもあります。

まずは、自分のサイトでどのポートが公開されているのか、HTTPSの設定は適切か、不要なファイルが見えていないか、といった基本的なところから確認してみてください。

なお、今回紹介した方法は、主に外部から確認できる設定や公開状態を調べるためのものです。認証処理やアクセス制御、入力値検証などの問題をすべて検出できるわけではありません。

診断結果を過信せず、サーバー側の設定やログ、アプリケーションの実装も含めて継続的に見直していくことが大切です。

最後に

面倒くさい!!