結論(代表的な管理ファイルが公開されていない)
代表的な管理ファイルが公開されていないとは、Webサーバーの公開ディレクトリにある管理用ファイルが外部から取得できない状態を指します。対象は/.env(環境変数)、/.git/HEAD(Git管理情報)、/phpinfo.php、/server-status、/backup.zipといったファイルです。いずれも存在すれば認証情報やソースコードの漏えいに直結するため、セキュリティAIチェッカーは重大度critical・重み5で評価し、ファイル固有の中身まで一致した場合に×と判定します。
この記事のポイント
- 対象は/.env・/.git/HEAD・/phpinfo.php・/server-status・/backup.zipの5種で、どれも存在すれば即座に重大な情報漏えいにつながります。
- 誤公開は、git cloneしたディレクトリの公開、ドキュメントルートの設定誤り、一時ファイルの削除忘れ、既定設定で起こります。
- ステータス200だけでは判断できないため、ソフト404や206 Partial Contentを考慮し、ファイル固有の中身(シグネチャ)で判定します。
- 対策の基本は公開ディレクトリからの物理的な削除で、漏えいした可能性のある認証情報は必ず再発行します。
- ドットファイル拒否ルールでは/.well-known/を必ず除外しないと、証明書の自動更新が失敗することがあります。
| 診断項目名 | 代表的な管理ファイルが公開されていない |
|---|---|
| 項目ID | public.exposed-files |
| 分類 | 公開ファイル・情報露出 |
| 重大度・配点の重み | 最重要(critical) 重み 5 |
| 関連する標準・ガイドライン | OWASP ASVS 5.0.0 V13.4.1(.gitや.svn等のソース管理メタデータを外部から到達不能にする)、V13.4.2(本番でのデバッグ機能無効化)、V13.4.5(監視用エンドポイントを意図なく公開しない)、V13.4.7(Web層で配信する拡張子を限定する)、OWASP WSTG-CONF-04(古いファイル・バックアップ・参照されていないファイルの確認)、CWE-538(外部からアクセス可能なファイル・ディレクトリへの機密情報の挿入)、CWE-530(バックアップファイルの露出)、IPA「安全なウェブサイトの作り方」(パス名パラメータ/ディレクトリ・トラバーサル、ウェブサーバの運用に関する対策) |
代表的な管理ファイルが公開されていないとは
代表的な管理ファイルが公開されていないとは、Webサーバーの公開ディレクトリに、本来公開すべきでない管理用ファイルが置かれたままになっておらず、外部から取得できない状態のことです。セキュリティAIチェッカーは、代表的な5種類を対象に確認します。
| パス | 内容 | 漏えい時の影響 |
|---|---|---|
/.env | 環境変数ファイル(DB接続情報、APIキー等) | 認証情報の直接漏えい |
/.git/HEAD | Gitリポジトリの管理情報 | ソースコード全体と履歴の復元 |
/phpinfo.php | PHPの設定・環境情報 | 内部パス、モジュール、環境変数の露出 |
/server-status | Apache mod_statusの状態ページ | 処理中のURL、接続元IP、内部構成の露出 |
/backup.zip | サイトのバックアップアーカイブ | ソース・設定・データの一括漏えい |
いずれも「存在すれば即座に重大な情報漏えいにつながる」ファイルであるため、重大度critical・重み5で評価します。
robots.txtやサイトマップに書かれたパスから情報が漏れる問題は、「robots.txtに機密パスを列挙していない」と「sitemapに非公開ページを含めていない」で別に確認します。このページは、管理ファイルそのものが取得できてしまう問題に絞って解説します。
管理ファイルの誤公開はなぜ起きるのか
誤公開の主な原因
- デプロイ方法:開発環境で
git cloneしたディレクトリをそのまま公開ディレクトリにすると、.git/が一緒に公開されます。 - フレームワークの慣習:Laravel等は
.envをプロジェクト直下に置きます。ドキュメントルートをpublic/ではなくプロジェクト直下に設定すると.envが配信されます。 - 一時作業の放置:動作確認用の
phpinfo.php、改修前に作ったbackup.zipを削除し忘れる。 - 既定設定:Apacheの
server-statusを全体に許可する設定、ディレクトリ単位のアクセス制御漏れ。
公的機関による注意喚起
スイスの国家サイバーセキュリティセンター(NCSC、現BACS)は、公開された .git フォルダから完全なソースコードと過去の変更履歴、DBパスワードやAPIキーが取得され得ると注意喚起し、2022年10月の公表で、約1,300の該当システムを確認し約400の宛先へ直接通知したとしています。同センターは .env や .DS_Store にも同様のリスクがあるとしています。
「200が返る=公開」ではない理由
多くのCMSやCDNは、存在しないURLにもトップページや独自エラーページをステータス200で返します(ソフト404)。逆に、Apacheやnginxは静的ファイルへのRange付き要求に 206 Partial Content を返します。したがって、ステータスコードだけでは誤検知・見逃しの両方が起こります。セキュリティAIチェッカーはファイル固有の中身(シグネチャ)で判定します。
代表的な管理ファイルが公開されていないの診断基準(セキュリティAIチェッカー)
取得方法
- 診断の最終URLのオリジン(例:
https://www.city.example.lg.jp)に対し、以下を並行してGETします。リダイレクトは追跡しません。- 基準用の存在しないパス
/miniparse-security-review-not-found-probe - 上表の5パス
- 基準用の存在しないパス
- 各要求は
Range: bytes=0-4095を付け、先頭最大4,096バイトだけを受け取ります。サーバーがRangeを無視して大きな応答を返した場合も、先頭4,096バイトで打ち切って判定に使います(大きなZIPやphpinfo出力でも取得失敗にしません)。タイムアウトは4秒です。 - ステータス200または206の応答だけを判定対象にします。
シグネチャ(公開と判定する条件)
| パス | 公開と判定する条件 |
|---|---|
/.env | HTMLでなく、先頭(BOM・空白・コメント行の後でも可)が KEY= 形式 |
/.git/HEAD | HTMLでなく、ref: refs/ または40桁の16進(detached HEAD) |
/phpinfo.php | phpinfo()、PHP Version 見出し、Configuration File (php.ini) というphpinfo出力特有の文字列のいずれか |
/server-status | Apache Status、Apache Server Status、Server uptime、Total accesses:、mod_status のいずれか(大小文字を区別しない) |
/backup.zip | 先頭がZIPのマジックバイト PK + 03/05/07 |
判定条件
| 判定 | 条件 | 得点への影響 |
|---|---|---|
| × 要改善(fail) | いずれかの対象でシグネチャが一致 | 重み5 × 0.00 |
| △ 要確認(warn) | 200/206で応答したがシグネチャ不一致で、かつエラーページとも判断できない対象がある(要目視確認) | 重み5 × 0.45 |
| 対象外(na) | 上記に該当せず、5パスの要求がすべて接続失敗またはタイムアウトで応答を得られなかった。根拠欄は「すべての確認用リクエストが接続失敗またはタイムアウトとなり、公開の有無を判定できませんでした。」 | 計算から除外 |
| ○ 問題なし(pass) | 上記以外(1パス以上で応答があり、非200/206またはエラーページと判断) | 重み5 × 1.00 |
「エラーページと判断」は、基準パスが200/206を返すサイト(ソフト404)である場合、基準パスと同じ <title> を返した場合、または応答がHTMLである場合です。これらは誤検知として除外し、根拠欄に列挙します。
判定の限界
代表的な5パスのみの確認です。WAF等が診断の要求を遮断して5パスすべてが接続失敗・タイムアウトになった場合は対象外(判定不能)で、非公開を確認できたわけではありません。一部のパスだけ応答がない場合は ○ になり得るため、後述の確認方法で自ら確かめてください。
なお、診断の最後にトップページを取り直し、HTTP 403/429または無応答に変わっていた場合は、レポートを返さず診断全体をエラーにします。.svn/、.DS_Store、*.bak、wp-config.php~、/old/、ディレクトリ一覧などは別項目または手動確認の対象です。○ でも「誤公開がない」ことの保証にはなりません。
自治体サイトでの判定例
| 応答の状態 | 判定 |
|---|---|
.git/HEAD が ref: refs/heads/main を返す | × |
| すべて404/403 | ○ |
| 5パスすべてがタイムアウト | 対象外 |
| CMSが全URLにトップページHTMLを200で返す | ソフト404として除外し ○(根拠欄に除外理由を記載) |
/backup.zip が200で中身がZIPではないバイナリ | △(目視確認) |
管理ファイルが公開されているとどんなリスクがあるか
.env:DB・メール・外部APIの認証情報が漏れると、住民情報を含むDBへの不正アクセスや、自治体ドメインからのスパム送信に直結します。.git:ソースコード全体と過去のコミットが復元でき、削除済みのパスワードや未修正の脆弱性が見つかることがあります。phpinfo:ドキュメントルートの絶対パス、読み込まれた拡張、環境変数(クラウド環境ではキーを含むことがある)を表示し、他の攻撃の足がかりになります。server-status:処理中のリクエストURL(クエリ文字列にトークンや個人情報が含まれる場合を含む)と接続元IPを表示します。- バックアップアーカイブ:上記すべてを一度に含み得ます。
管理ファイルの公開を防ぐ方法(Apache・nginx・IIS・Next.js)
1. まず削除・移動する
最も確実なのは、公開ディレクトリから該当ファイルを物理的に取り除くことです。.env はドキュメントルートの外へ置き、ドキュメントルートをフレームワークの public/ に設定します。漏えいの可能性がある認証情報は、削除と同時に**必ず再発行(ローテーション)**します。
2. Webサーバーで拒否する(多層防御)
Apache(.htaccess または VirtualHost)
# ドットで始まるファイル・ディレクトリを拒否(.well-known は除外)
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule "(^|/)\.(?!well-known/)" - [F]
</IfModule>
# バックアップ・設定系の拡張子を拒否
<FilesMatch "\.(?:zip|tar|gz|bak|old|orig|sql|env|log|ini)$">
Require all denied
</FilesMatch>
# phpinfo の撤去が原則。どうしても残る場合
<Files "phpinfo.php">
Require all denied
</Files>
server-status は VirtualHost側で管理者端末のみに限定します(.htaccessでは設定できません)。
<Location "/server-status">
SetHandler server-status
Require ip 127.0.0.1 192.0.2.10
</Location>
nginx
location ~ /\.(?!well-known/) { deny all; return 404; }
location ~* \.(?:zip|tar|gz|bak|old|orig|sql|env|log)$ { deny all; return 404; }
location = /phpinfo.php { return 404; }
IIS(web.config)
<system.webServer>
<security>
<requestFiltering>
<hiddenSegments>
<add segment=".git" />
<add segment=".env" />
</hiddenSegments>
<fileExtensions allowUnlisted="true">
<add fileExtension=".zip" allowed="false" />
<add fileExtension=".bak" allowed="false" />
</fileExtensions>
</requestFiltering>
</security>
</system.webServer>
Next.js(Vercel)
public/ 配下だけが静的配信されるため、.env* や .git を public/ に置かないことが基本です。ビルド成果物に不要ファイルが混入していないか、デプロイ前に public/ の一覧を確認します。
3. デプロイ手順を見直す
git cloneではなく、ビルド済み成果物だけを転送する(rsync --exclude '.git' --exclude '.env'等)。- CMSの更新作業でバックアップを作る場合は、公開ディレクトリ外に保存し、作業後に削除する。
- 調達仕様書・保守契約に「公開領域に管理ファイルを置かない」「納品時に確認する」を明記する。
4. 確認方法
for p in /.env /.git/HEAD /phpinfo.php /server-status /backup.zip; do
printf '%s ' "$p"; curl -s -o /dev/null -w '%{http_code}\n' "https://www.city.example.lg.jp$p"
done
curl -s -H 'Range: bytes=0-200' https://www.city.example.lg.jp/.git/HEAD
404または403で、中身が当該ファイルでないことを確認します。対処後はセキュリティAIチェッカーで再診断し、根拠欄に公開が確認された対象が残っていないことを確かめます。
サイトを壊さないための注意点(ガードレール)
- ドットファイル拒否のルールでは
/.well-known/を必ず除外します(security.txt、ACMEのHTTP-01認証、各種ドメイン認証で使います)。除外しないと証明書の自動更新が失敗することがあります。security.txtの設置は「security.txtを公開」で確認します。 - 拡張子拒否は、住民向けに配布しているZIPやCSV(オープンデータ等)まで止めないよう、配布用ディレクトリを確認してから適用します。
- 設定変更後は、トップページ・主要ページ・ダウンロードファイルが表示できることを確認します。
よくある質問(FAQ)
.gitフォルダが公開されているとどうなりますか?
.gitからはソースコード全体と過去のコミットが復元でき、削除済みのパスワードや未修正の脆弱性が見つかることがあります。スイスのNCSC(現BACS)は、公開された.gitフォルダから完全なソースコードや変更履歴、DBパスワードやAPIキーが取得され得ると注意喚起しています。
.envファイルが外部から見えてしまう原因は何ですか?
Laravel等は.envをプロジェクト直下に置くため、ドキュメントルートをpublic/ではなくプロジェクト直下に設定すると.envが配信されます。.envはドキュメントルートの外へ置き、ドキュメントルートをフレームワークのpublic/に設定してください。
管理ファイルが公開されていたら何をすればよいですか?
まず公開ディレクトリから該当ファイルを物理的に取り除きます。漏えいの可能性がある認証情報(DB、メール、外部APIのキー等)は、削除と同時に必ず再発行(ローテーション)します。そのうえでWebサーバーの拒否設定を多層防御として追加します。
URLにアクセスして200が返れば公開されていると判断してよいですか?
判断できません。多くのCMSやCDNは存在しないURLにもトップページや独自エラーページを200で返し(ソフト404)、逆に静的ファイルへのRange付き要求には206を返します。中身が当該ファイル特有の形式かどうかで判断します。
管理ファイルの公開チェックで「対象外」になったのは安全という意味ですか?
安全という意味ではありません。WAF等が診断の要求を遮断して5パスすべてが接続失敗・タイムアウトになった場合の判定不能です。curlなどで自ら確認してください。また○でも、確認したのは代表的な5パスだけで、誤公開がないことの保証にはなりません。
.htaccessでドットファイルを拒否したら証明書が更新できなくなりました。
ドットで始まるパスをすべて拒否すると、ACMEのHTTP-01認証やsecurity.txtで使う/.well-known/も拒否されます。拒否ルールでは/.well-known/を必ず除外してください。
この項目を含む127項目を、URLを入れるだけで無料診断します。