We had an interesting security report for our Oh Dear monitoring service. An attacker could load a specific URL and trigger a 404 page in which they controlled the output.
What content spoofing in a 404 page looks like
The URL looked like this.
https://ohdear.app/%2f%20This%20site%20is%20on%20maintenance%20Please%20visit%20www.devil.com%20because%20this%20site
If you decode that, you can see that the %2f
is a specially encoded path separator. The URL decoded version looks like this.
https://ohdear.app// This site is on maintenance Please visit www.devil.com because this site
You’d think Apache handles that OK by default, but it doesn’t. We have a custom 404 error page, but the URL above triggered this one.
What’s worrying here is that the attacker controls the text on the page, because the default 404 confirms the page URL right in the HTML body.
And since many browsers decide on hiding the URL in the address bar and just show the domain name instead, it isn’t immediately obvious the URL has been tampered with.
Preventing content spoofing in Apache’s 404 error page
Chances are, your website is vulnerable to this too. Copy/paste the URL above and see what kind of error page you get.
The fix is to apply a little-known Apache config called AllowEncodedSlashes and set it to AllowEncodedSlashes NoDecode
.
There appears to be a bug in Apache that requires you to set this in every VirtualHost because globally defined configs aren’t inherited to VirtualHosts.
In other words: copy this to every every VirtualHost you have.
<VirtualHost *:80>
[...]
AllowEncodedSlashes NoDecode
</VirtualHost>
After you add that config and reload the Apache daemon, you’ll be served either your custom 404 page (the one you were expecting) or a cleaned up 404 page of Apache.
It surprises me this is isn’t a default config in Apache though.