はじめに
https://example.com/.git/ や https://example.com/.env ── このURLにブラウザでアクセスできてしまうサイトは、今も珍しくありません。.git が見えればソースコード一式やコミット履歴が、.env が見えればDBのパスワードやAPIキーがそのまま読まれます。攻撃者は人間ではなくbotで、これらのパスを機械的に巡回しています。
やっかいなのは、これがアプリのコードではなく「ファイルが置かれたまま、Webサーバが配信できる状態になっている」だけで起きることです。つまり設定数行で確実に塞げる一方、放置していると気づかないまま漏れ続けます。この記事では、何が危ないのかを整理し、nginx / Apache / WordPress でのコピペ設定と、自分のサイトが大丈夫かの確認方法をまとめます。
確認は必ず自分が管理するサイトに対してのみ行ってください。他者のサイトへのアクセスや探索は、状況により不正アクセス等に該当し得ます。
何が危ないのか
公開ディレクトリ(ドキュメントルート)に置かれがちで、外から読めると危険な代表例です。
| パス | 漏れると何が起きるか |
|---|---|
/.git/ |
ソースコード・コミット履歴・過去に消したはずの秘密情報まで復元され得る |
/.env |
DB接続情報・APIキー・各種シークレットが平文で露出 |
/.svn/ /.hg/
|
同上(Git以外のバージョン管理) |
*.sql *.sql.gz 等のDBダンプ |
データベースまるごと |
*.bak *.old config.php~ 等の編集中・退避ファイル |
設定や認証情報 |
/composer.json /package.json /.env.example
|
構成・依存の手がかり(単体の害は小さいが偵察に使われる) |
特に .git は危険です。.git/ ディレクトリ全体が配信可能だと、専用ツールでローカルにリポジトリを丸ごと復元できてしまい、index.php だけ見られるのとは桁違いの被害になります。
なぜ起きるかというと、git clone や git pull で本番に配置した、エディタが退避ファイルを作った、デプロイ時に .env を一緒に上げた、といった運用上のごく普通の操作の結果です。アプリのバグではないので、コードレビューでは見つかりません。
直し方(コピペ)
考え方は2段構えです。(1) そもそもドキュメントルートに置かない、(2) 置かれていてもWebサーバが配信しない。両方やるのが理想ですが、まずは(2)を即入れて出血を止めます。
nginx
# ドットファイル/ディレクトリ(.git .env .svn など)を拒否。
# .well-known(Let's Encrypt等)だけは通す。
location ~ /\.(?!well-known).* {
deny all;
}
# バックアップ・ダンプ系の拡張子を拒否
location ~* \.(bak|old|orig|save|swp|sql|sql\.gz|tar|tar\.gz|zip)$ {
deny all;
}
反映:
nginx -t && systemctl reload nginx
- 補足:
locationの正規表現マッチは設定順序や他ブロックとの兼ね合いで挙動が変わることがあります。反映後に必ず後述の方法で確認してください。
Apache(.htaccess)
# .git .env など隠しファイル/ディレクトリを拒否(.well-known は除外)
<DirectoryMatch "/\.(?!well-known)">
Require all denied
</DirectoryMatch>
# ピンポイントで .env を拒否(.htaccess単位で効かせたい場合)
<FilesMatch "^\.env">
Require all denied
</FilesMatch>
# バックアップ・ダンプ系を拒否
<FilesMatch "\.(bak|old|orig|save|swp|sql|gz|tar|zip)$">
Require all denied
</FilesMatch>
-
DirectoryMatchはサーバ設定(httpd.conf等)に書く必要があり、.htaccessには書けません。.htaccessだけで対応する場合はFilesMatch側を使ってください。 - Apache 2.2系では文法が異なります(
Order deny,allow/Deny from all)。2.4系前提の例です。
WordPress
WordPressサイトでも、上記の nginx / Apache 設定がそのまま使えます(WordPress固有の対策ではなく、Webサーバ側で塞ぐのが確実です)。加えてWordPressでありがちなのは、
- 移行時に残した
wp-config.php.bakや*.sqlダンプの置き忘れ → 上の拡張子ルールで拒否。 - プラグイン/テーマを
gitで管理していて.gitごとアップロード → 上のドットファイルルールで拒否。
なお wp-config.php 自体の保護やディレクトリ一覧の停止など、WordPress全体の最低限対策は別記事にまとめています。
→ 関連記事:WordPressセキュリティ 最低限やることチェックリスト10
根本対策:そもそも置かない
- 本番には
git cloneで配置せず、ビルド成果物だけをデプロイする(.gitを含めない)。 -
.envはドキュメントルートの外、またはアプリのルート外に置く。 - デプロイ対象から
.git・.env・*.sql・退避ファイルを除外する(rsyncの--exclude、CI/CDのデプロイ定義など)。
自分のサイトを確認する
自分が管理するサイトに対して、外から見える状態かを確認します。
curl でHTTPステータスを見るのが手軽です(200 が返ると配信されている=危険、403/404 なら拒否できている)。
# ステータスコードだけ確認
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/.env
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/.git/HEAD
curl -s -o /dev/null -w "%{http_code}\n" https://example.com/.git/config
-
.gitは/.git/HEADや/.git/configが200で中身を返すかが要点です。トップの/.git/が一覧表示されなくても、内部ファイルが個別に取得できると復元され得ます。 - 設定変更後はブラウザキャッシュやCDNキャッシュの影響を受けることがあるので、キャッシュを避けて確認してください。
外形を一括で点検したい場合は、無料ツールも使えます。
- OWASP ZAP:ローカルで動かせるOSSスキャナ。公開ファイルや設定の問題を受動的に検出できる。
- nikto などのオープンソースの定番チェッカー:既知の危険パスを一括確認。
- サイトドック(sitedock.jp):URLを入れると登録不要で、公開されている設定ファイルやヘッダ・バージョン露出などの外形をまとめて健診しスコア化する無料サービス。確認手段の一つとして。
ツールはあくまで補助です。最終的には、上の curl で主要パスが 200 を返さないことを自分の目で確認するのが確実です。
まとめ
-
.git/.env/ DBダンプ / 退避ファイルがドキュメントルートから配信できると、ソースや認証情報がそのまま漏れる。botが機械的に巡回しているため発見は時間の問題。 - アプリのバグではなく「ファイルが配信可能な状態」で起きるので、Webサーバ設定で塞ぐのが確実(nginx/Apacheのコピペ設定で対応可)。
-
.well-knownは除外して、Let's Encrypt等を壊さないこと。 - 根本対策は「そもそも置かない」:本番は
.gitを含めずビルド成果物だけをデプロイ、.envはルート外、デプロイ対象から除外。 - 反映後は
curlで主要パスが200を返さないかを自分の管理サイトで必ず確認する。
関連記事
- Webサイトに最低限入れるべきHTTPセキュリティヘッダ7種と設定例
- WordPressセキュリティ 最低限やることチェックリスト10
- 兵庫県の企業サイト307件を外形調査したら、セキュリティヘッダがほぼ全滅だった
想定タグ: Security Git nginx Apache WordPress
想定読了時間: 約7〜9分
難易度: 初〜中級
お知らせ — バーチャルセキュリティコンシェルジュ「一ノ瀬あかり」がデビューしました🎉
JIISセキュリティラボから、セキュリティ用語をやさしく動画で解説する案内役「一ノ瀬あかり」が登場しました。よければデビューのご挨拶もご覧ください。