Penetration testing has suggested our web app is vulnerable to server-side request forgery. The supposed proof is that when making a request with a fake Host header (example: fakehost.com
) to our web app, we see incoming HTTP requests in fakehost.com
logs. (fakehost.com
could be controlled by an attacker) The behaviour happens once but then can't be reproduced for a given host.
curl -i -s -k -X $'GET' \
-H $'Host: fakehost.com' -H $'Accept-Encoding: gzip, deflate' -H $'Accept: */*' -H $'Accept-Language: en' -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36' -H $'Connection: close' \
$'https://subdomain.django_web_app.com/example'
Sending the above request once to our web app has generated six incoming requests on fakehost.com
, two without a path and four with the path from the request. The requests come from three different IP addresses, two are from the country where the web app is hosted and one is from the country where I am -- can't recognise any of these IP addresses, they are not my own IP address or our servers and they are not in Amazon AWS IP ranges. (The web app is behind an Amazon AWS load balancer.)
Are these requests made by the network along the way? Is this normal behaviour?
Yes, in fact it is so common to have such requests forwarded to your application that Django documentation devotes a paragraph just to discussing how to address common seemingly-secure configurations, explicitly warning
The simplest most obvious such case is the attacker entirely bypassing your load balancer when your application backend is accessible without going through your proxy.
In any case, because it is so notoriously hard to get right on the proxy, it may be entirely acceptable to just point out that the access log not just logs these requests, but also logs that they have been correctly rejected with a
400
HTTP status code.Remember your application is not vulnerable to that class of spoofing attacks just because it receives these requests. What would make it vulnerable would be acting on them in any fashion that might reveal or change state. Your application should be correctly configured to validate the header and respond
HTTP 400
accordingly if receiving requests with unexpected hosts.