当我们了解并掌握简单的反序列化知识后,我们可以通过一些经典的稍难题来进阶,熟悉做题流程和思路
这里我们采用nssctf平台上整理的 [NISACTF 2022]babyserialize 这道题
首先找切入点-------找到NISA类invoke的eval()函数,并且参数可控,则思路正确,这是一个正确的方向。。
接着做好标记
一、理清pop链并进行标注
先找eval、flag这些危险函数和关键字样(这就是链尾),找到 eval函数 ,且参数是txw4ever
我们可以利用这个txw4ever,来调用系统函数实现命令执行
OK,下面开始教你们做标注
首先我们找到第一步用到的参数所在位置,并在后面标注清楚需要传入的内容
1可以理解为第一步,shell表示我们这里需要传入一个类似shell的东西或者用system标注
传给谁就标注在谁的后面,这里表示要传给txw4ever,而txw4ever是在NISA类下
标注好后,我们继续沿着eval往上看,发现需要触发__invoke()的条件,
__invoke()是对象被当作函数进行调用时就会触发,总之一句话,(在所有!!类中)去找$a()这种形式的,,找到$bb(),它对应的参数是su,且在类llovetxm里 特征 $*****();
同理 我们进行标注表示要调用参数su,且给他传入NISA类
往bb上边看,发现需要触发__toString()函数,
__toString()当对象被当作字符串的时候自行调用,
继续在所有类中找,找到
Strtolower($a)就是把$a字符串变为大写,然后返回一串字符串
Strtolower($a)在four类中,继续进行标注,生成上一个对象
参数是a
继续往上看,需要触发__set()函数
__set()函数是对不存在或者不可访问的变量进行赋值就会自动调用
于是我们找到了huang,我们可以看到在llovetxw类中并不存在fun这个参数
同样进行标注,标注就是标注其参数!!!,同样改为上一个类的对象
继续看,需要触发__call()
而__call()是对不存在或不可访问的方法进行调用时,就会触发这个函数
继续在所有类中寻找
找到nisa();进行参数标注
在往上就是__wakeup(),在反序列化时调用之后。。这就是链头。
- ..编写脚本
我们就根据刚才标注的54321的顺序来写,用到那个类,必须先new实例化一遍
(哪怕重复到某个类,也要重新实例化一边)
开个头,我们先用到NISA类,说以实例化NISA类,$n=new NISA();
$n->txw4ever表示调用这个类里边的txw4ever
继续第二步我们用到llovetxw类,将其实例化。。。。。。。。。。。。。。。。。。。
- ..过滤与绕过。
一些需要赋具体值的,直接在原代码上改就行了。
System(“tac /f*”)被过滤,就把system变为大写,就可以绕过。。
拓展__get()函数
__get定义:__get 是 PHP 中的魔术方法之一,它用于在对象中访问不存在的或无法访问的属性时自动被调用。如果一个类中定义了__get()方法,那么当我们试图获取该类的一个不存在或无法访问的属性时,该方法会被自动调用,从而可以对该操作进行处理。
在直接获取私有成员属性得时候,自动调用了这个__get()方法
姓名:张三
在直接获取私有成员属性得时候,自动调用了这个__get()方法
性别:男
在直接获取私有成员属性得时候,自动调用了这个__get()方法
年龄:12
注意:
protected $var = 'php://filter/convert.base64-encode/resource=/flag';
- shell写flag.php就不对了,然而写/flag时就对了,很奇怪,所以不出答案时,多试一试,改一改。
- 关于__get()函数
找不到触发的条件怎末办
办法总比困难多,换一下思路。