Exfiltrating AWS Credentials via PDF Rendering of Unsanitized Input

Cristi Vlad
4 min readMar 1, 2023

--

I know the title is a mouthful; submissions are open for better candidates. If you have one, suggest it below!

In a recent pentest I did for a client, the scope included a banking/financial application.

From the very start, mostly nothing worked from my side of the testing, but this is good because it means that the client has a solid app.

Testing for broken access controls and permissions was close to impossible. The session token had a TTL of 10 minutes, after which you’d be logged out, the app would hang for a few minutes (technical glitch presumably), then you’d have to login again with password and 2FA.

And after setting up two accounts for testing, which took 2–3 minutes, you’d have about 6–7 minutes of testing until being logged out again. Pain in the ass, I tell you. It got me very frustrated.

At one point, I was cataloging all the functionalities of the app when I saw a feature to download a void check. This was a feature that allowed you to preview a check with your details and the company’s logo/name.

Upon clicking the download button, it would take you to an API of the company, where your voided check was rendered. The URL looked something like this:

https://example.com/api/docs/check?name=MarcusAu&address=12 Main Street&checkNo=12&accNo=12&routing=12

This was a simple GET request, unauthenticated. Harmless, right?

So I thought too. These guys/gals have very hardened security for this app. They couldn’t fail to validate or properly sanitize all these URL parameters, right? Right?

But, let me just try and replace name=MarcusAu with name=<h1>this</h1>that.

No way! Ok, let’s try some XSS payloads! I don’t like XSS and aside from the generic XSS testing in my pentests for compliance purposes, I rarely go deeper.

And, for that matter, nothing worked here. When I would try to alert, prompt, or confirm something, the request would hang indefinitely. So, something was definitely happening in the backend. But me not being XSS astute…

Let me take a step back, instead of alert, prompt, or confirm, let me make sure the script tags can be used: <script>document.write(window.location)</script>

Now what? What would be the most impactful thing that I could try and gain from here? I tried a bunch of stuff from the browser’s API. It all worked (like getting some location information, stuff about the operating system, etc), but it didn’t seem too important.

Just to clarify, in pentesting you have to show the impact of your findings, but it’s not like in bug bounties, where unless you dump the entire database, it’s N/A, dupe, or informational. This is one of the reasons I rarely do bounties. I don’t even have the time for them, given the amount of pentesting work I get from clients.

With this vulnerability, I could have just specified the ability to inject HTML and suggest they should sanitize the parameter and move on. But I wanted to play more!

Then I remembered I read a write-up a while ago of someone getting metadata via XSS.

Let me take another step back here and say (as I keep saying on my YouTube channel and on Twitter) that one of the fastest ways to grow your skills in penetration testing is to read write-ups and (maybe, just maybe) participate in VDPs (not paid bounties). No CTFs, no hacking the boxes or similar platforms, but straight-forward, hands-on, real-world experience by reading what worked for others and by doing via VDPs. My $0.02, don’t take it personally.

And this proved to me (one more time) to be the right decision. After some back and forth, my final crafted payload was: <script>window.location=”http://169.254.169.254/latest/meta-data/iam/security-credentials/<hostname>"</script>

One of the lessons I learned from my pentesting experience and reconfirmed here was that I should never trust appearances. This app was rock solid when it comes to permissions, authorization, BAC, and overall input sanitization.

However, with an issue like this, it often is all in vain. You only need one malicious actor to get their hands on your secret keys to spell disaster.

I’ve got some other cool vulnerabilities I found recently and keep finding in my pentests and I might write about them if and when I have the time. Stay tuned here and on my Substack weekly blog.

--

--