# Fix Apache Directory Listing Exposing Sensitive Files
A security scan reveals that your Apache server exposes directory listings, allowing anyone to browse your file structure. When visiting https://example.com/uploads/, instead of a 403 Forbidden or a custom index page, visitors see a complete listing of all files in the directory.
The Problem: Options Indexes Enabled
The default Apache configuration on many distributions includes Options Indexes, which enables automatic directory listing when no index file (index.html, index.php) exists in a directory:
<Directory /var/www/html>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>The Indexes keyword is the culprit. When Apache receives a request for a directory and no DirectoryIndex file exists, it generates an HTML page listing all files and subdirectories.
Disabling Directory Listing Globally
Remove Indexes from the Options directive:
<Directory /var/www/html>
Options FollowSymLinks
AllowOverride None
Require all granted
</Directory>Without Indexes, Apache returns 403 Forbidden when a directory has no index file. This is the correct security posture for most web applications.
Disabling for Specific Directories Only
If you need directory listings for a specific directory (e.g., a public downloads section) but want to disable them everywhere else:
```apache # Global: disable <Directory /var/www/html> Options FollowSymLinks Require all granted </Directory>
# Exception: enable for downloads only <Directory /var/www/html/downloads> Options Indexes FollowSymLinks Require all granted
# Customize the listing appearance IndexOptions FancyIndexing HTMLTable VersionSort NameWidth=* IndexIgnore .??* *.php *.sql *.bak *.conf *.env HeaderName /downloads/HEADER.html ReadmeName /downloads/README.html </Directory> ```
The IndexIgnore directive hides sensitive file patterns from the listing. IndexOptions controls the appearance.
What Attackers Look For in Directory Listings
An exposed directory listing reveals:
- Database backup files (
backup.sql,dump-2026.sql) - Configuration files (
.env,config.php.bak) - Version control directories (
.git/,.svn/) - Temporary files (
upload_tmp_abc123) - Log files (
access.log,error.log) - Old versions of files (
index.php.old,site.bak)
Test your own server:
curl -s https://example.com/uploads/ | grep -c "<a href="
curl -s https://example.com/.git/ | head -5
curl -s https://example.com/config/ | head -10If any of these return file listings or sensitive content, directory listing is enabled where it should not be.
Additional Hardening
Beyond disabling Indexes, add these protections:
```apache # Block access to hidden files and directories <DirectoryMatch "/\."> Require all denied </DirectoryMatch>
# Block specific file types globally <FilesMatch "\.(env|sql|bak|conf|config|ini|log|sh)$"> Require all denied </FilesMatch>
# Block .git, .svn, .hg directories RedirectMatch 404 /\.(git|svn|hg) ```
Finding All Directories with Indexes Enabled
Search your entire Apache configuration:
grep -rn "Options.*Indexes" /etc/apache2/
# or
grep -rn "Options.*Indexes" /etc/httpd/Check each result. If Indexes appears in a <Directory> block that should not have public listings, remove it. After making changes:
sudo apachectl configtest
sudo systemctl reload apache2Verify the fix by visiting known directory URLs in a browser and confirming you get 403 Forbidden instead of a file listing.