As web and other HTTP based applications become more complex, there is always going to be room for errors, especially since the large variety of systems that need to work together to function as a service are created, implemented, and maintained by very different people and teams. This allows for interesting quirks to come into play, notwithstanding your standard run of the mill web application security issues.
Most web application vulnerabilities are caused due to improper input validation. These are issues that result due to the application not parsing user supplied data contextually. HTTP desync attacks, which are a type of request smuggling attack, occur due to non-compliant HTTP request headers being parsed differently by different systems on their way to the target server.
HTTP desync attacks can lead to caching issues, access to sessions of other users, cache poisoning, arbitrary redirection etc. The attack usually results in a large set of the application’s user base to be affected.
In this Kloudle Academy article, we will do a quick review of what HTTP Desync attacks look like in the real world and how to configure AWS Load Balancers to resist these attacks and prevent them from being processed by proxies or app servers sitting behind the Load Balancers.
In its most basic form, HTTP desync attacks occur when a front-end proxy and the back end server understand and interpret a single HTTP request header differently. This causes both the front-end proxy (load balancer/reverse proxy) and the backend to become out of sync with each other, thereby allowing the attacker to modify the next request that arrives at the backend server.
Two HTTP request headers are commonly abused to do this: Content-Length (CL) and Transfer-Encoding (TE). Content-Length header is used to indicate the size of the request body in bytes denoted using a decimal number. The Transfer-Encoding header specifies the form of encoding used to transfer the payload.
The RFC specification 2616, states that “If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored”. This however is not implemented correctly across different types of proxies and app servers, especially when the headers themselves are malformed in the request. Various combinations of CL or TE header being parsed first leads to different attack scenarios, the most popular of which are:
A malicious HTTP request looks as follows
POST / HTTP/1.1
Host: example.com
Content-Length: 30
Connection: keep-alive
Transfer-Encoding: chunked
test
GET /admin HTTP/1.0
Bug: x
The CL header is parsed by the frontend reverse proxy (nginx for eg.) causing the entire request to be sent to the backend (gunicorn for eg.) which parses the TE header resulting in the GET /admin HTTP/1.0
to be processed as the beginning of the next request. When the attacker makes an actual HTTP request, it is appended to Bug: x
AWS, like most other major cloud providers, allows you to set up applications behind load balancers. The Application Load Balancer (ALB) and Classic Load Balancer (CLB) support mitigation modes for HTTP Desync attacks.
In an ideal world, to mitigate HTTP Desync attacks, you would need to only allow requests that conform to the standard RFC 7230 and 2616. However, real world web traffic contains mutations induced by browsers and middleware that results in non compliant headers. To counter this reality, AWS’s “Desync MItigation Mode” classifies every request reaching the ALB/CLB with a threat level using the AWS HTTP Desync Guardian library.
With Desync Mitigation Mode, customers can choose among three modes - “Defensive”, “Strictest”, and “Monitor”
To update the mitigation mode for an existing load balancer
Ensure your region is correctly selected
Navigate to the EC2 console at https://console.aws.amazon.com/ec2/v2/home
On the left navigation pane, under “Load Balancing”, choose “Load Balancers”
Select the load balancer from the list
On the “Description” tab, click on the “Configure desync mitigation mode” button under “Attributes”
The default “Defensive” is already chosen. However, if you wish to change the mitigation mode choose from “Strictest” or “Monitor” mode and click “Save”
aws elb describe-load-balancers --query "LoadBalancerDescriptions[].LoadBalancerName" --region us-east-1
elb.http.desyncmitigationmode
attribute set to monitor
, defensive
, or strictest
aws elb modify-load-balancer-attributes --load-balancer-name my-load-balancer --load-balancer-attributes file://attribute.json
Following is the content of attribute.json
{
"AdditionalAttributes": [
{
"Key": "elb.http.desyncmitigationmode",
"Value": "strictest"
}
]
}
HTTP Desync attacks are a novel way to perform HTTP request smuggling and like most systems that put usability ahead of security, affect chains of proxies and app servers. HTTP Desync attacks can be used to poison HTTP caches and cause information leak. Multiple publicly disclosed security issues have shown this which can lead to cross user session leakage and unauthorized access to restricted regions of web applications.
AWS provides a Desync Mitigation Mode that can be enabled to prevent attackers from exploiting this weakness in differential parsing of HTTP headers. The mitigation mode allows for completely disabling malicious requests, allowing trusted requests to pass through or simply monitoring traffic to understand the threat perception that your application faces from attackers. This feature is available free of charge for all load balancers within AWS for both the Classic Load Balancer (CLB) and Application Load Balancer (ALB) and can be configured by using either the console or the CLI.