In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-03 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >
Share
Shulou(Shulou.com)05/31 Report--
This article introduces what are the PHP deserialization vulnerabilities that often occur in CTF, the content is very detailed, interested friends can refer to, hope to be helpful to you.
0x01 what is PHP serialization and deserialization
PHP serialization is a method of converting variables or objects into strings for easy storage and transmission.
In PHP, serialization is used to store or pass the value of PHP without losing its type and structure.
For example, I now have a class that I need to transfer data through the interface or store it in the database for future use, while maintaining its structure so that the receiver receives or the database reads the data to restore its original structure. It needs to be serialized to convert the object into a string in a certain format.
Simply put, the data is stored in a string, including its data type and structure information.
Serialization function:
Serialize (object)
PHP deserialization is the escape of serialized object strings into concrete objects.
Deserialization function:
Unserialize (object)
Take a simple example:
Where O represents the object object type
4 is the length of the class name
"user" is the class name
1 is the number of attributes in the object
SRV 8: "username" indicates that the attribute is in string format username and the length of the attribute name is 8
SRV 3: "Bob" is the value of the attribute
There are three common types of attributes in php: public protected private
The variables modified by these three types have different formats after serialization.
Public normal serialization
Protected* variable name
Private variable name
Pay attention to manual input when copying payload
Magic methods related to 0x02 and PHP deserialization
What is magic? That's what the official document says.
_ _ construct (), _ _ destruct (), _ _ call (), _ _ callStatic (), _ _ get (), _ _ set (), _ _ isset (), _ _ unset (), _ _ sleep (), _ _ wakeup (), _ _ serialize (), _ _ unserialize (), _ _ toString (), _ _ invoke (), _ _ set_state () Methods such as _ _ clone () and _ _ debugInfo () are called magic methods (Magic methods) in PHP. You cannot use these method names when naming your own class methods unless you want to use their magic capabilities.
Note: all magic methods must be declared public
Warning: PHP keeps all class methods that start with _ _ (two underscores) as magic methods. Therefore, when defining class methods, in addition to the above magic methods, it is not recommended to prefix them with _ _.
These magic methods are often used in the use of php deserialization
_ _ construct () / called _ _ destruct () when an object is created / / called _ _ toString () when an object is destroyed / / use _ _ sleep () when an object is treated as a string / / run _ _ wakeup () before the object is serialized / / called _ _ call () after the object is deserialized / / when the method to be called does not exist or Automatically call _ _ get () / / when private attributes need to be called when permissions are insufficient
These methods are called during object generation, parsing, serialization, deserialization, and invocation. If the attributes can be used externally, it is quite dangerous.
The specific understanding of these magic methods is attached at the end of the article.
0x03PHP deserialization vulnerability
PHP deserialization vulnerability, also known as PHP object injection, is mainly caused by dangerous code execution caused by improper handling of deserialized data.
Give me a simple example.
[NPUCTF2020] ReadlezPHP
In the above example, there is a score class that accepts the GET parameter s.
Let's assume that the s parameter in this example accepts a serialized score object, and no matter what value we assign to the property name, the result will be changed to Bob by the _ _ wakeup function.
But if we can bypass the _ _ wakeup function, we can change the name property to any value we want.
The parameter s we passed just now is
Orlando 5: "score": 2: {SRAR4: "name"; SRAR4: "john"; SRAR5: "score"; SRAR4: "1000";}
Change it to:
Orlando 5: "score": 1: {SRAR4: "name"; SRAR4: "john"; SRAR5: "score"; SRAR4: "1000";}
The content of the control output can be realized, thus bypassing the _ _ wakeup function
0x05 function of the same name uses
Look at the following example:
After visiting the page
Session is stored under session.save_path, the file name is sess_+session_id, and the content of the file is session data
This is the session value of session.serialize_handler=php mode
This is the session value of session.serialize_handler=php_binary mode
This is the session value of session.serialize_handler=php_serialize mode
The vulnerability caused by Php session deserialization lies in the different session processor settings (session.serialize_handler) in the same service.
Understand through the following examples:
In the test1.php page, there is a dangerous class A that serializes the processor as php
The parameters passed by the user are accepted in session.php and stored in session, and the serialization processor is php_serialize.
Let's first take a look at the generated payload:
| payload: "A": 1: {payload 1: "a"; 10: "phpinfo ();";}
We use this as a reference to pass in session.PHP
Because the serialization processor of session.php is php_serialize, the serialization data stored in the file forms the content shown above, and when read by test1.php using the deserialization processor php, the content before the vertical bar of the different reading format will be read as a key value, and the later content will be deserialized as serialization data:
So the session value that is deserialized when accessing the test1.php page produces an object of dangerous class An and executes the dangerous code:
The basic idea of string Escape in 0x07 php deserialization
After understanding php deserialization, you can see that string escapes are essentially closed, similar to closing statements with semicolons or quotation marks in sql injection. Deserialization string escape also makes use of php's feature of serialized string parsing to attack.
When deserializing, the serialized values are separated by semicolons and end with}. Let's look at an example:
Running result:
Orlando 6: "people": 3: {people 4: "name"; SRAV 3: "Tom"; SRAV 3: "sex"; SRAV 3: "boy"; SPLR 3: "age"; Srig 2: "12";}
The process of deserialization is to match and stop parsing when you encounter the closest;}. We add some meaningless strings to the end of the deserialization result above and deserialize it.
Orlando 6: "people": 3: {people 4: "name"; SRAV 3: "Tom"; SRAV 3: "sex"; SRAV 3: "boy"; SPLR 3: "age"; Srig 2: "12";} 123123
After deserialization:
You can see that the 123123 we added at the end does not affect deserialization, and the program does not report an error in the parsing result and there is no problem. This shows that the above principle is correct.
But when I change the numeric value of the length of the string, let's see if deserialization can be parsed properly. For example, I changed sposition 2: "12" to slug 3: "12":
Orlando 6: "people": 3: {people 4: "name"; SRAV 3: "Tom"; SRAV 3: "sex"; SRAV 3: "boy"; SPLR 3: "age"; Srig 3: "12";}
Php error:
PHP Notice: unserialize (): Error at offset 75 of 77 bytes in / Users/oriole/WorkSpace/www/html/index.php on line 16
In fact, in the process of parsing a string, php will report an error when the string length is different from the deserialization description, to put it another way: php will read the string according to the length defined by the deserialized string, and an error will occur when the string with the defined length within the quotation marks is not read to the characters before the last quotation marks, or when it is read beyond the last quotation marks.
Because of this error report, there are two types of string escapes:
1. Keyword increase
two。 Keyword reduction
Keyword increase
In the title, some keywords are often filtered, and the means used usually replace keywords to increase the number of keywords, so as to have a simple understanding and serialize the results normally.
Output:
SARV 2: {username 8: "username"; SARV 3: "Tom"; SARV 3: "age"; SARV 2: "13";} aRV 2: {SRAV 8: "username"; SARV 3: "Toom"; SRAV 3: "age"; SRAV 2: "13";} PHP Notice: unserialize (): Error at offset 28 of 51 bytes in / Users/oriole/WorkSpace/www/html/index.php on line 11
In the above code, all o in the undeserialized serialized string will be replaced with oo, which must break the original rules of serialized string, so it will inevitably cause an error, and our purpose is to construct the string so that it does not cause an error. To make it easier to understand, we add a requirement: the age field is modified to 35.
Payload:
SARV 2: {username 8: "username"; SER 44: "oooooooooooooooooooooo"; SARV 3: "age"; SARV 2: "35";} "; SARV 3:" age "; SPLR 2:" 13 ";}
Principle: after preg_replace, each o will be replaced with oo. For example, when we pass in SRV 3: "Tom", it will be replaced with SVR 3: "Toom", which is bound to report an error. What we need to do is to make the string really as long as it describes when it grows, and to achieve our goal of changing the age field to 35.
The way to achieve this is to * * include the deserialization structure in this string, and when the string is replaced, its length is equal to the length of the string that originally contains the deserialization structure, so that it can be parsed normally as a string, while the deserialization structure contained in the string is recognized by php as a deserialization structure for parsing, while redundant deserialization structure (that is, complete { (other than the structure) is abandoned. * * it may seem hard to understand at first glance, but you can choose to take a closer look at the basic idea or continue to look down at every process of constructing a payload.
We also take the above code as an example, we need to construct a deserialization structure in the string while closing the front string after replacement: "; SRAV 3:" age "; SRAR 2:" 35 ";}, and the length of this deserialization structure is 22:
In other words, we need 22 characters to replace its position, and each o will be replaced by oo, that is, an additional character, which means we need 22 o to increase the length of 22 characters.
So we combine the 22-character length of oooooooooooooooooooooo with "; Susername 3:" age "; SARV 2:" 35 ";} to form the value of the username variable, and we serialize it to get:
SARV 2: {username 8: "username"; SER 44: "oooooooooooooooooooooo"; SARV 3: "age"; SARV 2: "35";} "; SARV 3:" age "; SPLR 2:" 13 ";}
After being replaced by preg_replace, an oooooooooooooooooooooo of length 22 becomes an oooooooooooooooooooooooooooooooooooooooooooo of length 44, and the entire deserialized payload becomes:
SARV 2: {username 8: "username"; SER 44: "oooooooooooooooooooooooooooooooooooooooooooo"; SARV 3: "age"; SARV 2: "35";} "; SARV 3:" age "; SPLR 2:" 13 ";}
When PHP deserializes the payload, SRV 8: "username"; SLAR 44: "oooooooooooooooooooooooooooooooooooooooooooo"; will be parsed as a whole, and "; SRAR 3:" age "; SRAR 2:" 35 ";} after the preceding variable is closed by quotation marks and semicolons:" age "; SSR 2:" 35 ";} will also be parsed normally. And because it has satisfied the complete {;} structure "; SRAR3:" age "; SRAR2:" 13 ";} will be abandoned and not parsed.
So you can see the following deserialization result:
Array ([username] = > oooooooooooooooooooooooooooooooooooooooooooo [age] = > 35)
This completes a successful escape.
Keyword reduction
If the above content is understood well, then the reduced part of the keyword will not be very difficult to understand. The difference between the keyword increase and the keyword increase is that the structure that needs to be deserialized is usually placed in the redundant discarded part of the keyword increase, while in the keyword increase part of the deserialization structure that we want to parse through the increase in the number of key strings, the deserialization structure that we want to parse through the increase in the number of keywords needs to become part of the key string due to the change in string length and is not parsed.
Similar to the example of an increase in keywords:
In this example, oo will be replaced with o, assuming that our goal is still to change the value of age to 35.
Payload:
SARV 2: {username 8: "username"; SER 44: "oooooooooooooooooooooooooooooooooooooooooooo"; SARV 3: "age"; SARV 2: "15";} "; SRAV 3:" age "; SPLR 2:" 35 ";}
You can see that age has been changed to 35.
The principle for doing this is similar to the increase in keywords:; age 3: "age"; SLR 2: "15";} length 22, we construct 44 o as the value of username, and then we deserialize the structure that we need to change; SREV 3: "age"; sage 2: "35";} at the end, the number of o is changed to 22 after preg_replace replacement, and the length defined by username is 44, and php will The 22 characters are read together as part of the username, and then as long as the latter part of the username is closed properly, it will be parsed as a normal deserialization structure, thus achieving the purpose of escape.
0x08 Phar deserialization vulnerability
Phar ("Php ARchive") is a packaged file similar to JAR in PHP. If you are using PHP 5.3 or later, the Phar suffix file is enabled by default, and you don't need any other installation to use it. There is also a useful point of deserialization in Phar files: phar files will store user-defined meta-data in serialized form, and user-defined metadata in meta-data will be deserialized when executing Phar files, thus achieving the purpose of deserialization attacks, which also extends the attack surface of PHP deserialization attacks.
This use comes from the topic of File Operation Induced Unserialization via the "phar://" Stream Wrapper shared by Sam Thomas at the 2018 Blackhat conference, which can be found here [portal]. (From Freebuff)
Under the condition that the parameters of file system functions (file_exists (), is_dir (), etc.) can be controlled, and with phar:// pseudo-protocol, this method can
Do not rely on unserialize () to deserialize directly.
In CTF, it is often difficult to construct POP chains combined with file uploading, arbitrary file reading and deserialization.
The file structure of Phar file: 1. A stub
It can be understood as a flag in the format of xxx, which is unlimited, but must end with _ _ HALT_COMPILER ();? >, otherwise the phar extension will not recognize the file as a phar file.
2. A manifestdescribing the contents
Phar file is essentially a compressed file, in which the permissions, attributes and other information of each compressed file are placed in this section. This section also stores user-defined meta-data in serialized form, which is the core of the above attack techniques.
3. The file contents
The contents of the compressed file.
4. [optional] a signaturefor verifying Phar integrity (phar file format only)
The signature should be placed at the end of the file in the following format:
Demo
According to the file structure, we build a phar file ourselves, and php has a built-in Phar class to handle the relevant operations.
Note: you cannot generate a phar file unless you set the phar.readonly option in php.ini to Off.
Through hex, you can see that the data is indeed serialized and stored in the file.
Serialization data will inevitably be deserialized. A large part of php file system functions will deserialize meta-data when parsing phar files through phar:// pseudo protocol. The functions affected after testing are as follows:
Look at the underlying logic of PHP:
Php-src/ext/phar/phar.c
Verify the phar file just generated by a small example
Other file manipulation functions are also available:
When the parameters of the file system function are controllable, we can deserialize without calling unserialize (), and some functions that looked "harmless" before also become "hidden kill", greatly expanding the attack surface.
Fake phar as a file in other formats
In the previous analysis of the file structure of phar, you may notice that php recognizes the phar file by the stub of its header, or more specifically, _ _ HALT_COMPILER (); > this code does not require the preceding content or suffix. Then we can disguise the phar file as a file in another format by adding any header and modifying the suffix.
Attached: php magic functions that often occur in deserialization vulnerabilities
1.__construct ()
It is called when the object is instantiated, and when the _ _ construct and the function with the class name exist at the same time, _ _ construct will be called and the other one will not be called.
Note: objects generated by deserialization do not call the _ _ construct function
2.__destruct ()
Called when the delete object or object operation terminates. Commonly used
3.__call ()
Object calls a method, which is called directly if the method exists; if it does not exist, the _ _ call function is called.
4.__get ()
When reading a property of an object, if the property exists, the property value is returned directly; if it does not exist, the _ _ get function is called.
5.__set ()
When setting a property of an object, if the property exists, it will be assigned directly.
If it does not exist, the _ _ set function is called.
6.__toString ()
Called when printing an object. Such as echo obj; or printobj; or printobj
7.__clone ()
Called when the object is cloned. Such as: t=newTest (); t=newTest (); t1=clone $t
8.__sleep ()
Serialize was called before. If the object is large and you want to delete something before serializing, consider this function.
9.__wakeup ()
Unserialize is called to do some initialization of the object.
This is the end of the PHP deserialization vulnerabilities that often occur in CTF. I hope the above content can be helpful to you and learn more. If you think the article is good, you can share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.