For a basic understanding of the serialize() function, let's take a look at the following PHP code snippet:
In the preceding code, we initialized an array named my_array with the following elements:
- my_array[0] = "Harpreet"
- my_array[1] = "Himanshu"
We then used the serialize() function to generate serialized data for the array. As you can see in the following screenshot, the serialized data stream is as follows:
The other PHP serialized formats that are commonly used are these:
- a: Array
- b: Boolean
- i: Integer
- d: Double
- O: Common object
- r: Object reference
- s: String
- C: Custom object
Metasploit also has a built-in exploit for this vulnerability. Taking a look at the source code of the exploit, we notice that it uses almost the same payload as that generated by PHPGCC:
The only difference is that the command and its length are set dynamically as per the input given by us via the exploit options.
As we can see in the following screenshot (where we are calling the __destruct() function), to perform function injection in call_user_func(), we have to control the _fn_close method so that dangerous functions, such as system(), passthru(), and eval(), are easily passed to call_user_func() as the first argument:
To control the _fn_close method, we have to look at the constructor ( __construct()):
As can be seen from the preceding screenshot, the $methods array is passed as an argument to the constructor. The __construct() function will create functions by looping through the $methods array and then prepending the _fn_ string. If the $methods array has a close string in it, the string will be prepended with _fn_, making the _fn_close method. Now, let's see the elements inside the $methods array:
From the preceding screenshot, it's clear that the $methods array has an element with the value close in it. Now that we know how to control the _fn_close method, next, we have to find a way to pass the dangerous function and the command to be executed to _fn_close. For this, we have to create a POP chain.