As a precursory, I really don't like how this article is written. It takes more time to hype up the bug and the companies work than actually explain the vulnerability. Additionally, the vulnerability write up is all over the place and hard to fully grasp. Most of the time, I wouldn't write up an article like this but given that its an interesting JWT issue within AWS, I felt it was worth having around. Please don't write articles that are this vendor heavy, name the bug and/or over hype the issue; I just want to understand the vulnerability and move on with my day.
The Amazon Application Load Balancer (ALB) is used to distribute app traffic to various services on EC2, operating at Layer 7. AWS allows developers to configure the ALB to do the authentication for them through various different methods. For the application, it ends up verifying a JWT signed by AWS in some capacity. This was after a request was made to the SSO provider itself.
When looking at the example code for the JWT verification, they noticed that this was using a region specific JWT. Given that all apps built on the ALB would use the same signer, this was a little off-putting. A common JWT issue with SSO is not checking the aud field, which this did not have. According to the documentation, developers should verify the signer and iss (IdP URL) field within the JWT to determine if it's the proper application.
When submitting the JWT in the x-amzn-oidc-data header, the ALB simply removes and strips the header making this an unviable attack. They realized that direct requests to the server instead of going through the ALB were susceptible to this attack. All they had to do was get a JWT for an application in one region then use this JWT on a different application, using the ALB as a signing oracle.
The authors were curious if they could forge the issuer of the request in some way. Changing the issues in the OIDC configuration failed but they noticed an interesting quirk of how the system worked. There are multiple requests being made: one for the session between the ALB and the user and the headers derived from the session/configuration sent from the ALB to the application. Their goal was to desync the users session from the application receiving after the ALB.
The load balancer creates an encrypted cookie called the AWSELBAuthSessionCookie that corresponds to a particular user and app. If a cookie was gathered and the ALB configuration was changed, then the cookie expired, it would have to mint a new token. Crazily enough, the issuer was taken from the new configuration and not from the cookie itself. This allowed the, to forge the issuer, bypassing an existing protection of the JWT.
What are the full exploit steps? Assuming an application that was exposed to the internet and didn't check the signer fields, this is what you would do:
- Create an ALB with the target region with one IdP.
- Mint a token with the desired OIDC claims with our controlled IdP.
- Reconfigure the ALB to use the target applications issuer.
- Once the token expires (only a single minute), refresh it to get a JWT with the incorrect issuer.
- Send the token to the target application and circumvent the IdP.
- App validates the JWT and we're operating with a forged token.
Overall, a good find but way overhyped tbh. It's always fun to see the ol' switcheroo work on an application though. It's worth checking out these types of bugs even in modern apps!