Follow along in the discovery and exploitation of an authenticated remote code execution vulnerability in OctoberCMS
Hello again, it’s been a while since we’ve last had the pleasure of deep diving into open source projects and audit them for vulnerabilities. Prior to this one, we examined Plone, where we’ve discovered an authenticated RCE vulnerability, which was assigned CVE-2021-32633. You can find the write-up for it over here.
How it all started
Back in May 2021, previously published vulnerabilities for OctoberCMS sparked our interest and motiviated us to take a closer look at the project with the goal of finding security issues.
A series of security advisories (CVE-2020-15247, CVE-2020-262231), reported by ka1n4t, were our initial starting point. The advisories outlined that OctoberCMS may allow the execution of arbitrary PHP code by bypassing Twig’s sandbox and “Safe Mode” restriction:
A bypass of CVE-2020-15247 (fixed in 1.0.469 and 1.1.0) was discovered that has the same impact as CVE-2020-15247:
An authenticated backend user with the cms.manage_pages, cms.manage_layouts, or cms.manage_partials permissions who would normally not be permitted to provide PHP code to be executed by the CMS due to cms.enableSafeMode being enabled is able to write specific Twig code to escape the Twig sandbox and execute arbitrary PHP.
The advisory further mentions that…
This is not a problem for anyone that trusts their users with those permissions to normally write & manage PHP within the CMS by not having cms.enableSafeMode enabled, but would be a problem for anyone relying on cms.enableSafeMode to ensure that users with those permissions in production do not have access to write & execute arbitrary PHP.
In essence, users have the ability to edit template or page contents with access to a sandboxed Twig environment via the “Markup” tab in the page editor. The “Code” tab accepts executable PHP code, but is restricted by the Safe Mode configuration option:
The Attack Surface
Having these protection mechanisms in mind, we set out to analyze the restrictions put in place for an authenticated user with access to the “Markup” editor tab and “Safe Mode” enabled - the same exact attack scenario as in the above mentioned advisories.
Our main point of concern was the way the two vulnerabilities were resolved. The SecurityPolicy, which was introduced in the first patch in order to resolve CVE-2020-15247, and was later updated to fix CVE-2020-262231, raised our suspicions.
The SecurityPolicy implemented by OctoberCMS is based on a blocklist approach in order to restrict access to certain methods and properties in the sandboxed Twig environment. After CVE-2020-15247 and CVE-2020-262231 were resolved, the SecurityPolicy was updated, restricting access to seven methods:
Due to the small number of methods that have been restricted with this policy, we suspected that alternative ways of exploiting this attack scenario may exist.
Enter The Sandbox
We’ve started digging around the Twig context in order to discover what was
available to us in the restricted environment.
To make our lives easier, we’ve modified OctoberCMS to load Twig’s debug
extension (even when OctoberCMS is not running in debug mode) so we could use Twig’s
dump() without parameters dumps an array of available variables in Twig’s
which looked like so:
Iterating over the elements of
this and dumping them one at a time, revealed
a list of potential methods, which we could call in the restricted Twig
environment. Here’s a short excerpt of those classes:
- this.page: Cms\Classes\Page
- this.layout: Cms\Classes\Layout
- this.theme: Cms\Classes\Theme
- this.controller: CMS\Classes\Controller
We carefully analyzed most of these classes to determine if any of the exposed methods could be abused to achieve our goal of executing arbitrary code.
After digging through the
Theme classes, we’ve
discovered that the
Controller class exposes the
It returns a reference to the Twig\Environment,
which in turn exposes the registerUndefinedFilterCallback($callable)
method - a method you do not want to be accessible to untrusted users.
In order to verify the exploitability via
we’ve created a new page containing the following markup:
A malicious callback is registered via a call to
registerUndefinedFilterCallback() and then triggered via the call to
getFilter(). The call to
getFilter() attempts to lookup the undefined ‘id’
filter which in turn passes it to the undefined filter callback
The combination of these calls boils down to invoking
as can be verified by saving and then previewing the just created page:
Our suspicions were confirmed, the previous patches to prevent the execution of code by untrusted users via Twig were not sufficient. Arbitrary code execution was achieved by successfully bypassing Twig’s sandbox.
After reporting our finding to OctoberCMS a patch was pushed which would simply
restrict access to the
getTwig() method on
this.controller, as well as the
write method (yet another way of bypassing the sandbox).
The patch can be found here: 167b592
We were still not convinced that simply updating the blocklist (SecurityPolicy) with a new entry would prevent similar bypass attempts in the future, nor did we know for sure how these issues will be handled in newer versions of OctoberCMS.
This issue affected OctoberCMS prior to v1.0.473 and v1.1.6 and was assigned CVE-2021-32649.
- 2021-05: Vulnerability discovered and reported
- 2021-05: Vendor acknowledges vulnerability, CVE requested
- 2021-05-12: CVE-2021-32649 reserved
- 2021-05-29: Vendor releases patch
- 2022-01-14: CVE-2021-32649 published
- 2022-02-25: Write-up released