Vulnerability Details
The Instance Metadata Service has two mitigations to help protect applications
that are vulnerable to SSRF. Namely, the Metadata-Flavor: Google
header is
required and requests with the X-Forwarded-For
header are ignored. The three
examples below describe methods for bypassing the first protection, which could
expose customers to risk in specific scenarios.
Use any of the following commands to demonstrate issues with the metadata service protections:
- Bypass the
Metadata-Flavor: Google
requirement by including an extra ‘/’ in the URL:
curl 'http://169.254.169.254/computeMetadata//v1/instance/name'
- Bypass the
Metadata-Flavor: Google
requirement by sending an HTTP/1.0 request, which (strangely) dumps all metadata content:
printf "GET / HTTP/1.0\r\n\r\n" | nc 169.254.169.254 80
- In some scenarios, an attacker may not fully control a URL. They can
use
;
in a URL to ignore all content following the semi-colon:
curl -H 'Metadata-Flavor: Google' 'http://169.254.169.254/computeMetadata/v1/instance/name;extra/content'
Attack Scenario
Actor: An attacker exploiting an SSRF vulnerability in an application running in GCP
Target: Service account credentials from metadata service
Outcome: Compromise of those credentials when the metadata service would normally protect them
During a recent penetration test for a client using GCP, we discovered a
specific SSRF vulnerability in that client’s application that allowed requests
to an arbitrary host with a partially controlled URL (e.g.
http://xxx:xx/xxx/yyy
, where x
is attacker-controlled and y
is
hardcoded). The URL http://169.254.169.254/computeMetadata//v1/instance/name;yyy
allowed bypassing both the Metadata-Flavor
requirement and, specific to our
client’s vuln, the hardcoded data at the end of the URL. This was due to the
way the Metadata Service handled both //
and ;
sequences in URLs (as shown
in #1 and #3 above).
During my research, I haven’t found a scenario where #2 would come up in
practice, but it is another example of bypassing the Metadata-Flavor
requirement.
Timeline
- 2019-06-14: Issue reported to Google VRP
- 2019-06-17: Issue triaged
- 2019-06-19: Internal bug report filed
- 2019-07-22: Issue fixed
- 2019-07-23: VRP issued reward ($5000)