What is RCE?

RCE is a type of attack that enables an attacker to execute arbitrary commands on a target machine. These attacks are particularly critical because an attacker can gain total control of a victim’s machine, meaning an adversary can access, modify, and delete any and all sensitive data stored in a system.

I like to think of RCE not just as a bug but as an impact. Why? Because there are numerous ways—literally 1001—to achieve RCE. The initial foothold for an RCE attack can vary significantly, ranging from unrestricted file uploads and command injection to SQL injection, XML external entity (XXE) attacks, server-side template injection (SSTI), and, in some cases, even server-side request forgery (SSRF)!

 

My approach to RCE

I try to keep things pretty simple. The first thing I do is fingerprint the web technology or content management system (CMS) in use. A simple Google search of prior technology research will yield a list of any available exploits that may lead to RCE. However, if no public exploit is available, you may need to dig deeper. Sometimes, public exploits don’t exactly work flawlessly, and you have to find a workaround for that, but hey, that’s not a reason to give up!

And if it’s not a specific CMS in use, you can try to dive straight into an application and keenly observe how every functionality works to figure out potential entry points for code execution.

For example, figuring out a vulnerable version of an image-handling service like ImageMagick or Ghostscript could lead to RCE. Finding a little unescaped HTML that gets rendered into a PDF may also lead to RCE. There are so many ways to achieve RCE. Context is key, and understanding the web application you’re hacking plays a crucial role. I take note of every feature to construct a mind map of how user input is processed. Testing every potentially vulnerable endpoint or service is essential. Most importantly, trust your instincts.

 

How my method landed me a critical vulnerability

I was working on an Adobe Experience Manager (AEM) web app when I found a critical issue. AEM is a CMS used by many Fortune 500 companies.

Here’s how it went down:

AEM employs a GroovyConsole (similar to Jenkins) to run Groovy scripts for internal development operations. If left exposed to the public, the console allows script creation to manipulate content and execute arbitrary code—an instant jackpot!

If you see such a box in the wild, congrats, you’re in luck! Dig a little deeper and you’re likely close to an RCE exploit.

 

 

Bypassing the AEM Dispatcher

The GroovyConsole is typically accessible at:

https://site.com/etc/groovyconsole/jcr:content.html

However, on our target, accessing “/etc/groovyconsole/jcr:content.html” returned an error page. What now?

AEM employs a web application firewall (WAF)-like mechanism called the AEM Dispatcher, which uses allow/deny lists to restrict resource access. However, it can be bypassed.

Appending harmless extensions like .png, .css, or .gif to the resource path might bypass the restriction. 

 

We tried:

https://site.com/etc/groovyconsole/jcr:content.html/aa3.gif#

Voila! We are now able to access the GroovyConsole. Now, let’s try to run some basic commands.

 

Uh oh! Seems like we’ve been hit with an error here. Time to find the culprit!

 

 

Found it! So, the blocker appears whenever we input a command in the console; it sends a POST request, which doesn’t have the bypass appended (/aa3.gif).

Now, we can append it to the path and send the request containing a basic command!

 

 

Achieving RCE

Cool! But what now? Looking for public information on RCE via GroovyConsole, I stumbled upon similar scripts.

Here, we directly pass the system command to the execute function; in other words, def proc=’cat /etc/passwd’ .execute().

I copied the same script and tried reproducing the result on my target.

 

Unfortunately, the server blocked our attempts to directly invoke a system command. We even tried .execute(), but it was detected. Even ProcessBuilder was blocked.

Now, we needed a workaround or there would be no P1 payout for me. Fortunately, with the help of internet lords and ChatGPT, I was able to come up with the following script:

This script was quite harmless and wasn’t flagged by the server. Yet, my script demonstrated the capabilities of RCE by exfiltrating all environment variables using System.getenv().

And there go the environment variables.

 

 

But wait! It’s time to up the ante and go a step further.

Upon further exploration, we came up with this crafty code that discloses the contents of the home directory (here - /opt/cq/app).

 

The command output is similar to ls /opt/cq/app.

 

 

The final blow

By adding another line to the code, we were able to specify any directory and disclose all its contents (we were also able to identify whether it’s a file or a folder) and not just stay limited to /opt/cq/app.

 

But here comes the best part!! Taking it a step further, I was able to build this script that defines a list of sensitive files, and if this list exists, the script returns the whole output!

And voila!! Sweet, sweet RCE in the bag <3.

 

NOTE: I kept the PoC limited to reading files to avoid harming the prod instance. However, I could edit/delete files and folders as well.

Findings like these are bound to impress Program Teams, which is what happened in this case. See affirmations below:

 

Summary and takeaways

Server-side issues are always a fun topic to discuss. My writeup only details one of countless (remember, 1001) RCE possibilities. That being said, here are a few takeaways:

  1. Understand RCE as an impact, not just as a bug:
    • RCE can be achieved through numerous vectors such as unrestricted file uploads, command injection, XXE, SSTI, and SSRF.
    • The key is to find an entry point that allows you to acquire an initial foothold that may later lead to RCE.
  2. Understand the importance of enumeration:
    • Proper reconnaissance helps identify underlying technologies, CMS versions, and known exploits, if any.

 

  1. Think like an attacker:
    • Always approach an application with a curious mindset. Break down how a system processes user input and look for weak points in it.

As a closing note, I’d highly recommend checking out the following presentations. They expertly show innumerable ways to achieve RCE.

While Emil’s talk is tailored toward exploiting different kinds of image processors to achieve RCE, Laluka showcases a plethora of his findings that resulted in RCE and impactful bugs.

Both of their research is amazing and offer unique perspectives on RCE.