如何?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是一个弱类型语言,我们甚至可以对类中未赋值的变量赋值任何类型的值,甚至是一个类。

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

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

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

相关推荐
IT小辉同学3 分钟前
一键生成本地SSL证书:打造HTTPS安全环境
安全·https·ssl
weisian1518 分钟前
认证鉴权框架SpringSecurity-2--重点组件和过滤器链篇
java·安全
Koi慢热17 分钟前
信息收集合集
网络·安全·web安全·网络安全
网安_秋刀鱼2 小时前
PHP代码审计 - SQL注入
sql·web安全·网络安全·php·1024程序员节
B20080116刘实2 小时前
CTF攻防世界小白刷题自学笔记13
开发语言·笔记·web安全·网络安全·php
PcVue China5 小时前
PcVue + SQL Grid : 释放数据的无限潜力
大数据·服务器·数据库·sql·科技·安全·oracle
数据小小爬虫8 小时前
如何用Java爬虫“偷窥”淘宝商品类目API的返回值
java·爬虫·php
汤米粥10 小时前
小皮PHP连接数据库提示could not find driver
开发语言·php
Hacker_Nightrain10 小时前
网络安全CTF比赛规则
网络·安全·web安全
看山还是山,看水还是。10 小时前
Redis 配置
运维·数据库·redis·安全·缓存·测试覆盖率