Zend Framework, used by developers to build object-oriented web applications, consists of PHP packages installed millions of times all over the globe. The framework along with Laminas Project is vulnerable to untrusted deserialization, leveraging attacker’s ability to exploit it to gain Remote Code Execution (RCE) on vulnerable PHP sites. Tracked as CVE-2021-3007 and rated high-risk, it can lead to remote code execution if the content is controllable, related to the __destruct method of the Zend\Http\Response\Stream class in Stream.php.
The actual vulnerability lies in the chain of classes of PHP language, rather than the framework. Insecure deserialization – when a website allows a user to introduce untrusted data, or perform an object injection, into a web app. The injected data can abuse the logic of an application and trigger a denial-of-service (DoS) attack or allow an attacker to execute arbitrary code as the data is deserialized.
The destructor of the Stream class which is a PHP magic method is the vulnerable component. To free up the memory and to destroy the new class object that has already served its purpose throughout the program, the PHP interpreter will call the object’s destructor. If the class of the serialized object implements any method named __wakeup() and __destruct(), the methods will be executed automatically when unserialize() is called on an object.
In the said vulnerability, the unlink() method called by Stream’s destructor for deleting a file expects a filename as a parameter, which is of the string data type. In effect, should the streamName object be of a non-string type, at the end of the application execution, it would still get passed to the destructor. The destructor, which only expects a string value would therefore attempt to call the object’s __toString method to get its string-equivalent value. But, the __toString method can be easily customized by the creator of the object, or rather the creator of the class that the object instantiates.
Image Source: Github
The __toString method in the Gravatar class of Zend Framework had been written by its programmers in a way that it eventually returned values leading it to arbitrary code execution. In a proof-of-concept (PoC) exploit, the researcher, Ling Yizhou demonstrated how the web app’s phpinfo page successfully parsed his system command “whoami” passed through a serialized HTTP request, and returned the Windows account name, “nt authority\system.”
Image Source: Ling Yizhou
The bug was publicly disclosed in the first week of January 2020 by Ling Yizhou, who also published two POC attack scenarios.
Affected Versions
Zend Framework version 3.0.0
Laminas Project laminas-http before 2.14.2
Solution
In January 2020, Zend Framework was migrated to Laminas project. Laminas Project has issued a minor security patch on GitHub. For more detailed mitigations, check for the Laminas Project page, also hosted on GitHub.
Qualys Detection
Qualys customers can scan their network with QID 374828 to detect vulnerable assets.
Please continue to follow Qualys Threat Protection for more coverage on latest vulnerabilities.
References and Sources
https://github.com/laminas/laminas-http/commits/2.15.x/src/Response/Stream.php
https://github.com/laminas/laminas-http/pull/48
https://www.php.net/manual/en/language.oop5.magic.php
https://github.com/laminas/laminas-http/blob/2.15.x/src/Response/Stream.php#L285