A Different Way to Attack Reverse Proxies

discodamone
3 min readAug 14, 2021

--

In this post I will discuss a web security edge case which may change the way you attack reverse proxies, specifically those that proxy requests to s3 buckets. This research was inspired by Frans Rosén’s blog post for Detectify. All of this information has been published for educational and ethical purposes.

Let’s say a website has the path /images-prod-abc/*, which, when requested, proxies the request to “hxxps://s3.amazonaws.com/images-prod-abc/*. This is a somewhat common situation, although less common now that the preferred format is hxxps://bucketname.s3.amazonaws.com/*.

The proxy mechanism does something similar to the following:

  • checks if the path begins with /images-prod-abc/
  • takes the path and appends it to hxxps://s3.amazonaws.com/
  • makes a request to that URL
  • returns the response to the user that originally requested /images-prod-abc/*

The problematic edge case involves an inconsistency between the check for if the path begins with /images-prod-abc/ and the appending of the path to the s3 bucket URL.

Specifically, the check for if the path began with /images-prod-abc/ was performed after shortening the URL. Likely, this happened due to the use of a library that automatically shortened URLs. Then, the unshortened path was appended to hxxps://s3.amazonaws.com/.

As an attacker, when thinking about a proxy mechanism that forwards the request to hxxp://s3.amazonaws.com/images-prod-abc/*, one goal is to be able to escape the images-prod-abc bucket to achieve XSS. By taking advantage of the inconsistency between the check performed on the path and the appending of the path to the s3 bucket URL, XSS is possible. The proof-of-concept is hxxps://example.com/attackerbucket/%2e%2e%2fimages-prod-abc/poc.html. Here is how it works:

  1. The web server receives a request for /attackerbucket/../images-prod-abc/poc.html. The request has been URL-decoded before parsing (which is also quite common). The reason the “../” had to be URL-encoded before sending the request is that browsers will automatically shorten URLs, and if hxxps://example.com/attackerbucket/../images-prod-abc/poc.html was visited by a user, the browser would shorten it to hxxps://example.com/images-prod-abc/poc.html before sending the request.
  2. The vulnerable code checks if the shortened path begins with /images-prod-abc/. This check passes because the shortened path is /images-prod-abc/poc.html.
  3. The vulnerable code appends the unshortened path to hxxps://s3.amazonaws.com/ to get hxxps://s3.amazonaws.com/attackerbucket/../images-prod-abc/poc.html
  4. You might wonder how AWS will treat the URL. To AWS, the requested object is named “../images-prod-abc/poc.html” and resides in the bucket “attackerbucket”

Now we have an html object being requested from the bucket named “attackerbucket”, but how can we serve an object with this name? Trying to upload using the s3 CLI does not work because the s3 CLI uses the URL hxxps://attackerbucket.s3.amazonaws.com/../images-prod-abc/poc.html, and gives a 400 error because many web servers validate the path to prevent traversing past the root. To work around this, we can use the following option in the s3 CLI:

--endpoint-url s3.amazonaws.com

This changes the URL requested by the CLI to be hxxps://s3.amazonaws.com/attackerbucket/../images-prod-abc/poc.html, and the upload works.

Now, visiting the original proof-of-concept URL achieves XSS in the meaningful context.

Also worth noting is that this vulnerability has been discovered in paths that are not the name of s3 buckets, for reasons unknown. For example, /images/ being proxied to hxxps://s3.amazonaws.com/images-prod-abc/ and /attackerbucket/%2e%2e%2fimages/ being proxied to hxxps://s3.amazonaws.com/attackerbucket/%2e%2e%2fimages-prod-abc/.

--

--