Exposed backup or archive files

A backup archive, database dump or editor backup copy of a configuration file is downloadable from the web root, exposing source code, credentials and user data.

Do this: Delete the archives and deny .bak, .old and .zip in config. A backup archive is the whole application, configuration and often the database in one download.
PassNo backup or archive files were found at common locations.
HighA backup, dump or archive file is publicly downloadable.

The fix, in one snippet

Example to adapt nginx
location ~* \.(sql|bak|old|zip|tar|tar\.gz|swp)$ { deny all; return 404; }

Illustrative values. Change the paths, hostnames and options to match your own site before using it.

The sections below explain what is tested, why it matters and the alternatives.

What we test

Scan.now requests a short fixed list of well-known backup names: /backup.zip, /backup.sql, /backup.tar.gz, /site.zip, /www.zip, /db.sql, /dump.sql, /database.sql, /<hostname>.zip, /wp-config.php.bak, /wp-config.php~, /config.php.bak, /.htaccess.bak and /web.config.bak. It fetches only the first few kilobytes of any 200 response using a Range header and checks the content rather than trusting the status: ZIP files start with PK\x03\x04, gzip with 1F 8B, SQL dumps with -- MySQL dump, CREATE TABLE or INSERT INTO, and a .bak of a PHP file is confirmed by a literal <?php in the body, which means the server returned the source as text. Soft-404 HTML pages are ignored. Whole archives are never downloaded. Rated high; when the file is a configuration backup with credentials, treat it as critical.

Why it matters

A backup archive is the whole site in one download: application source, configuration with database credentials and API keys, and often the uploads directory with customer documents. A database dump adds the user table, with email addresses and password hashes that go straight into offline cracking, plus whatever personal data the application stores. Editor and admin backups are smaller but just as damaging: wp-config.php.bak is served as plain text because the web server only runs .php through the interpreter, and it contains the database password and the authentication salts. Attackers guess file names from the hostname and common conventions, so "nobody knows the URL" is not protection, and search engines index these files when they are linked from anywhere. The exposed files guide explains how scanners find them and the WordPress guide covers the CMS-specific cases.

How to fix it

Never write backups into the document root. Send them off-server (object storage with restricted access, or a backup host) and delete any that are already there:

find /var/www -type f \( -name '*.bak' -o -name '*.sql' -o -name '*.zip' -o -name '*.tar.gz' -o -name '*~' \) -print

Then deny the extensions at the server so a future mistake is not published. nginx (adjust the list if you intentionally serve archives for download):

location ~* \.(bak|old|orig|save|swp|sql|tar|gz|tgz|zip|7z|rar)$ {
    deny all;
    return 404;
}
location ~* ~$ { deny all; return 404; }

Apache 2.4:

<FilesMatch "\.(bak|old|orig|save|swp|sql|tar|gz|tgz|zip|7z|rar)$|~$">
    Require all denied
</FilesMatch>

Cloudflare WAF custom rule: (http.request.uri.path matches "\.(bak|sql|zip|tar\.gz)$"), action Block, on Pro plans or above where regex matching is available. If a configuration backup was reachable, rotate the credentials it contains and, for WordPress, regenerate the salts in wp-config.php. Check the access log for who downloaded it before you closed the door.

Where this fits

Exposed backup or archive files is check 3 of 14 that the website vulnerability scanner runs under exposed files and information disclosure, ordered the way they are worth fixing. That ordering is the point: Fixing this one while the check above it still fails buys less than it looks like.

Fix this one first

Above it in the same category sits Exposed .git repository (critical), where the site's .git directory is reachable over HTTP. An attacker who has that does not need this, so it is the better use of the same hour.

What fixing this still leaves open

Exposed backup or archive files closes one route in. Immediately below it: Exposed phpinfo() page, where a phpinfo() page is publicly reachable; Directory listing enabled, where the web server generates an index of files for a directory that has no index page, exposing every file in it, including ones that are not linked from anywhere; Exposed server status page, where a server status page (Apache mod_status, nginx stub_status or PHP-FPM status) is reachable from the internet, revealing live requests, client IPs, internal hostnames and load details.

Found in the same scan

The website vulnerability scanner reports this alongside checks from other categories that are at least as serious, including Certificate chain and hostname validation, where the certificate presented for this hostname did not validate: The chain does not reach a trusted root, an intermediate is missing, the name does not match, or the certificate is self-signed or expired, and HTTPS is available, where the site could not be reached over HTTPS on port 443, or the TLS handshake failed. A single run of website vulnerability scanner answers all of them at once.

Prompt for an AI Hand this check to an assistant Sign in to copy it
The first few lines
You are a senior web engineer. I ran a security and SEO scanner against my site and it reported the finding below. Fix it properly rather than suppressing the symptom.

Finding: Exposed backup or archive files (high severity)
Scanner check id: exposed-backup-files
17 more lines, including the evidence and the exact fix

The rest of this prompt names the pages and line numbers we found the problem on, the configuration to change, and the constraints a good answer has to respect. It is free, it just needs an account so the work is not scraped wholesale.

Sign in with Google

Signing in is free and takes one click. We store your email address and nothing else.

References

  1. OWASP WSTG: Review Old Backup and Unreferenced Files
  2. CWE-530: Exposure of Backup File to an Unauthorized Control Sphere
  3. WordPress: Hardening WordPress

Related guides