Affected are TYPO3 8.x through 8.7.26, and TYPO3 9.x through 9.5.7. A deserialization of untrusted data leads to a Remote Code Execution vulnerability, which can be combined with a Cross-Site Scripting vulnerability that was also detected in the backend (CVE-2019-12748).

The truncated analysis results are available in our RIPS demo application. Please note that we limited the results to the issues described in this post in order to ensure a fix is available.

Overriding the Database with a Payload

The vulnerability occurs when saving any form in the backend section of TYPO3. If a user modifies the pages section for example, the data to be edited is fetched from the SQL database of TYPO3 and written back to the database. After fetching the data from the database, the application logic allows overriding single columns of the fetched data with user input. This feature allows a malicious authenticated backend user to override database values containing serialized data which are later deserialized. This leads to a PHP Object Injection that alows an attacker to remotely execute code (CVE-2019-12747).

Technical Details

When saving a backend form in TYPO3, the compile() method of the $formDataCompiler object is called. The argument is an array which is populated with user input, as seen in line 1263 of the following listing.

typo3/sysext/backend/Classes/Controller/EditDocumentController.php

1258
1259
1260
1261
1262
1263
<?php
  $this->overrideVals = $parsedBody['overrideVals'] ?? 
    $queryParams['overrideVals'] ?? null;
  // ... 
  $formDataCompilerInput['overrideValues'] = $this->overrideVals[$table];
  $formData = $formDataCompiler->compile($formDataCompilerInput);

The method makes use of a for-loop iterating over an ordered list of FormDataProvider objects and invokes the addData() method on each $provider object in sequence.

typo3/sysext/backend/Classes/Form/FormDataGroup/OrderedProviderList.php

58
59
60
61
62
63
64
65
66
67
<?php
public function compile(array $result): array
{
  // ...
  foreach ($orderedDataProvider as $providerClassName => $providerConfig) {
    // ...
    $result = $provider->addData($result);
  }
  return $result;
}

As you can see in the source code listing on line 64, the $result of the previous $provider->addData() invocation is used as an argument in the next addData()-call. On each iteration, the $result variable which represents an array is modified after the $provider has processed its contents. One of those providers is an instance of the DatabaseRecordOverrideValues class which allows to override the data fetched from the database stored under the databaseRow-key of the $result array.

typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseRecordOverrideValues.php

30
31
32
33
34
35
36
37
38
39
40
<?php
public function addData(array $result)
{
    foreach ($result['overrideValues'] as $fieldName => $fieldValue) {
        if (isset($result['processedTca']['columns'][$fieldName])) {
            $result['databaseRow'][$fieldName] = $fieldValue;
            // ...
        }
    }
    return $result;
}

Finally, one of the following FormDataProvider objects implements an unserialize() call on the overridden data, leading to the vulnerability:

typo3/sysext/backend/Classes/Form/FormDataProvider/DatabaseLanguageRows.php

61
62
63
64
65
66
67
68
69
<?php
public function addData(array $result)
{
  // ...
  if (/*...*/) 
  {
    $result['defaultLanguageDiffRow'][$defaultLanguageKey] = unserialize(
        $result['databaseRow'][$result['processedTca']['ctrl']
        ['transOrigDiffSourceField']]);

You can find more information on how to exploit PHP Object Injections with gadget chains in our blogpost.

Stored Cross-Site Scripting in Backend

A Cross-Site Scripting vulnerability exists in the TYPO3 backend (CVE-2019-12748). An unprivileged user who has access to the Site Redirects section can inject a malicious URL which makes use of the t3:// pseudo protocol.

t3://url/?url=javascript:alert(1);

By adding this specific site redirect another benign higher-privileged TYPO3 user can be tricked into clicking the link which triggers the malicious JavaScript. He could use this vulnerability as a pivot point to launch the remote code execution exploit from above.

TYPO3 prevents a user to make use of the dangerous javascript: pseudo protocol in links and URLs provided by the user which would mean the direct execution of JavaScript. However, it does not prevent a user to make use of TYPO3’s builtin t3:// pseudo protocol which implements multiple functionalities like referencing TYPO3 internal pages, files, email addresses or URLs. In fact, specifying a URL which is automatically translated into a clickable link bypasses the whitelist of TYPO3 which initially prevented the javascript: pseudo-protocol.

Summary

The presented vulnerabilities can have critical impact on any TYPO3 system with one or more TYPO3 backend users. An authenticated backend user with access to the Pages section can execute code on the underlying remote system. He could use the Cross-Site Scripting vulnerability in the Site Redirects module as a pivoting point to exploit this vulnerability. The vulnerability was detected with an automated security scan of RIPS which found the vulnerabilities within a total scan time of 2 minutes and 9 seconds.

Timetable

DateEvent
09 May 2019Sent vendor vulnerability details
09 May 2019Vendor acknowledged
10 May 2019Coordination with security lead of vendor on fixing the issue
06 June 2019Vendor informs us about detailed release plans 25 June 2019
25 June 2019TYPO3 9.5.8 patch released