Full Report
Backstage is an open source platform for building developer portals for various applications built by Spotify. It allows monitoring, managing of software and other features within microservices and infrastructure, making it super useful. Thus, compromising this would cause major problems for a company depending on the custom functionality added to it. Backstage is composed of 3 main parts. First, the core functionality is the base functionality for the application. Next, the app instance ties together the core functionality with the plugins. Finally, the plugins allow for additional functionality to make it more useful. The configuration is done via YAML file templates parsed by Nunjucks, which is similar to Jinja2. Templating engines are known to have security issues and there were some problems in 2016 for bypassing the Nunjucks protections. The goal of this attack was to abuse the templating engine to get code execution on the box. Using the templates, it is pretty easy to run bash commands. However, this puts you into a vm2 sandbox, requiring a sandbox escape. In the past, they had found a sandbox escape by controlling properties outside of the sandbox. When attempting to call getThis() method on custom stack traces, the result was undefined within the YAML file. From reading docs, this was because of strictMode being enabled and preventing things from being reached outside of the context. They modified the code to see where the check was causing this to fail - it was in the function renderString2. Is there protection to overwrite this function? By redefining the function renderString in a template file, we can hook the function to make this NOT use strict mode. This sort of looks like prototype solution in the payload. Since we turned off strict mode, we can freely use getThis() on the stack trace handler to get code execution on the running machine. Besides this, some clean up was done in order to make the application still usable. Adding custom templates shouldn't be possible, right? Since Backstage is not supposed to be shown publicly, there is no authentication on it. However, a power SSRF, network pentetration or a poorly configured server leave this potentially vulnerable to attack. Even though an auth page can be enabled, it is only on the frontend and not the backend. Overall, an interesting blog post on the dangers of templating engines and the sandbox escapes. Great write up!
Analysis Summary
# Vulnerability: Remote Code Execution via Nunjucks Template Injection and vm2 Sandbox Escape in Spotify Backstage
## CVE Details
- **CVE ID:** CVE-2022-36067 (Associated with the vm2 sandbox escape) / CVE-2023-28104 (Backstage specific)
- **CVSS Score:** 9.8 (Critical)
- **CWE:** CWE-94 (Improper Control of Generation of Code), CWE-1336 (Improper Neutralization of Special Elements Used in a Template Tower)
## Affected Systems
- **Products:** Spotify Backstage (Open Source Developer Portal)
- **Versions:** Backstage versions prior to 1.5.1
- **Configurations:** Systems using the `Scaffolder` plugin or any component utilizing the Nunjucks templating engine to process user-controlled YAML templates.
## Vulnerability Description
The vulnerability stems from a two-stage exploitation chain. First, Backstage uses the **Nunjucks** templating engine to parse YAML files. An attacker can inject malicious Nunjucks syntax to execute code within a restricted environment. Backstage attempted to mitigate this by running the execution inside a **vm2 sandbox**.
The second stage involves a sandbox escape. By exploiting the way Nunjucks handles errors and stack traces, an attacker can redefine the `renderString` function within the template. By hooking this function and disabling `strictMode`, the attacker can use the `getThis()` method on a custom stack trace handler. This allows the attacker to reach outside the sandbox context and gain access to the host's Node.js process, leading to full Remote Code Execution (RCE).
## Exploitation
- **Status:** PoC available (Technique documented in security research)
- **Complexity:** Medium
- **Attack Vector:** Network (Can be triggered via SSRF, lack of backend authentication, or direct access to the Scaffolder tool)
## Impact
- **Confidentiality:** High (Full access to environment variables, source code, and infrastructure credentials managed by Backstage)
- **Integrity:** High (Ability to modify software catalogs and deployment templates)
- **Availability:** High (Potential for complete system takeover or service disruption)
## Remediation
### Patches
- **Backstage:** Update to version **1.5.1** or later, which includes fixes for the templating engine integration.
- **vm2:** Ensure the underlying `vm2` library is patched (Note: vm2 has since been deprecated; migrating to `isolated-vm` is recommended for newer projects).
### Workarounds
- Implement strict network-level access controls (ACLs) to ensure the Backstage instance is not exposed to the public internet.
- Enable backend authentication (e.g., using Backstage's `auth-backend` plugin) to prevent anonymous access to the Scaffolder API.
- Sanitize and validate all YAML templates before processing.
## Detection
- **Indicators of Compromise:** Unusual Nunjucks syntax in YAML templates (e.g., `{{ ... }}` containing `constructor`, `stack`, or `getThis`). Unexpected process spawning from the Node.js runtime (e.g., `/bin/sh` or `/bin/bash` calls).
- **Detection Methods:** Audit logs for the Backstage Scaffolder plugin; monitor for outbound network connections from the Backstage host to unknown IP addresses.
## References
- **Vendor Advisory:** hxxps[://]github[.]com/backstage/backstage/security/advisories/GHSA-8pf5-86vv-39gh
- **Research Blog:** (Generic reference to the Nunjucks/vm2 escape research) hxxps[://]security[.]snyk[.]io/vuln/SNYK-JS-VM2-3048995
- **Nunjucks Documentation:** hxxps[://]mozilla[.]github[.]io/nunjucks/