SSRF to fetch AWS credentials with full access to multiple services

Zonduhackerone
4 min readFeb 27, 2021

This is a post about how I found a simple yet really critical vulnerability in a bug bounty program. It was the most critical bug I have ever found.

All started after I found a path in a subdomain that was almost a blank page with no functionality at all.

It had a few parameters that were all vulnerable to XSS so I reported the issue, it was triaged by Hackerone but at the end (yeah I have bad luck) it was closed as “internal dupe”.

The path was in https://host/payment/? so it was looking really promising that I was able to access this endpoint while being unauthenticated although the page was almost blank.

I didn’t give up and started fuzzing this endpoint as well as trying to find new ones to see if more unauthenticated stuff would show up. After some time I finally got something, a callback to our server.

After identifying the vulnerable parameter urlLogo (I changed the parameter name a bit because I have to redact everything), I started to think it would be a blind SSRF because the response of the url I was providing was not in the response.

Exploitation

After detecting the vulnerable parameter I started to test for SSRF as I usually do. Because I thought it was a Blind SSRF, I started to look into discrepancies in the response when providing a valid domain (zonduu.me) and when providing a host that doesn’t exist (asdqwd.asdq), providing port 80 and then 555, etc. to check if the server would timeout, give an error response or anything that we can certainly know when the server hit a valid host or not. The server was giving a timeout when providing a host like zonduu.me:555

I started burp suite pro, send a new tab to burp intruder and started fuzzing it with SSRF payloads I have gathered from public sources and personal experience.

When analyzing the responses from burp intruder I noticed that the responses were different from each other. There was a img tag with a base64 value, and when providing different urls, it would have different responses because the base64 value would store the responses of the requests we were making.

<img src="data:image/png;base64, base64encodedvalue.." onerror="path-to-same-blank-image" />

So I asked a friend I hacked a lot with in the past (neema) if he would give me a hand exploiting the issue as I previously validated it was probably a valid ssrf.

My mind was sure this endpoint would not fetch non-image endpoints so I didn’t decode the base64 value and started to think what default image to get in localhost so I could make a clear poc or to dig further into port enum, etc.

I took a break and started to play Warzone and in the middle of the game neema sent me a message telling me it was full read SSRF. The server was base64 encoding the response of the url we were providing in urlLogo parameter, no matter the content-type or anything and not only images (this is really unusual).

Awesome news since this was a full-read SSRF now.

we tried http://169.254.169.254/latest/meta-data/iam/security-credentials/rolehere

Decoded the base64 value and yes, there was the response with the AWS credentials:

{
"Code" : "Success",
"LastUpdated" : "2021-01-26T23:02:52Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "REDACTED",
"SecretAccessKey" : "REDACTED",
"Token" : "REDACTED==",
"Expiration" : "2021-01-27T05:06:28Z"
}

This endpoint allow us to generate temporary credentials to access aws resources, so then we exported the AWS keys:

export AWS_ACCESS_KEY_ID="REDACTED"
export AWS_SECRET_ACCESS_KEY="REDACTED"
export AWS_SESSION_TOKEN="REDACTED"

Tested them out and they were working!

The keys could have restricted privileges, minimizing the impact of the issue, so we checked to what we were having access, and we were surprised:

aws s3 ls

listed over 200 internal s3 buckets of the company.

aws ec2 describe-security-groups --region eu-west-2
aws ec2 describe-instances --region eu-west-2
aws ec2 describe-vpcs --region eu-west-2
aws ec2 describe-images --region eu-west-2

listed ec2 instances. The other commands were used to check if we had write access to ec2 instances without compromising the information inside the instances.

Overall the keys appear to have full privilege over the AWS services so the impact is just insane. Reading/deleting +200 buckets containing private information, messing up with the ec2 instances, creating and/or using other services, etc.

Without going further, I wrote the report and sent it.

It was then triaged as max impact possible and a few days later a bounty was rewarded:

I was expecting a massive bounty, bigger that the usual bounty for a critical vulnerability in this program (not sure why I was expecting that, probably because of the massive impact of the issue) but at the end it was rewarded max bounty + a bonus, still pretty good.

That’s all for the write-up. Follow me on twitter https://twitter.com/zonduu1 (not here) if you want to read my next write-up, because if I feel with time, I make the post directly at my site https://zonduu.me and not in medium.com, just doing it here because it is fast to do.

If you feel like buying me a coffee because whatever, you can do it here:

Hope you liked it, zonduu.

--

--