The journey of Web Cache + Firewall Bypass to SSRF to AWS credentials compromise!

Hi Guys,
Back with an interesting hack that I was eagerly waiting to get the writeup to publish. This hack is about a chain of vulnerabilities which includes multiple bypasses in a various different layer which finally lead to access of AWS credentials in India’s biggest stock broker company. Below I’ll explain how I was able to access AWS credentials by first bypassing Web application firewall (WAF) and then leveraged it to SSRF via bypassing Web cache mechanism and finally gets hold of AWS account credentials.

(This was done with the explicit permission of the concerned company)

During the first phase of testing, I found an endpoint which was interacting with some file system so I went ahead to check for LFI (local file inclusion) vulnerability and found that application was behind the Cloudflare firewall —

Cloudflare WAF

Now to basically bypass the firewall, I had to directly send my request to the origin server hoping that they don’t have whitelisting of IPs request coming to their servers or load balancers —

Scenario of usual request call

In order to find the origin server IP, I simply ran “dig www.readacted.com” and I had the origin server IP —

Following article can help understand by digging the domain gave the origin server ip — https://support.cloudflare.com/hc/en-us/articles/115003687931-Warning-about-exposing-your-origin-IP-address-via-DNS-records

and then I simply made the entry in the host file and tried the LFI to read /etc/passwd and below is what I got as the response —

Sample Redacted Image

So, I managed to bypass the firewall and able to execute LFI vulnerability. When I searched the IP for the whois information, I found that the IP belongs to AWS. Now the next target was to read AWS account credentials by exploiting SSRF vulnerability which I was hoping it would definitely be there because of the designated functionality of the page/URL so without wasting any time, I proceeded to make the API call to read AWS instance metadata (http://169.254.169.254/latest/meta-data/ )—

HTTP Request to read AWS instance metadata
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 06 Apr 2019 14:32:48 GMT
Content-Type: text/css;charset=UTF-8
Connection: close
Vary: Accept-Encoding
Strict-Transport-Security: max-age=15552000
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Proxy-Cache: HIT
Content-Length: 0

But the response was empty with 200 OK response which meant that it surely interacted with the API and then returned the empty response. But why the response was empty? If you look at the above image, you will find the server header as a “Nginx” and response header “X-Proxy-Cache” which was set by Nginx cache layer whose value was set as “HIT” which meant that when the client tried to access the AWS metadata API, it first hit the Nginx cache layer and gave the response from the cache which was empty.

Now basically to get the response from the server, I had to bypass the cache layer for which firstly I needed to understand how URL caching paging rule are made in the nginx caching system.

Some references — https://www.digitalocean.com/community/tutorials/how-to-implement-browser-caching-with-nginx-s-header-module-on-centos-7
https://www.howtoforge.com/make-browsers-cache-static-files-on-nginx

What I understood is that general caching is done on the URL route path basis so if the URL is https://somewebsite.com/a.html and if it matches the route path (which it will because of caching rule) then it would hit the cache but if the URL is https://somewebsite.com/a.html? then the URL route path will not get matched with the caching rule hence it would miss the cache and get the response from the server. So I proceeded to make the call to read AWS instance metadata API ending with ? or any other special character, not matching the URL route path set in the caching rule(http://169.254.169.254/latest/meta-data?) and below is the response I got —

Web Cache Bypass HTTP Request to access AWS instance metadata
HTTP/1.1 200 OK
Server: nginx
Date: Fri, 06 Apr 2019 14:32:48 GMT
Content-Type: text/css;charset=UTF-8
Connection: close
Vary: Accept-Encoding
Strict-Transport-Security: max-age=15552000
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Proxy-Cache: MISS
Content-Length: 315
ami-id
ami-launch-index
ami-manifest-path
block-device-mapping/
events/
hostname
identity-credentials/
instance-action
instance-id
instance-type
local-hostname
local-ipv4
mac
metrics/
network/
placement/
product-codes
profile
public-hostname
public-ipv4
public-keys/
reservation-id
security-groups
services/

If you see the “X-Proxy-Cache” cache header value, it is now set to “MISS” which meant that now the API call doesn’t hit the caching layer and it fetches the response directly from the server.

So I was able to successfully bypass the caching layer to exploit SSRF. Now to read AWS account credentials, I had to make the call to AWS instance metadata security credentials API (http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance?) and as I expected, I was able to get hold of it —

I got the AWS access ID, secret Access key and the token and using which I was able to login into their AWS account and was able to access plenty of critical stuff. So having first bypassed the Cloudflare firewall, I exploited LFI then escalated it to SSRF by bypassing web cache mechanism and finally I got hold of AWS account credentials by exploiting SSRF vulnerability.

So, that’s it about this interesting finding!:)


Report details-

06-April-2019 — Bug reported to the concerned company.

07-April-2019 — Bug was marked fixed.

07-April-2019 — Re-tested and confirmed the fix.

09-April-2019 — Rewarded.

Thanks for reading!

~Logicbomb ( https://twitter.com/logicbomb_1 )