如何?WEB安全(六)

php反序列化

按照我学习的次序,慢慢的已经说到了反序列化了。

这个我个人觉得还是比较简单的,因为它大部分已经不是你可以操作的了,都是PHP这个语言自已已经预定义好的函数。

那么先说说序列化到底是个什么东西呢,在互通互联的这个时代,光纤等之间传播的是字节流,根据一定规则形成的字节流。序列化正是为了能够更加方便传输而设计的,将数据结构转变成字节进行传递,接收后还可以反序列化进行还原,虽然失去了一些信息。但只要有相同的模板,表明的是相同的对象,一切就都还原了。

可能我说的不是很明白,为了讲明白我上面所说的东西。简单给大家说一下面向对象思想,PHP支持这种思想的编程,因此如果不好好考虑周全,可能会出现反序列化漏洞。

面向对象程序开发思想

在我看来,这种思想相对于面向过程开发,注重的是抽离出抽象的概念,赋予它相关的属性,他的功能。对于这整个的抽象概念我们成为其,也叫class

比如,人这个概念。抽象出来,就是他有属性:年龄、身高、性别等等,他的功能是:吃饭、睡觉等等。

其中属性我们可以叫它属性或者数据,功能我们叫它函数(功能)或者方法

下面我用PHP写一个类,供大家观赏,理解一下。

php 复制代码
<?php
    class man{
    public $name;
    public $age;
    
    
    public function eat(){
        echo "eating";
    }
}

当然php也有相应的静态属性和静态变量,所不同的地方就是添加static关键词还有静态属性,使用::并带有$来调用,静态方法不需要加$但要加前者。

而动态的变量在类外面引用的时候不需要在变量前添加$,比如:$who=new man(); $who->name="Raya";这种方式。

对类当中的方法调用时:$who->eat();来完成。

有了这些前置的知识,接下来要说一说序列化和反序列化了,这在网络传输当中经常使用到(或许还有其他用途,我目前知识并不清楚)。在序列化之后(以php举例,其他语言也有序列化函数,只不过有些不同),会生成一段规则的字符串,例如:

php 复制代码
O:6:"person":3:{s:4:"name";s:5:"lihua";s:3:"age";i:20;s:6:"height";i:170;}

以上就是被一个初始化的person类进行的序列化,我们会注意到里面除了可以依稀辨别的字符串和数值,还有其他的一些信息,比如o或者s之类,它们是用于携带原信息之外的信息的(如果有兴趣可以去查以下对应表)。

描述它们的不同数据类型,后面跟着的一个整数表示后面字符串的所占的字节数(我认为是这样的),需要一一对应,不然可能无法还原成功。

其序列化使用的函数叫:serialize(),反序列化的叫:unserialize()

还有一个问题就是,当我们序列化之后还要看得就是那些变量的访问权限,会有public、protected、private以及缺省不写(会默认public级别)这几种。关于public这种没关系,剩下两种的序列化字符串当中存在一些不可打印字符:protected 修饰的属性被序列化的时候属性值会变成%00*%00属性名;private 修饰的属性被序列化的时候属性值会变成%00类名%00属性名

这时候需要对其进行url编码或者base64编码来传输,不然会出现数据丢失,导致错误。

这里要说的还有一点就是,php当中,以及其他的某些编程语言当中会存在一些魔术方法,它们不需要显示的调用,达到一定条件之后自动触发,程序员可自定义书写触发内容。

这也就是漏洞的成因,如果通过构造特定的类对象,就可能会出现严重的危险。

它们通常以两个下划线开头,比如php类的构造方法就是如此。

  1. __construct(),类的构造函数
  2. __wakeup(),执行unserialize()时,先会调用这个函数
  3. __destruct(),类的析构函数,允许在销毁一个类之前执行的一些操作或完成一些功能,通常程序结束时会触发
  4. __call(),在对象中调用一个不可访问方法时调用
  5. __get(),获得一个类的非公有成员变量时调用
  6. __set(),设置一个类的成员变量(非公有)时调用
  7. __toString(),对象被当成字符串处理时的方法
  8. __invoke(),调用函数的方式调用一个对象时的回应方法
  9. __callStatic(),用静态方式中调用一个不可访问方法时调用
  10. __isset(),当对不可访问属性调用isset()或empty()时调用
  11. __unset(),当对不可访问属性调用unset()时被调用。
  12. __sleep(),执行serialize()时,先会调用这个函数
  13. __set_state(),调用var_export()导出类时,此静态方法会被调用。
  14. __clone(),当对象复制完成时调用
  15. __autoload(),尝试加载未定义的类
  16. __debugInfo(),打印所需调试信息

以上是一些相关的魔术方法,大多数都有执行的条件,其中有两个是只要定义就会被执行的:__wakeup()还有__destruct()。

大部分的方法无法跳过,满足条件自动执行,但是__wakeup()函数如果反序列化出现的对象存在问题就会跳过执行,有时会使用到这个知识点。

由于php是一个弱类型语言,我们甚至可以对类中未赋值的变量赋值任何类型的值,甚至是一个类。

如果是在解这方面题,首先要去看是什么语言,遵守其序列化和反序列化的规则,其实就是构造一条长长的反序列化漏洞传递链条,先尝试找到可以自动触发的魔术方法,没有再去看其他方法有无可能,之后根据语言的操作内容构造一个以上的类对象,将其序列化然后传入相应位置,让代码执行。

我想说的就是这么多,剩下的就是做题之类的找到相应的感觉。

但这里主要是总结知识点,做题部分如果有机会我会发布一个新的文章,一定会有的。

相关推荐
JaguarJack12 小时前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo12 小时前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack2 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理2 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
一次旅行2 天前
网络安全总结
安全·web安全
red1giant_star2 天前
手把手教你用Vulhub复现ecshop collection_list-sqli漏洞(附完整POC)
安全
QQ5110082852 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe2 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5
ZeroNews内网穿透2 天前
谷歌封杀OpenClaw背后:本地部署或是出路
运维·服务器·数据库·安全
一名优秀的码农2 天前
vulhub系列-14-Os-hackNos-1(超详细)
安全·web安全·网络安全·网络攻击模型·安全威胁分析