A Salesmans Code Execution: PrestaShop 1.7.2.4


PrestaShop is an open-source e-commerce solution. With more than 270,000 running instances it is one of the top 10 most used content management systems in the Web1. 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.

Our leading security analysis solution RIPS detected a highly critical PHP object injection vulnerability in PrestaShop that allows to execute arbitrary code on any installation with version <= 1.7.2.4. In this technical blog post we present the vulnerability and the exploitation technique that could have allowed attackers to compromise PrestaShop servers. This posed a serious risk for the PrestaShop Ready cloud. A fix was released and administrators of outdated PrestaShop installations are highly encouraged to update.

The Impact

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 default2. 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 security risk3. 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

3359336033613362336333643365336633673368
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

DateWhat
2018/02/09Provided vulnerability details and PoC to vendor
2018/02/13Vendor confirmed security issue
2018/02/26Vendor 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.

Tags: robin peraglie, php, Remote Code Execution, PHP Object Injection, unserialize,

Author: Robin Peraglie

Security Researcher

Robin is a passionate bug hunter and security researcher at RIPS Technologies. Since he was young he experimented with web security, cryptography and lockpicking. He received a degree in IT Security at the Ruhr-University Bochum and collected industrial experience in penetration tests and professional code audits.

Comments

comments powered by Disqus