Skip to content

Instantly share code, notes, and snippets.

@Genzer
Last active January 13, 2025 10:04
Show Gist options
  • Save Genzer/0da834a8d7662f104b79eef3cf77ee79 to your computer and use it in GitHub Desktop.
Save Genzer/0da834a8d7662f104b79eef3cf77ee79 to your computer and use it in GitHub Desktop.

Mitigate "Rate Limiting bypass" through AWS ALB if the application relies on X-Forwarded-For

This gist documents a tactic which works in a situation:

  • Your Software System runs behind an AWS Application Load Balancer (ALB)
  • Your Software System uses AWS WAF in conjunction with ALB.
  • Your Software System handles Rate Limiting by itself.
  • Your Software System Rate Limiting implementation make use of X-Forwarded-For header to determine the correct Client Source IPO.

I discovered that by default AWS ALB 1 "Append" the X-Forwarded-For. That meant if a HTTP request contained an X-Forwarded-For header, ALB happily appended the actual Client IP Address to the existing value. This allowed attackers can bypass Rate Limiting just by randomizing values and spoofing the X-Forwarded-For header.

The mitigation for this, in this gist, is very simple: Use AWS WAF to block ALL requests containing proxy headers. In this gist, you can find the AWS WAR rule in JSON. The rule checks if there are any of the following headers avaiable in the request: Forwarded, X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Port and X-Forwarded-Proto, then AWS WAF blocks it.

{
"Name": "BlockAllRequestWithProxiedHeaders",
"Priority": 3,
"Action": {
"Block": {}
},
"VisibilityConfig": {
"SampledRequestsEnabled": true,
"CloudWatchMetricsEnabled": true,
"MetricName": "requests-from-internet-with-proxied-headers"
},
"Statement": {
"SizeConstraintStatement": {
"FieldToMatch": {
"Headers": {
"MatchScope": "KEY",
"MatchPattern": {
"IncludedHeaders": [
"Forwarded",
"X-Forwarded-For",
"X-Forwarded-Host",
"X-Forwarded-Port",
"X-Forwarded-Proto",
"X-Real-Ip"
]
},
"OversizeHandling": "MATCH"
}
},
"ComparisonOperator": "GT",
"Size": 0,
"TextTransformations": [
{
"Type": "NONE",
"Priority": 0
}
]
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment