Die siberas GmbH ein auf Sicherheitsanalysen und Penetrationstests spezialisiertes Beratungsunternehmen, welches Sie herstellerunabhängig und kompetent im Bereich IT-Sicherheit berät.
TYPO3 is an enterprise Open Source CMS based on PHP. While it might not be as well-known
as competitors like Joomla or Wordpress, it has quite a high market share here in Germany. During a recent penetration test I had to deal with an outdated Typo3 installation that was vulnerable to CVE-2016-5091. As details for this vulnerability were not publicly available, I thought I share my analysis.
Official advisory
On May 24, 2016, the TYPO3 security team released a security advisory for TYPO3 4.3.0-8.1.0. The fixed vulnerability was rated “critical” as it may allow an unauthenticated attacker to execute arbitrary code on the TYPO3 installation. The vulnerability (or variations of it) was discovered by Stefan Horlacher (Arcus Security GmbH), Alex Kellner and Oliver Hader.
Extbase request handling fails to implement a proper access check for requested
controller/ action combinations, which makes it possible for an attacker to execute
arbitrary Extbase actions by crafting a special request. To successfully exploit this
vulnerability, an attacker must have access to at least one Extbase plugin or module
action in a TYPO3 installation. The missing access check inevitably leads to information
disclosure or remote code execution, depending on the action that an attacker is able to
execute.”
Notes:
TYPO3 installations with at least one publicly available Extbase action, are
exploitable without any further authentication.
TYPO3 installations without publicly available Extbase actions, are still exploitable for
authenticated backend users with access to a backend module, which is based on Extbase.
Test environment
TYPO3 is Open Source, you can find all versions on their Sourceforge page. I recommend to install at least TYPO3 7.6.3 as this version is required for the “Introduction Package” which is available in the online repository. Setting up an entire TYPO3 installation from scratch can be painful, especially if you never worked with this CMS before. Therefore, using the Introduction Package is highly recommended.
Developer mode
The TYPO3 default settings disable detailed error messages. If full error messages/stack traces should be displayed, you must switch to developer mode. Developer mode is enabled through the environment variable “TYPO3_CONTEXT”. You can set this variable in the Apache configuration.
Extbase referrer fundamentals
By reading the public advisory and taking a look at the fix package, it is clear that the Extbase module actions are the root cause for the vulnerability. The Extbase framework adds several hidden fields to a generated HTML form. The update basically changes the way how these fields are generated and secured.
Hint:
The Introduction Package contains a page (/index.php?id=3) with a vulnerable Extbase form.
Here is an example HTML form that was generated by an Extbase module (before the patch):
In case of an error Extbase uses the __referrer fields to redirect the user to its originating request. The responsible code can be found in the errorAction method of the ActionController class (ActionController.php).
The description is quite self-explaining:
Here is the code of the forwardToReferringRequest method:
The referringRequest object is created by getReferringRequest(). This function uses the values from the hidden __referrer fields to populate the object. Note that while it checks the MAC value from the passed function arguments, the __referrer fields are used without any additional checks.
To make a long story short:
If we are able to cause an error in the form processing, the information in the (attacker controlled) __referrer fields are used to call a server side action method. Creating such a condition is easy, for example by providing no value for a required field.
We can verify this by intercepting a HTTP POST request that triggers an server side form validation error. For example, setting [__referrer][@controller] to “siberas” will cause an exception as we can see in developer mode.
Frontend vs. backend actions
Most Extbase action controllers contain code (actions) for the TYPO3 frontend and administration backend. This vulnerability makes it possible to call TYPO3 backend actions without authentication which can lead to various issues (see below).
Calling restrictions
Unfortunately, it is not possible to call completely arbitrary action-Functions as the following restrictions apply:
We can’t change the vendor
While the POST request contains a [__referrer][@vendor] field, it is not used by TYPO3 to forward the request I’m not sure if this is some sort of protection mechanism or if they just forgot to add the code. Once again, the call to the “forward” method:
So if you have an Extbase form from a 3rd party extension, it is not possible to directly invoke action-functions from the TYPO3 core as they have a different vendor. However, you can call actions of other extensions from the same vendor.
Naming restrictions
We are restricted to code that is implemented in a ActionController subclass. In fact we can only call “Action” methods as we must follow the Extbase naming conventions.
We can’t modify arguments
The arguments that are passed to the method call are protected by an HMAC. Therefore, it is not possible to change these values from the original request.
Arguments
The fact that we can’t modify arguments is not as restrictive as it might sound. Take a look at the following code:
If you execute this code on the command line, you get the following output:
The function is called, even if we provide a wrong number of arguments. Thus you can call action methods that don’t require arguments. In certain cases you might even be able to use functions with arguments as you can see in the remote code execution example below.
Practical examples
As pointed out in the original advisory the possible impact of this vulnerability depends on the methods that can be called by the attacker. Let’s see how this might be abused in a real world example.
Information disclosure (powermail)
Powermail is a mailform extension with a lots of useful features. It was downloaded over 157.000 times from the TYPO3 extension repository. Powermail is mainly used for things like contact forms, hence an Extbase form from this extension can be accessed without authentication.
The ModulController.php provides various export actions that allow an administrator to download the contact attempts via Excel or CSV. These actions don’t require any arguments:
We can exploit this by just changing the hidden fields in the request.
Remote code execution (TYPO3 core)
If the [__referrer][@vendor] field is set to “TYPO3/CMS” we are able to call methods from the TYPO3 core which has a large code base. From an attacker point, the most valuable action can be found in “typo3_src/typo3/sysext/extensionmanager/Classes/Controller/UploadExtensionFileController.php”. This action is responsible for uploading/installing a TYPO3 extension.
This method requires an boolean argument, however as we install our own malicious extension, we don’t really need to care if the value is true or false. The action takes the extension from the $_FILES array which is directly populated from our client request.
Vulnerability fix
The Typo3 security update changed several interals, resulting in an additional class file (typo3/sysext/extbase/Classes/Mvc/Web/ReferringRequest.php). Thus it is possible to verify if the patch was installed, just check the existance of that file. This even works if no Extbase form is accessible.
If the patch is installed, extabase forms include a hidden [__referrer][@request] field. This field contains a HMAC for the referrer fields to ensure that they can’t be modified by an attacker.
The HMAC is generated with an encryption key that is stored in “/typo3con/LocalConfiguration.php”. In consequence, a file disclosure vulnerability in the TYPO3 backend could be escalated to RCE. An attacker that has access to this file (or the key) could manipulate an existing extbase form and install a package by calling extractAction. This happenedbefore and might happen again.