During a recent application vulnerability assessment we found a Stored HTML Injection vulnerability that was quickly escalated to a full Server Side Request forgery (SSRF) on a AWS EC2.
We test a lot of applications hosted in AWS, especially on EC2. If you are new to this, we recommend reading couple of them before continuing.
Server Side Request Forgeries occur when an application accepts user input and performs a network operation based on the user input. This could be an HTTP request, a database connection operation, a SMB connect, a SSH connection or any other network request. As long as the user input determines where the server will make a request to, it is a Server Side Request Forgery (SSRF)
The exploitation of SSRF can lead to all sorts of interesting outcomes ranging from simple information disclosures, port scanning activity, full account compromises and in the case of cloud based services potential compromise of the cloud account itself.
During the security assessment of one of our client’s web application, hosted on AWS, my colleague Riddhi discovered what appeared to be an HTML Injection bug with the potential of escalating it to a Stored XSS. Based on the feature where this issue was found, she realised that there was potential for further exploitation. A stored XSS issue (bad) a SSRF (worse)
Detection for SSRF
The application used user information added during user registration on a formatted HTML page containing a report (sort of like a PDF preview but as HTML). This HTML page could be downloaded as a PDF document. The HTML to PDF conversion was happening on the server side.
The first sign that something was amiss with the feature was when our user’s address that we had provided as
<iframe src="https://appsecco.com"></iframe> was not sanitised in the HTML preview page, although it was sanitised everywhere else where the user’s address was displayed. Furthermore, generating the PDF caused the iframe to be rendered in the downloaded PDF as well.
Once we knew that the PDF render on the server was using the HTML page as source, we set about to identify if the iframe was actually a server side render or a client side call.
Identification to confirm SSRF
By using Burp Suite’s Collaborator feature we tried to identify if the server was indeed making a request on user’s behalf.
We created a new user in the application, added
<iframe src="http://BURP-COLLABORATOR-URL"></iframe> as the user’s address and attempted to preview the report in HTML.
However, when we started the PDF file download, we received a DNS and HTTP hit to our Burp Collaborator listener from the IP address of the web application server.
Once we had confirmed this was a SSRF via HTML Injection, we set about to exploit the issue and see what an attacker could extract given that the application was hosted on AWS.
Exploitation of SSRF to steal data from AWS account
On numerous occasions in our multiple client assessments, we have come across vulnerabilities on AWS hosted web applications that have allowed us, in some way or the other, to move outside the plane of the web application and actually interact with the AWS cloud infrastructure.
An SSRF on a AWS hosted web application, can potentially allow access to the AWS EC2 Instance Metadata service. This can be used to generate temporary tokens (if an IAM role is attached to the the EC2 instance) that would allow access to other services in AWS, based on the privileges the role has.
In this case as well, our payload of
<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/revealed an IAM role attached to the EC2 instance. Using the role name, it was possible to generate temporary tokens for the attached role as well using the payload
Once the temporary AWS credentials were retrieved successfully, we configured the aws cli using the
--profile option and attempted to identify who we were using
aws sts get-caller-identity --profile ssrftoken
We used the AWS credential permission enumeration script from https://github.com/andresriancho/enumerate-iam to see what access we had, and we were not disappointed.
We stopped our exploitation attempts here and reported the issue to the client along with the mitigations that would fix this issue. For additional post exploitation scenarios, check this post out —
The vulnerability existed because all places where the user provided data was being consumed were not output encoded as per context. The client added additional checks at these entry points to mitigate the vulnerability.
When attacking applications on the cloud, look out for features that accept user input and then use the user input in a different place. Depending on the context of data usage, you may be able to attack the user consuming the data (Stored XSS) or attack the server using payloads that have special meaning on the server based on the context (SSRF using server side HTML injection).
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, firstname.lastname@example.org 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..