CWE-530, Exposure of Backup File to an Unauthorized Control Sphere, is what you get when a backup copy of a file ends up somewhere the public can request it. It hits any team that runs a web server, which is nearly everyone. MITRE marks it as not specific to any language or technology.
How it happens
MITRE gives a plain picture. Older files get renamed with an extension such as .~bk to tell them apart from the production copy. If those renamed files stay in the webroot, the source code can often be retrieved. The rename may have been done automatically by the web server or by hand by an administrator.
The usual story: someone edits a file on the server, saves a copy as index.php.bak first, and forgets it. A web server will serve a .bak file as plain text, because it no longer matches the extension that triggers the script engine. So the visitor gets your source instead of your page.
Backup archives follow the same path. A zip of the site dropped in the document root is just a download link for anyone who finds it.
CVE-2024-7315 shows a variant. MITRE describes it as a chain: a WordPress plugin did not use enough randomness when generating the filename for a backup (CWE-340), so attackers could obtain the backup files (CWE-530). The backup location was reachable, and the filename was guessable. See the Gold entry for CVE-2024-7315.
What an attacker gains
MITRE lists a confidentiality impact: reading application data. At a minimum, whoever gets the file has everything in it. That can be database calls, the format of parameters the application accepts, or the architecture of the site.
Source with database credentials is the worst case, but even without secrets the attacker now reads your logic instead of probing it blind.
How to find it
- Look at your webroot for files ending in
.bak,.old,.orig,.save,~,.zip,.tar.gzand.sql. - Check deploy scripts and editors. Some editors drop backup files next to the original by default.
- Run your own deployment artifact through a file listing before it ships and fail the build if backups appear.
- MITRE notes that static analysis tools can find some instances of this weakness, though a file listing of what you actually deploy is more direct.
A quick check from a shell:
find ./public -type f \( -name "*.bak" -o -name "*.old" -o -name "*~" -o -name "*.orig" -o -name "*.zip" -o -name "*.sql" \)
How to fix it
MITRE's mitigation is a policy one: prohibit backing up web application source code in the webroot. Turn that into practice:
- Keep backups outside the document root, on storage the web server cannot serve.
- Use version control for history instead of copying files by hand.
- Build deployments from a clean checkout, so stray files on a server never matter.
- If a plugin generates backups, make sure the location is not web accessible and the names are not guessable.
- Add a web server rule that denies requests for common backup extensions as a second layer.
Quick check
Why does a .bak file leak source when a .php file does not?
The server only runs files whose extension maps to the script engine. A .bak file is treated as static content, so the raw source is sent to the requester.
Is a deny rule for .bak files enough?
It helps, but the real fix is to keep backups out of the webroot entirely, as MITRE recommends.