Dest1ny的第一篇教学文章!如果你对 PHP 还不太熟悉,但又想了解反序列化攻击是怎么回事,那么这篇教程就是为你准备的。我们将从最基础的概念讲起,用简单的例子一步步带你理解 PHP 反序列化的工作原理、准备好,我们就开始吧!
php反序列化介绍
PHP 反序列化是指将通过序列化操作转换成字符串格式的数据重新恢复为原来的 PHP 对象或数组的过程。序列化是将复杂的数据结构(如对象、数组)转换成字符串的方式,这样可以方便地存储或传输这些数据。而反序列化就是将这些字符串还原成原始的 PHP 数据结构。
但是这种介绍看一百遍都没啥用,接下来我们用例子来跟大家讲解!
CLASS-1 php面对的是对象!
首先php语言是一个面向对象的语言,那我觉得就是你定义了一个英雄模版(如下图),这个英雄有名字和性别,而且有一个可以查看英雄属性的选项,当你去创建一个英雄的时候,可以去初始化他的数值,并且可以调用他自带的查看属性的功能。
结果如下:
可以说这一切的一切都是因为我创建了一个新角色,才会有后面的操作。
CLASS-2 !我会了!我要去反序列化了!
ok,没问题!这是一道非常easy的反序列化,大家可以试试!
我在哪,我是谁,我在干嘛......如果是小白肯定就不知道自己要干什么了,这其实都不算一个题目,就是考验大家php代码基础,哈哈。
这里小白们我觉得会有三个疑问:
-
php看不明白?
-
我咋去利用php反序列化?
-
这段代码有啥漏洞?
我跟别的大佬不太一样,我喜欢用结果去推出问题。我们这篇文章的目标就是把这点代码看明白!
CLASS-3 !php代码理解!
这是上面代码的注释版本
其实很简单啊,就是你现在有一个test的模版,里面有一个属性,是一个$a,然后test还有一个displayVar的方法,里面写着eval()。
这里的$_GET大家可以理解为,给了你一个接口可以去修改test里面属性的值!那有人会说$a不都赋好值了吗?这其实是$a的默认值,只要你去创建了一个新的对象,模版是test,你就可以去随意改动默认值,就像游戏一样,你可以自己主动去修改游戏里的操作数值,如果不修改,它就会使用默认值。
get之后还有一个unserialize,英文翻译为反序列化。代码最后调用了displayVar。诶,反序列化!一定是这里有洞!是的没错,那我该如何利用呢?
CLASS-4 !unserialize?serialize?
首先大家可以看一下这个序列化的例子,代码很简单,我们关注一下$a序列化出来的结果。
感觉好熟悉,有test,有pub,还有benben都是test这个模版里面出现的?诶等等怎么没有我最想要的技能(jineng)?是不是忘记了?
那我们先把这个序列化出来的结果正规的讲解一下:
-
O
:表示这是一个 对象(Object)。 -
4
:这是 类名长度,表示接下来类名的字符数是 4 个字符。 -
"test"
:这是 类名,该对象的类名是"test"
。表示这是一个test
类的对象。 -
1
:表示该对象有 1 个属性。 -
{}
:花括号内包含该对象的属性和对应的值。-
s
表示这是一个 字符串 类型的值。 -
6
表示字符串的长度为 6 个字符。 -
"benben"
是属性pub
的值。
-
s
表示这是一个 字符串 类型的值。 -
3
表示字符串的长度为 3 个字符。 -
"pub"
是属性名,表示该对象的一个公共属性(public
属性)名为pub
。
-
s:3:"pub"
: -
s:6:"benben"
:
-
所以总的来说,就是把test模版里面除了jineng的方法,其他全部很详细的用字符串显示出来,包括属性,包括属性的值,甚至是类本身的名字也显示出来了。
那反序列化啥意思啊?还是这个模版,稍微改了一下:
大家重点关注一下这,我把serialize的结果用unserialize去执行了!
这里注意一下,我去反序列化的字符串不一样的是,我把pub的值给改了,大家一定要注意,为什么6变成了9,因为我传的值发生了改变,从benben的六个字符变了guanzhuwo的9个字符,大家一定要注意,一定要注意数字的值跟字符串的个数对应情况!
结果是什么呢?
pub的值被改成"guanzhuwo"了,所以反序列化简单来说就是把序列化出来的字符串进行反向操作,去修改类里面的值!
诶诶诶!感觉有点火热了,那是不是说我可以通过反序列化修改类里面属性的数值去干点坏事呢?
CLASS-5 !eval竟然是你!
那我们可以去改动类里面的值,但是改变值有啥用啊?有危险方法在调用我们的值不就可以去干坏事了吗,危险函数是谁呢?eval!大家在哪里见过它呢,一句话木马!
eval函数干啥的呢,eval()
会把传入的字符串当作 PHP 代码执行。
eval() 函数会执行任意 PHP 代码。如果我们可以能够控制传入的 $a 属性内容,他们可以执行任意 PHP 代码,导致远程代码执行漏洞。
php里面有一个方法可以执行命令,就像是python里的os库一样,是system!一句话木马里也经常出现!所以我们只要让$a的值里去用system执行命令,那么是不是就完成进攻了呢?
CLASS-5 Happy-ending!
万事俱备,所以我们的思路是
-
去新建一个以test为模版的对象。
-
用test的模版对象去修改变量模版对象$a的值,这里有同学会说我在这改我自己设置的对象有屁用?其实这几步都是为了去构造序列化的结构,不然你想手撸序列化代码啊哈哈。
-
将传完之后的结果序列化出来,这个序列化完的结果的结构完全可以用反序列化的方式倒回到被攻击的服务器上部署的php代码里的test
-
最后务器上部署的php代码会自动执行$a里的命令
形象一点:
我买了一个玩具 -> 我又去把玩具倒了个模具出来 -> 我用模具做了一个一样的外壳 -> 不同的是我把外壳里面换成了shi -> 找商家7天无理由退款->商家一看,诶,外观啥的都一样,符合退款标准,同意退款!-> 商家被臭昏了
这里面谁出问题了呢,一定是商家检查机制不好,臭死活该!
最后的payload,大家请查收!
http://127.0.0.1:8088/class06/index.php?benben=O:4:%22test%22:1:{s:1:%22a%22;s:17:%22system(%27whoami%27);%22;}
比较简单,只是给小白开个头,希望可以帮助到你们!
我是Dest1ny,制作不易,记得点关注点赞!!!