目次
1. うちのサイト、外からどう見えている?
「SSLは設定した」「ファイアウォールも入れた」——そう思っていても、外部から見ると意外な穴が残っていることは珍しくありません。
情報システム担当者であれば、こんな不安を感じたことはないでしょうか。
- Webサーバーの設定、本当にベストプラクティスに沿っている?
- SSL証明書の期限切れに気づかず、ブラウザ警告が出ていないか?
- 開発時に開けたポートが、そのまま外部に公開されていないか?
.envや.gitが外部からアクセスできる状態になっていないか?
2. なぜ脆弱性診断が必要か
攻撃の典型的な流れ
- 偵察 — ポートスキャン・ディレクトリ探索で「入口」を探す
- 脆弱性探索 — バージョン情報・設定ミスから突破口を見つける
- 侵入・悪用 — 情報窃取、改ざん、他サーバーへの踏み台化
放置した場合のリスク
情報漏洩
顧客データや認証情報の流出。賠償責任や信用失墜につながる
サイト改ざん
フィッシングページの設置やマルウェア配布の踏み台にされる
踏み台化
スパム送信やDDoS攻撃の発信元として悪用される
3. 5つの診断カテゴリ
IPintelの脆弱性診断は、Webサイトのセキュリティを5つの観点から総合的にチェックします。
3.1 HTTPセキュリティヘッダー
HTTPセキュリティヘッダーは、いわば「ブラウザへの安全指示書」です。 サーバーからブラウザに「このページはこう扱ってほしい」と伝えることで、 XSS(クロスサイトスクリプティング)やクリックジャッキングなどの攻撃を防ぎます。
チェック項目
| ヘッダー | 役割 |
|---|---|
Strict-Transport-Security | HTTPS接続を強制(HSTS) |
Content-Security-Policy | 読み込み可能なリソースを制限(XSS対策) |
X-Frame-Options | iframe埋め込みを制限(クリックジャッキング対策) |
X-Content-Type-Options | MIMEタイプのスニッフィングを防止 |
Referrer-Policy | リファラー情報の送信範囲を制御 |
Permissions-Policy | ブラウザ機能(カメラ・位置情報等)の使用を制御 |
Server ヘッダー | バージョン情報が露出していないか確認 |
Server: nginx/1.24.0 のように バージョン番号が露出していると、既知の脆弱性を狙った攻撃を受けやすくなります。server_tokens off; で非表示にしましょう。3.2 SSL/TLS証明書
SSL/TLS証明書は暗号化通信の「鍵」です。 この鍵が古かったり期限切れだったりすると、通信の安全性が保証できません。
チェックポイント
- 証明書の有効期限 — 期限切れはブラウザに警告を表示させ、ユーザーの信頼を失う
- TLSバージョン — TLS 1.0/1.1は既に非推奨。TLS 1.2以上が必須
- 証明書チェーン — 中間証明書が正しく設定されているか
- ドメイン名の一致 — 証明書のCN/SANとアクセスURLが一致しているか
対処のポイント
# Let's Encrypt で無料SSL証明書を取得(certbot)
sudo certbot --nginx -d example.com -d www.example.com
# 自動更新の設定確認
sudo certbot renew --dry-run
# nginx で TLS 1.0/1.1 を無効化
# /etc/nginx/conf.d/ssl.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;3.3 ポートスキャン
ポートは建物でいう「ドア」です。 必要なドア(80/443番ポートなど)だけを開けて、 不要なドアは閉じておくのがセキュリティの基本です。
特に危険なポート
| ポート | サービス | 外部公開時のリスク |
|---|---|---|
3306 | MySQL | データベースへの直接攻撃 |
5432 | PostgreSQL | データベースへの直接攻撃 |
6379 | Redis | 認証なしでデータ読み書き可能な場合も |
27017 | MongoDB | 認証なしの場合、全データ漏洩 |
22 | SSH | ブルートフォース攻撃の対象 |
8080 | 管理画面等 | 開発用サーバーの露出 |
対処例
# firewalld: 許可するポートを限定
sudo firewall-cmd --permanent --zone=public --add-service=http
sudo firewall-cmd --permanent --zone=public --add-service=https
sudo firewall-cmd --reload
# iptables: DBポートを外部からブロック
sudo iptables -A INPUT -p tcp --dport 3306 -j DROP
sudo iptables -A INPUT -p tcp --dport 5432 -j DROP
sudo iptables -A INPUT -p tcp --dport 6379 -j DROP3.5 ディレクトリ探索
Webサーバー上に「見えてはいけないファイル」が 公開されていないかをチェックします。 約100パスを探索し、ソフト404対策(カスタム404ページを正常なレスポンスと誤検知しない処理) も実装しています。
特に危険なファイル
.env — 認証情報の漏洩
データベースパスワード、APIキー、シークレットキーなどが平文で記載されていることが多い。 これが公開されると、システム全体が侵害される可能性があります。
.git/HEAD — ソースコードの漏洩
Gitリポジトリがそのまま公開されている状態。 ソースコード全体を復元でき、さらなる脆弱性の発見につながります。
phpinfo.php — サーバー情報の全公開
PHPバージョン、モジュール一覧、環境変数、ファイルパスなど、 攻撃に有用な情報がすべて表示されます。
wp-config.php / バックアップファイル
WordPressの設定ファイルやデータベースバックアップが公開されているケース。.bak、.sql、.tar.gz などの拡張子に注意。
対処例(nginx)
# 隠しファイル(.env, .git 等)へのアクセスを拒否
location ~ /\. {
deny all;
return 404;
}
# バックアップファイルへのアクセスを拒否
location ~* \.(bak|sql|tar\.gz|zip|log)$ {
deny all;
return 404;
}対処例(Apache/.htaccess)
# 隠しファイルへのアクセスを拒否
<FilesMatch "^\.">
Require all denied
</FilesMatch>
# 特定ファイルへのアクセスを拒否
<FilesMatch "\.(env|bak|sql|log)$">
Require all denied
</FilesMatch>4. スコアの読み方
診断結果は100点満点の減点方式で、 A〜Fの6段階グレードで評価されます。
グレード基準
| グレード | スコア | 意味 |
|---|---|---|
| A | 90〜100 | 優秀 — 主要なセキュリティ対策が適切に設定されている |
| B | 80〜89 | 良好 — 軽微な改善点がある |
| C | 70〜79 | 要改善 — いくつかの対策が不足 |
| D | 50〜69 | 不十分 — 重要な対策が欠けている |
| E | 30〜49 | 危険 — 早急な対応が必要 |
| F | 0〜29 | 非常に危険 — 重大な脆弱性が複数存在 |
減点の仕組み
| 深刻度 | 減点 | 例 |
|---|---|---|
| Critical | -20点 | .env公開、DBポート外部公開 |
| High | -10点 | HSTS未設定、TLS 1.0/1.1有効 |
| Medium | -5点 | CSP未設定、X-Frame-Options未設定 |
| Low | -2点 | Referrer-Policy未設定 |
5. よくある検出項目と対処法
Critical: .env ファイルが公開されている
データベースパスワードやAPIキーが外部から閲覧可能な状態です。
# nginx: .envファイルへのアクセスを拒否
location = /.env {
deny all;
return 404;
}
# Apache: .htaccess に追記
<Files ".env">
Require all denied
</Files>Critical: データベースポートが外部公開
MySQL(3306)、PostgreSQL(5432)、Redis(6379)等が外部からアクセス可能です。
# ファイアウォールでDBポートを遮断
sudo firewall-cmd --permanent --remove-port=3306/tcp
sudo firewall-cmd --permanent --remove-port=5432/tcp
sudo firewall-cmd --permanent --remove-port=6379/tcp
sudo firewall-cmd --reload
# Docker の場合: ports ではなく expose を使う
# docker-compose.yml
services:
db:
# ports: ["3306:3306"] ← これは外部公開される
expose: ["3306"] # ← コンテナ間のみHigh: HSTS が設定されていない
HTTPS接続が強制されず、HTTP経由のアクセスで中間者攻撃のリスクがあります。
# nginx
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Apache
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"Medium: Content-Security-Policy が未設定
XSS攻撃に対するブラウザ側の防御が有効になっていません。段階的に導入できます。
# まずは Report-Only モードで影響を確認
add_header Content-Security-Policy-Report-Only "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';" always;
# 問題なければ本番適用
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline';" always;6. 今すぐ診断してみる
IPintel Service - Webサイト脆弱性診断ガイド