How I gained Remote Code Execution and what we can learn as software developers

    Article by  Stiig Gade on 07 June 2023

The following post is a fictional security review based on an aggregate of experiences regarding cyber security in software development and from conducting security reviews.

What is Remote Code Execution (RCE)? 

According to OWASP, RCE (or, in their terms, Code Injection) is the process of injecting code, which is then interpreted or executed by an application or system. Personally, I consider this the holy grail of vulnerabilities. If an attacker gains access to an RCE, they can quickly take over the system and gain a foothold/persistence, so they can easily access said system afterwards.

Why am I even hacking? 

Even though we are a software consultancy company, we also conduct security reviews. We truly believe that security is a fundamental cornerstone of software development, and not a feature which is implemented as an afterthought in the last sprint, because we have to”. By doing security reviews, we raise awareness of this fact both internally and externally, which improves the quality of our products, and helps clients reduce their attack surface. 

Gaining access 

I have been tasked with finding vulnerabilities within a system used to generate certificates. I start by powering up Burp Suite and browsing around the test-environment to get a feeling of the website. New users need to be approved by a moderator before gaining access to the system. Well, in production, at least, as it turns out that users get auto-approved in Test. This would be alright if the test environment were behind a VPN, but it’s open to the public. I have now gained access to the test environment; if I can, everyone else can too. This in itself may not seem too worrying, but let’s see where we can go from here.

Information exposure 

I am a normal user in this system, and the only thing I can do is print certificates from predefined templates. The endpoint is GET /certificate/render/1?name=Stiig, which renders said certificate with my name. Now for every endpoint I find, I poke at it with various variations of requests, such as POST/PUT and with all kinds of input. POST’ing to said endpoint returns 401 (Unauthorized), but because this is Test, I also get a message and stack trace:

Curl command in kali linux to POST a payload which should test for Server Side Template Injection in Razor, but the application denies this request with a stacktrace, because this is Test, disclosing useful information about user not having a Moderator object

Stacktrace which exposes inner workings of the application

From this, it doesn’t take long to extrapolate that the User-entity has a relationship to a Moderator-entity. Still, as I am not a moderator, it seems like I don’t have that entity.

Privilege escalation 

The system has an endpoint PUT /users, which is used to update my own information. It takes a User-entity that consists of NameEmail and Password. But what if I extend this information with ModeratorId? Often the first user created in a system is an admin-user; thus id 1 seems like a valid option: 

Curl command in kali linux which attempts to update the users information, and also includes an extra property, ModeratorId, which might cause privilege escalation on said user, as the user gains Moderator privileges

Unsanitized input causes the application accept unintended modification

It looks like it was a success. Now I have escalated my privileges so that I can modify templates. One step at a time, we breach further and further.
This could have been avoided by specifying an input-model which only had the desired properties, like this:

Example of a data transfer object in C#, which would have mitigated unintended modification of data, but not having a ModeratorId-property defined

Example of UserEditDto which would mitigate unintended data modification

Now deserialized input will not include ModeratorId, thus it isn’t possible to change. 

Server-Side Template Injection exploit

As mentioned, the system allows for creating templates if you have the proper privileges – which I do now. So let’s attempt to do this, but with special characters, to see if the website is vulnerable. The process of testing for which payload should be used can easily be automated with various tools, but as I know, this system runs .net, I might start with manually testing this with @-sign, which denotes expressions in Razor:

Curl command in kali linux, which attempts to test for Server Side Template Injection vulnerability in Razor, by sending data which Razor might execute: @(2+2)

Testing for Server Side Template Injection vulnerability


Now when rendering this template, we can see that the code is executed:
 

Curl command in kali linux, which executes a stored payload and verifies present Server Side Template Injection vulnerability

Verified SSTI vulnerability

The payload sent was @(2+2), which is interpreted by the Razor engine. 

Accessing the host 

Time to verify if we can access the host system, which can easily be done with a simple payload: 

C:/temp/test.txt”) which, if executed, would store a file in the temp folder on C-drive” width=”1500″ height=”365″ /> Using SSTI to gain access to RCE on the host system

If this payload gets interpreted, we will create a file on the host system. Let’s attempt to GET this template: 

Curl command in kali to execute the stored payload to attempt Remote Code Execution

Remote code execution using stored payload in SSTI

And the final check to see if the file was created: 

Curl command in kali linux to first store a payload which would list files in the temp-folder in C-drive using Server Side Template Injection, followed by a curl command which executes the payload. The response confirms that the earlier Remote Code Execution-attempt was in fact executed, as our file has appeared in C:/temp, amongst other temp files.

Confirmation of access to the underlying host system

As we have proof that we can start processes on the remote system, we have gained Remote Code Execution and thus can infiltrate the host machine. And we did it in three small steps. Each may have seemed innocuous, but together enabled the holy grail of vulnerabilities.

Escaping the containment 

When conducting security reviews, we must oblige to certain rules. These rules are both for the customers’ as well as our own protection so we don’t break something by mistake. In this case, I do not want to access other systems, but I want to verify if a potential attacker might be able to do this. For this purpose, I could list other IIS websites hosted by the machine. This gives the following output, which confirms that test and production are hosted on the same machine:

Curl command in kali linux to first store a payload which would exploit Server Side Template Injection vulnerability to list contents of the default folder, in which IIS stores websites, followed by execution of said payload. The response lists the Test-environment which we are attacking but also the same system with prod-suffix, which suggests that we have access to a production environment.

Confirmation of other systems present

Always separate different environments so that if an attacker should gain access, (s)he can’t access other systems. 

What is the takeaway?

The point of this post is not how to mitigate individual vulnerabilities, but that systems are often compromised because of multiple vulnerabilities used in conjunction with one another. Unfortunately, reports of vulnerabilities are often brushed aside with the argument that exploitation requires other dependencies (like elevated rights). But as we have seen here, many small vulnerabilities can be stitched together into a large breach.

I want developers to change their fundamental chain of thought during development. When you implement functionality which handles user interaction, like an API, think Evil. Think about how this could be exploited, and then consider how this can be mitigated. Every single mitigated vulnerability reduces the attack surface of the system itself and other internal and external systems.

Sikkerhedsreview

Læs mere om Commentors arbejde med sikkerhedsreview her.