PHP开发中的不安全反序列化

    序列化是开发语言中将某个对象转换为一串字节流的过程,转换后的字节流可以方便存储在数据库中,也可以方便在网络中进行传输。而反序列化则是将数据库取出的字节流或从网络上接收到的字节流反向转换为对象的过程。概念虽如此,但不同的开发语言的序列化和反序列化的过程又略有不同。    

    以下代码是PHP序列化和反序列化的简单示例:

    如果应用的反序列化字符串能够最终被用户操控,那么恶意攻击者可以操控序列化对象将恶意代码植入到应用中执行,从而造成诸如命令执行的漏洞。因此,应用开发中对不可信的输入来源如无必要不要做反序列化操作。   

   PHP的序列化基本类型如下表所示。

    以上文中的序列化输出为例:

O:3:"Car":3:{...}

   开头大写的O表示后面的字符串是对象类型,之后的3表示类名的长度(即Car的长度),最后的3表示类中属性的个数(即brand、model、year)。

s:5:"brand";s:6:"Toyota";

    这是Car类的第一个属性,包括属性名称和属性值,根据上面的序列化基本类型,s表示是字符串,5和6表示字符串长度,最后是字符串值。

s:5:"model";s:5:"Camry";

    同上,这是Car类的第二个属性,包括属性名称model和属性值Camry。

s:4:"year";i:2022;

    这是Car类的第三个属性,包括属性名称year和属性值2022,其中i表示整型类型,后续接数值2022。

    可见,字符串在序列化后是不会转义的,但上例中属性都是公有的(public),因此没有类名做前缀,如果是保护类型(protected),则会表示为\x00*\x00,如果是私有类型(private),则会表示为\x00Car\x00。

    假设上述序列化字符串的model属性存在注入漏洞,且该序列化字符串可被攻击者控制,那么攻击者可以构造类似下面的序列化字符串:

O:3:"Car":3:{s:5:"brand";s:6:"Toyota";s:5:"model";s:17:"Camry\' or 1=1 -- ";s:4:"year";i:2022;}

    CVE-2018-18702和CVE-2019-13292便是由于用户输入的内容经过反序列化之后执行数据库操作从而导致的SQL注入漏洞,因此CVSS评分高达9.8分。

    CVE-2019-13292构造的POC是:

echo base64_encode(serialize(["0" => "' or sleep(5) and '1'='1"]));

    实际场景中很少会有这么简单且直接的反序列化漏洞。这时攻击者可以利用PHP的魔法函数,魔法函数以双下划线开头,并会在反序列化被调用过程中执行。    PHP中的魔法函数包括:

__destruct:析构函数

__wakeup:反序列化时先被调用,而后再执行反序列化,用于准备对象需要的资源

__sleep:序列化时先被调用,而后再执行序列化,用于清理对象

__toString:类被当做字符串时调用,该方法必须返回字符串

__invoke:类被当做函数使用时调用

    比如下面的示例代码:

    上述代码的类对象序列化之后的结果是:

O:12:"Serialkiller":4:{s:24:"%00Serialkiller%00cache_file";s:16:"cache/john.cache";s:22:"%00Serialkiller%00log_file";s:13:"logs/john.log";s:21:"%00Serialkiller%00content";s:12:"Starting log";s:18:"%00Serialkiller%00user";s:4:"john";}

    因此,可以控制cache_file变量和log_file变量执行任意操作。比如利用__wakeup函数写入shell代码:

O:12:"Serialkiller":4:{s:24:"%00Serialkiller%00cache_file";s:5:"1.txt";s:22:"%00Serialkiller%00log_file";s:13:"logs/rce1.php";s:21:"%00Serialkiller%00content";s:24:"<?php%20system(%27ls%20~%27);%20?>";s:18:"%00Serialkiller%00user";s:4:"john";}

    在实际开发中,为了防止可能出现的反序列化漏洞有多种办法,其中一种是检查序列化字符串的类型。比如下面的代码:

<?php
function _safely_unserialize($input) {if (is_string($input) &&in_array(substr($input, 0, 1), array('a', 'O', 'b'))) {$input = "#" . $input;}return @unserialize($input);
}_safely_unserialize($_POST['data']);?>
?>

    这段代码中,_safely_unserialize函数通过in_array方法判断用户可控的data参数是否是PHP序列化的三种类型,即数组(a)、对象(O)和布尔值(b),如果是其中之一的类型,则在字符串前增加#,从而导致在反序列化时造成反序列化失败,最终返回false值。该函数旨在判断序列化字符串是否是安全的,但判断方法仅仅是判断序列化类型。

    黑名单的过滤方式漏掉了PHP的另一种序列化对象类(C),因此可以构造类的序列化字符串绕过黑名单检查。    比如通过下述代码构造C开头的序列化字符串:

class obj implements Serializable {private $data;public function __construct() {$this->data = "My private data";}public function serialize() {return serialize($this->data);}public function unserialize($data) {$this->data = unserialize($data);}public function getData() {return $this->data;}
}$obj = new obj;
$ser = serialize($obj);var_dump($ser);

    从PHP 8.1版本开始,官方不再鼓励从Serializable类继承serialize()和unserialize(),而是建议直接使用魔术方法__serialize()和__unserialize(),但生成的序列化类型会是O。

class obj {public $message;public function __construct() {$this->message = "My private data";}public function __serialize() {return ['msg' => $this->message];}public function __unserialize(array $data) {$this->message = $data['msg'];}
}$obj = new obj;
$ser = serialize($obj);var_dump($ser);
var_dump(unserialize($ser));

作者:裴伟伟

2024年5月15日

洞源实验室

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

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

相关文章

ASP.NET在线二手交易系统的设计与实现

摘 要 随着当今社会信息技术的进步&#xff0c;基于互联网的各种应用日益受到了人们的重视&#xff0c;二手商品的重新利用也逐渐被人们关注&#xff0c;二手交易系统就在这种形势下产生了&#xff0c;它利用网络&#xff0c;改变了人们的购物方式。 本文是基于现代二手交易…

AC/DC电源模块的故障诊断与维修技巧

BOSHIDA AC/DC电源模块的故障诊断与维修技巧 AC/DC电源模块是一种常用的电力转换设备&#xff0c;用于将交流电转换为直流电供给电子设备。然而&#xff0c;由于使用环境和操作不当等原因&#xff0c;电源模块可能会出现故障。本文将介绍AC/DC电源模块的故障诊断与维修技巧。…

什么?你设计接口什么都不考虑?

如果让你设计一个接口&#xff0c;你会考虑哪些问题&#xff1f; 1.接口参数校验 接口的入参和返回值都需要进行校验。 入参是否不能为空&#xff0c;入参的长度限制是多少&#xff0c;入参的格式限制&#xff0c;如邮箱格式限制 返回值是否为空&#xff0c;如果为空的时候是…

VC++6.0自定义实现日志记录到文件及界面显示

1&#xff0c;实现日志记录到文件&#xff0c;支持日志文件大小限制&#xff0c;节省空间 void CController::LogWriteRecord(CString strText,CString strFileName) {CStdioFile csFile;try{BOOL bRet csFile.Open(strFileName,CFile::modeCreate|CFile::modeNoTruncate|CFi…

不相交集合的数据结构

一、不相交集合的操作 不相交集合的数据结构维护了一组不相交动态集的集合 &#xff0c;用集合中的某个成员作为代表标识集合。 集合在没有修改的情况下每次访问代表得到的答案是相同的&#xff0c;此外在其它一些应用中&#xff0c;可能按照规定选择集合的代表&#xff0c;例如…

【CSS基础】

4.CSS基础 4.1css的介绍 层叠样式表(英文全称:Cascading Style Sheets),是一种对web文档添加样式的简单机制&#xff0c;属于表现层的布局语言.4.2css基础语法 CSS语法由两部分组成&#xff1a;选择符、声明。 声明包括&#xff1a;属性和属性值选择符 {属性: 属性值 ;属性:…

docker 配置文件使用经验,后续持续增加

1. 容器中如何访问主机服务 在docker容器、docker compose 中如何访问主机服务呢&#xff1f; docker容器 20.10.0 版本在 linux 新增 host.docker.internal 支持&#xff1a; docker run -it --add-hosthost.docker.internal:host-gateway alpine cat /etc/hosts 127.0.0.…

leetcode hot100_part28_图论

目录 200.岛屿数量 DFS bfs 并查集 994.腐烂的橘子 207.课程表 DFS BFS 208.实现Trie&#xff08;前缀树&#xff09; 做完了这四题&#xff0c;总结一下&#xff0c;还是要掌握基本的dfs&#xff0c;bfs模版&#xff0c;都是在这些基础上变换的。 模版&#xff1a; …

项目-坦克大战

增加功能 我方坦克在发射的子弹消亡后&#xff0c;才能发射新的子弹。同时实现发多颗子弹 1&#xff0c;在按下J键&#xff0c;我们判断当前hero对象的子弹&#xff0c;是否已经销毁2&#xff0c;如果没有销毁&#xff0c;就不去触发shotEnemyTank3&#xff0c;如果已经销毁&…

WebSocket or SSE?即时通讯的应用策略【送源码】

最近在研究H5推送&#xff0c;发现除了我们常用的WebSocket以外&#xff0c;其实还有一种协议也能实现H5推送&#xff0c;那就是SSE协议。 而且&#xff0c;当前主流的大模型平台&#xff0c;比如ChatGPT、通义千问、文心一言&#xff0c;对话时采用的就是SSE。 什么是SSE协议…

文件上传OSS实现

1). 定义OSS相关配置 在sky-server模块 application-dev.yml sky:alioss:endpoint: oss-cn-hangzhou.aliyuncs.comaccess-key-id: LTAI5tPeFLzsPPT8gG3LPW64access-key-secret: U6k1brOZ8gaOIXv3nXbulGTUzy6Pd7bucket-name: sky-take-outapplication.yml spring:profiles:a…

100m/s高速轧制钢材 八轴测径仪检测毫无压力

关键词&#xff1a;八轴测径仪,在线测径仪,钢材测径仪,高速轧制 随着技术的提升&#xff0c;钢材的生产速度越来越快&#xff0c;一些高速生产的钢材&#xff0c;生产速度甚至达到了100m/s&#xff0c;这是一个非常快的速度。 如果汽车以120公里/小时的速度行驶&#xff0c;那么…

Unity WebGL全屏显示

一、删除footer节点 二、删除最下面点击事件绑定 修改Canvas宽高 canvas.style.width "960px"; canvas.style.height "600px"; 改成 canvas.style.width document.documentElement.clientWidth"px"; canvas.style.height document.document…

行为驱动开源免费接口测试框架:karate

什么是行为驱动测试&#xff1a; 行为驱动测试&#xff08;Behavior-Driven Testing&#xff0c;简称 BDT&#xff09;是一种测试方法&#xff0c;旨在通过描述系统行为和功能来编写测试用例。BDT的重点是从用户的角度出发&#xff0c;描述系统应该如何行为&#xff0c;而不是专…

计算机视觉全系列实战教程:(二)Opencv4+VS2022开发环境搭建

1.下载和安装 VS2022下载&#xff1a;https://visualstudio.microsoft.com/zh-hans/vs/ Opencv下载&#xff1a;https://opencv.org/releases/ Opencv安装有多种方式&#xff0c;一般学习者直接下载.exe傻瓜式安装即可 2.VS2022配置opencv4开发环境 &#xff08;1&#xff0…

Ubuntu设置中文教程

一、前言 Ubuntu是一款广受欢迎的Linux发行版&#xff0c;其界面友好、易用性强&#xff0c;并且拥有庞大的用户群体和丰富的社区资源。对于使用非英文操作系统的用户来说&#xff0c;将Ubuntu设置为中文界面是非常必要的。本文将介绍如何在Ubuntu中设置中文环境。 二、准备工…

DiskANN数据布局

_mem.index.data&#xff1a;和sift_base.fbin一模一样。0-3字节是总向量数&#xff0c;4-7是每个向量的特征数。后面就是依次放置的每个向量。 _disk.index&#xff1a;是存储的图&#xff0c;但是不光包含图也包含原始向量。前4KB不知道存的是啥。从第0x1000开始存放的是原始…

国内企业更喜欢私有化部署的 6 大原因

今天在 V 站看到一篇题为《为什么国内企业会更倾向于接受私有部署而不是 SaaS&#xff1f;》的帖子&#xff0c;觉得很有启发&#xff0c;这里把网友的观点稍作整理和总结&#xff0c;分享给大家参考。 在技术日益发展的今天&#xff0c;国内企业的软件部署方式似乎呈现出与欧…

【机器学习】机器学习:人工智能中实现自动化决策与精细优化的核心驱动力

&#x1f512;文章目录: &#x1f4a5;1.概述 ❤️2.机器学习基本原理 &#x1f6e4;️2.1定义与关键概念 &#x1f6e3;️2.2 机器学习算法 ☔3.自动化决策中的机器学习应用 &#x1f6b2;4.精细优化与机器学习的结合 &#x1f44a;5.挑战与前景 &#x1f4a5;1.概述 …

样式表单MIME 类型 “text/plain“ 不是 “text/css“问题处理

样式表单www.*.com/static/js/*.css未载入&#xff0c;因为它的 MIME 类型 "text/plain" 不是 "text/css"。 原因是服务器返回的MIME类型为 "text/plain"&#xff0c;而预期应该是 "text/css"。MIME类型是一种标准&#xff0c;用于定…