Journey of a security bug — From a naive-looking PDF Download to SSRF via HTML Injection in AWS

Riddhi Shree
Appsecco
Published in
8 min readApr 8, 2020

--

I work as Security Analyst at Appsecco doing application security testing and pentesting mostly

Prelude

When I looked at the target application for the first time, it looked like any other web application. But, what looked like a single web application, initially, turned out to be a conglomerate of multiple web and mobile applications. No one knew what the boundaries were.

The first week of security testing went by in discovering authorisation flaws alone. Authorisation issues were all over the place. Exploitable XSS, SQL injection, or file upload vulnerabilities were nowhere to be found. File downloads, however, seemed interesting and we decided to pay special attention to this area.

At this instance, let me clarify that we are looking at two different applications side by side. While one application was accessible to administrators only (let’s call it admin portal), the other application (let’s call this user portal) was supposed to be accessed by lower privileged users mapped to different business roles.

The user portal allowed arbitrary users to register themselves into the target system. We found that user inputs were not being sanitised during the user registration process. All the user entered details were stored in a database and displayed to a privileged user in the admin portal.

  1. User portal allowed arbitrary user inputs to be entered only during the user registration process. Once an account was created, the user was not allowed to edit the basic user details.
  2. The admin portal, on the other hand, allowed privileged users to modify account details of any user. Once again, it was possible for an administrator to enter arbitrary data in input fields like, full name, address line, postal code, etc.

It was very clear that both, internal and external, types of attackers have the capability to pass unvalidated random text into the target system. What should be the next step?

Identifying the Vulnerable Entry Point

There were too many input fields and too many steps that had to be taken before a user account was created successfully. Input validation was missing from almost all of the entry points. It was important to find a place where data from at least one of the attacker-controlled entry points was being reflected as is.

It was a painstaking process, but we went ahead and started creating new low-privileged users, one after the other, with varying payloads. Jumping from user portal to admin portal and back to user portal, logging in and logging out of user accounts, analysing various screens to see if any of the inputs were reflecting as is… It was tiring and confusing, initially. We had to simplify this process somehow.

This is what we did.

We created a new user account with following payload being entered literally everywhere, with dropdown boxes and checkboxes being the only exceptions to the rule.

”><iframe src=“http://localhost/”></iframe>

The objective was to see if the <iframe> gets rendered anywhere across applications. At most of the places, it was observed that the arbitrary HTML code was reflecting as is. This meant that HTML output encoding was in place. Our attacks were being rendered useless. But we had to be patient. It wasn’t over, yet.

The “View Reports” feature that was generating an HTML preview of report, was reflecting our payload twice. This meant that inputs from two of the input fields under our control were being reflected here. We continued analysing the rest of the content in this HTML preview. We noticed a “Download” button.

Fig. 1 — The download button

On clicking the download button, a PDF file was generated and downloaded to our system. We opened the PDF file with an intention to see if the content was any different from the HTML preview. We did notice a difference. The <iframe> tags were missing in the downloaded PDF file.

Fig. 2 — Missing <iframe> tag in downloaded PDF

This was a ray of hope. Something was probably happening here.

We went back to the HTML preview screen and did a browser inspect on the two elements where attacker-controlled user inputs were being reflected. The class names of the two corresponding <div> elements helped us in narrowing down our scope.

Fig. 3— Inspect element

It was time to create a new user. A new user was created with attack payload accompanied by an identifying text for each of the address input fields. This time, the HTML preview in “View Reports” screen looked like this

Fig. 4 — HTML code reflected in statement preview

What we thought was a single address field, turned out to be a combination of two address fields. The reflected inputs were being fetched from “Residential Address Line” and “Residential Postal Code” address fields.

We had found the vulnerable entry points. It was time to play with the payloads.

The Payload

We tried several payloads, but the ones that returned the most interesting results were

”><iframe src=“http://169.254.169.254/latest/meta-data/iam/security-credentials/”></iframe>

and,

”><iframe src=“http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE-NAME”></iframe>

The first payload returned the AWS IAM role name, while the second payload returned the temporary AWS credentials for that IAM role.

Note: To understand these payloads in greater detail, read this interesting blog by Riyaz Walikar https://blog.appsecco.com/an-ssrf-privileged-aws-keys-and-the-capital-one-breach-4c3c2cded3af

Fig. 4 — Retrieved Security Credentials from Amazon EC2 Instance Metadata

Once the temporary AWS credentials were retrieved successfully, the enumerate-iam python script was used to list down the accessible AWS services.

Fig. 5 — List of accessible AWS services

What was the issue?

Server Side Request Forgery (SSRF) issue occurs when a user supplied input is used to make a server side network/HTTP request. If an application or a service, accepts a user controlled URL, IP address or hostname and fetches data from this, the application could potentially be vulnerable to SSRF. In the current example, our target application was vulnerable to Server Side Request Forgery (SSRF) attack via HTML injection in PDF download feature.

Even though the HTML preview itself was not vulnerable, the final PDF report was vulnerable. The necessary input validations were missing when API calls were being made to fetch content for the final PDF report.

Because an attacker was able to inject arbitrary HTML content successfully into the HTML preview screen, in addition to the standard API calls, the server also made a call to the endpoint specified in the src attribute of the injected<iframe> tag when the final PDF was generated. The raw response was retrieved and printed as is in the final PDF report, thereby leaking sensitive server-side details to the attacker.

What caused the issue?

  1. Server side user input validations were missing, allowing users to enter arbitrary HTML code in address fields.
  2. HTML output encoding was missed while generating the final PDF report. This resulted in user injected HTML code getting executed on the server.
  3. Raw server response was incorporated as is into the final PDF content, thereby, leaking sensitive server details to a potential attacker.

What could be the business impact?

Due to missing input validations a user can inject HTML code that becomes part of the “View Reports” screen. When user tries to download the report in a PDF format, the user injected HTML code gets executed on the server and the output is printed in the downloaded PDF file. By carefully crafting the attack payloads, a malicious user can read sensitive data from the target’s internal network which is possibly behind a firewall.

As the application is hosted on AWS, it is possible to use the vulnerability to access the AWS EC2 instance metadata endpoint, fetch temporary AWS credentials and use that to access other AWS services.

By modifying the attack payload various other server details could also be obtained. An attacker can potentially use a combination of payloads to obtain enough information, gain privileged access to the AWS account, and gain access to the entire AWS infrastructure from there.

Recommended Fix

  1. Server-side validations must be in place for all input fields. This will stop a user from passing arbitrary text to the server. Example, postal codes have an expected format and it should be easy to implement a server-side whitelist validation to check if the user entry looks like a valid postal code or not.
  2. Context-driven output encoding is a must to allow the server to distinguish between user input and actual code.
  3. Output of API calls must be validated before incorporating them in the PDF report, or anywhere else. This will ensure that any unnecessary data is not leaked to the application users.

Summary

This whole experience has been a milestone in my career as a pentester. Until sometime ago, I felt really confused whenever someone would talk about SSRF vulnerability. For me, I find it hard to grasp things until I see them working. After exploiting this interesting SSRF vulnerability in a live project, now, I do understand what SSRF really means.

The project was huge, and there was enough scope to get lost into the details. So, I took a call to get my findings reviewed by Riyaz at the end of each assessment day. Riyaz was supportive and equally excited about our daily discussions around various possibilities. At times I did test his patience, not deliberately of course, but he set a great example each time by being patient with me.

When I think back, I can clearly see that we are capable of achieving greater things when we work together compared to when we choose to work independently.

It was Riyaz’s experience and my enthusiasm, together, that led us to uncover this highly sensitive issue for one of our clients.

Hire Appsecco to pentest your AWS based Applications

At Appsecco we provide advice, testing and training around software, infra, web and mobile apps, especially that are cloud hosted. We also specialise in auditing AWS environments as per the AWS CIS Foundations Benchmark to create a picture of the current state of security in your AWS environment. Our experience has led us to creating multiple hands on training courses like the very popular “Breaking and Pwning Apps and Servers on AWS and Azure” and “Automated Defence using Cloud Services for AWS, Azure and GCP”.

Drop us an email, contact@appsecco.com if you would like us to assess the security of your AWS infrastructure or if you would like your security team trained in advanced pentesting techniques against AWS..

https://appsecco.com

--

--

Inquisitive by nature, I tend to drift towards things that are seemingly difficult, yet, interesting.