The Impact

With more than 270,000 running instances, PrestaShop it is one of the top 10 most used content management systems in the Web. Additionally to the classical software download, PrestaShop Ready offers to rent an online shop and to get administrative access to pre-hosted PrestaShop instances. From the perspective of attackers these e-commerce systems are very attractive targets because thousands of customers enter sensitive payment information.

The security bug is located in the orders section of the PrestaShops backend which requires access privileges for a Salesman, Logistician, or Admin account. For all of these three user roles the read permission to the orders section is enabled by default. This is the only requirement for an exploitation.

Matching this requirement an attacker can turn a PHP Object Injection vulnerability into a remote code execution vulnerability that allows to perform further attacks and to steal sensitive data. The attack is especially critical for PrestaShop Ready as an adversary can meet the requirement by setting up a free PrestaShop Ready trial account and potentially execute the exploit against the PrestaShop Ready cloud.

PrestaShop

The vulnerability was detected within 643,000 lines of code in only 8 minutes.

The Vulnerability

PrestaShop uses the PHP function unserialize() with user input which is a known bad practice and a security risk. This introduces PHP object injection vulnerabilities. But in order to prevent these issues, PrestaShop added a wrapper method unSerialize() to its code base that tries to prevent malicious injections.

classes/Tools.php

3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
public static function unSerialize($serialized, $object = false)
{
    if (is_string($serialized) && (strpos($serialized, 'O:') === false
	|| !preg_match('/(^|;|{|})O:[0-9]+:"/', $serialized)) && !$object
	|| $object) {
        return @unserialize($serialized);
    }

    return false;
}

Based on the second argument $object of this method, an additional security check is added (enabled per default). This additional security check considers any $serialized input as harmless if it does not match a specific pattern. The regular expression O:[0-9]+:" in line 3362 tries to detect if an attacker injected serialized objects which is a known exploitation technique.

However, this black-list security approach is insufficient since not all serialized object strings match this regular expression. Similar to Challenge 11 of our PHP Advent Calendar 2017, it is possible to bypass the validation check and to inject any serialized object. This can be achived by adding + characters to the length values of the serialized object string. These + characters will not break the unserialize() result but will bypass the matching pattern of the regular expression. The following table illustrates this effect:

Value of $serialized
Object string
Regular Expression
(Security Check)
O:8:"stdClass":0:{}
Matches
=> Payload filtered
O:+8:"stdClass":0:{}
Does NOT Match
=> Payload allowed!

As a result, an attacker can inject nested objects in their serialized format and obfuscate the true malicious nature from the regular expression. The then deserialized PHP objects can force PHP to execute code in specific magic methods. You can find out more about this attack technique in our previous blog posts.

The Payload

Finding a PHP object chain can be a tedious and time consuming process as the code base has to be searched for suitable classes which expose methods that can be used for exploitation. Often though, Composer is used to add many dependencies to the code base although only a small fraction of their code is actually used. In big applications like PrestaShop this results in a large attack surface for crafting a PHP object chain. Even better, RIPS is able to automatically scan the code base for possible exploit chains when a PHP object injection was found. It was possible to leverage parts of the Monolog library to craft a chain that in the end executes arbitrary code on the PrestaShop server. We refrain from releasing a working exploit at this moment.

Time Line

Date What
2018/02/09 Provided vulnerability details and PoC to vendor
2018/02/13 Vendor confirmed security issue
2018/02/26 Vendor released patch

Summary

In this post we analyzed a critical security vulnerability in the popular PrestaShop e-commerce solution. It could be exploited directly by setting up a free trial account of PrestaShop Ready or by malicious PrestaShop users with a Salesman role. Successful exploitation leads to the remote execution of arbitrary system commands and to the breach of sensitive payment information of customers. It is highly recommended to updated your shop installation. We would like to thank the PrestaShop team for the professional communication and the very fast release of a patch.