CraftCMS Zero-day – SSTI + XSS triggering RCE (Proof of Concept)

Published on 2021-07-29
This article is a continuation of CraftCMS Zero-day – SSTI + XSS triggering RCE.


The vulnerability is exploited via XSS. Note that any XSS on the website (even outside of the craftCMS installation itself, as long as it's triggering within same origin, can lead to the RCE being triggered. The CraftCMS have very little functionality in fresh installation. All the features and functionalities are developed by the developer using twig templates and plugins. For the demonstration purpose, we will use Guest Entries plugin and write own templates to build a demo site having an upload functionality.

  1. First, install the Guest Entries plugin.
  2. Now copy the following templates to your templates directory in CraftCMS installation.

After uploading these, you can point routes to these two templates and our demo site is ready.

Crafting the exploit

The exploitation starts with uploading the XSS payload that takes the following steps to upload a twig template via XSS triggered by an admin. Note that all these must be done by XSS payload script on behalf of an admin. It is not possible to exploit some functionalities as a regular user.

  1. Creates a volume that points to @config/../templates
  2. Uploads a malicious twig template within this newly created volume.
  3. Creates a route to the uploaded twig template.
  4. Invalidates cache.

Creating a Volume

CraftCMS uses a concept of volumes as its storage unit. A volume can point to a local directory or some out of sphere storage like S3 buckets. To ensure that we can execute code, we create our own volume. We point volume to @config/../templates because @config is an alias that points to config directory that sits outside the publicly accessible directory. We walk the path by appending /../templates to the alias @config and reach the templates directory. When I was testing, I thought it would be easier to upload to vendor directory and execute code. But sometimes, vendor's directory does not have write permissions on and we cannot upload PHP files directly.

Uploading Malicious Twig Template to gain SSTI and Code Execution

Uploading a twig or php file is not possible due to security measures in the upload feature of CraftCMS. So we upload files with other file extensions like SVG. There is some SVG sanitization but the code within curly braces survives the SVG/XML Sanitization. Within the malicious twig template, we can use twig templates filters to escape the sand box and gain code execution.

Creating a Route to our Payload

After uploading the twig template, we can point a route to our twig template that resides within the templates directory easily. The twig template does not cares about the file extension and happily load the content from our malicious twig template. The shell now lives at the route you created (In the following PoC, run commands via cmd query parameter ie. Allowing you to run any PHP code or system commands.

Invalidate Cache

As a last step, invalidating cache helps in regenerating the twig template's cache. A backdoor route is obviously very shouting and should be removed. As a post exploitation process, you can clear all the footprints and maintain access by replacing some internal files of CraftCMS or going deep inside the OS.


The following exploit is a quick script that I wrote to report the vulnerability to the developers and it was patched in the newer version of CraftCMS.

Proof of Concept: