Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 0.5.8

Bug #21165 PHP Object Injection Vulnerability through PHP Serializer
Submitted: 2017-01-19 02:39 UTC
From: egix Assigned: cweiske
Status: Closed Package: HTML_AJAX (version 0.5.7)
PHP Version: 5.6.29 OS:
Roadmaps: (Not assigned)    
Subscription  


 [2017-01-19 02:39 UTC] egix (Egidio Romano)
Description: ------------ When handling AJAX requests a "serializer" will be selected automatically relying on the Content-Type HTTP header (AJAX.php, lines 427-436): // auto-detect serializer to use from content-type $type = $this->unserializer; $key = array_search($this->_getClientPayloadContentType(), $this->contentTypeMap); if ($key) { $type = $key; } $unserializer = $this->_getSerializer($type); $args = $unserializer->unserialize($this->_getClientPayload(), $this- >_allowedClasses); When the header is set to "application/php-serialized", the HTML_AJAX_Serializer_PHP class will be used to deserialize user input coming from the AJAX request. Such a class will use the unserialize() PHP function with user-controlled input unless a class is found within the serialized string which is not in the provided array of allowed class names: function unserialize($input, $allowedClasses) { [...] $classes = $this->_getSerializedClassNames($input); if ($classes === false) { trigger_error('Invalidly serialized string'); return false; } $diff = array_diff($classes, $allowedClasses); if (!empty($diff)) { trigger_error('Class(es) not allowed to be serialized'); return false; } return unserialize($input); } By default the $allowedClasses array is empty, meaning that no classes are allowed to be unserialized. However, due to a faulty security check in the "_getSerializedClassNames()" method it might be possible to bypass such a restriction by replacing "O:X" with "O:+X" from within the serialized string, where X is the length of the class-name: function _getSerializedClassNames($string) { [...] // Pull out the class names preg_match_all('/O:[0-9]+:"(.*)"/U', $string, $matches); <=== faulty regex leading to a security bypass // Make sure names are unique (same object serialized twice) return array_unique($matches[1]); } This can be exploited to inject arbitrary PHP objects into the application scope, allowing an attacker to perform some attacks by using a "POP chain" or exploit memory corruption vulnerabilities within the internal implementation of the unserialize() function, which has a long history of security bugs (see e.g. CVE-2016-5771). More info: https://www.owasp.org/index.php/PHP_Object_Injection NOTE: I discovered this vulnerability in a PHP application which uses the HTML_AJAX Pear package for its AJAX server. They asked to get a CVE created for this issue, so that other developers using the package will be notified about the potential security risk. I'm not sure if MITRE will assign a CVE identifier for vulnerabilities in Pear packages, since they product list mention PHP but not Pear (https://cve.mitre.org/cve/data_sources_product_coverage.html). Could you please try to request a CVE for this vulnerability? Test script: --------------- HTTP request to reproduce the issue: POST /HTML_AJAX-0.5.7/examples/server.php?c=test&m=echo_string HTTP/1.1 Host: localhost X-Content-Type: application/php-serialized Content-Length: 20 Connection: close O:+8:"stdClass":0:{} Expected result: ---------------- {"errNo":1024,"errStr":"Class(es) not allowed to be serialized","errFile":"\/HTML_AJAX- 0.5.7\/HTML\/AJAX\/Serializer\/PHP.php","errLine":51} Actual result: -------------- {"errNo":4096,"errStr":"Object of class stdClass could not be converted to string","errFile":"\/HTML_AJAX- 0.5.7\/examples\/support\/test.class.php","errLine":20}

Comments

 [2017-01-26 00:03 UTC] egix (Egidio Romano)
-Status: Open +Status: Critical
I'm going to change the status to "Critical" because I think this poses a serious security risk for every application which uses the HTML_AJAX PEAR package. Last week the details of a type-confusion vulnerability in the GMP deserialization has been published on the Full Disclosure mailing list [1], and this can be exploited through the vulnerability I reported here, allowing a potential attacker to manipulate properties of already created objects within an application which uses HTML_AJAX to implement an AJAX server (which may result in catastrophic consequences). In addition to this recent PHP bug, a talk published on December 2014 [2] shows how it's possible to exploit unserialize() vulnerabilities in PEAR applications leveraging a magic method from the DB_common class, which allows to call arbitrary callbacks (in other words, Remote Code Execution). References: [1] http://seclists.org/fulldisclosure/2017/Jan/55 [2] https://hack4.org/2014/talks/exploit-alchemy/Exploit%20Alchemy.pdf
 [2017-02-02 14:09 UTC] egix (Egidio Romano)
FYI: the Common Vulnerabilities and Exposures project (cve.mitre.org) has assigned the name CVE-2017-5677 to this vulnerability.
 [2017-02-02 21:56 UTC] cweiske (Christian Weiske)
-Status: Critical +Status: Closed -Assigned To: +Assigned To: cweiske
Fixed in 0.5.8