原标题:细说php反序列化字符逃逸

11/5

文章共计4381个词

预计阅读10分钟

前言

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

基础知识理解

字符逃逸在理解之后就能够明白,这是一种闭合的思想,它类似SQL中的万能密码,理解这种原理之后会变得特别容易。

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

class people{

public$name = 'Tom';

public$sex = 'boy';

public$age = '12';

}

$a = newpeople;

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,可以看到下图成功修改了

例题

有了以上基础,就可以做题了,简单的开始入手

安H四月(字符减少)<?php

show_source( "index.php");

function write($data){

returnstr_replace(chr( 0) . '*'. chr( 0), '000', $data);

}

function read($data){

returnstr_replace( '000', 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{

echofile_get_contents( $this->c);

return'nice';

}

}

$a = newA($_GET[ 'a'],$_GET[ 'b']);

//省略了存储序列化数据的过程,下面是取出来并反序列化的操作

$b = unserialize(read(write(serialize($a))));

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

function write($data){

returnstr_replace(chr( 0) . '*'. chr( 0), '000', $data);

}

function read($data){

returnstr_replace( '000', chr( 0) . '*'. chr( 0), $data);

}

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

题目中序列化的是对象$a,里面有两个参数,username和password,我们要传入的也是这两个参数的值,所以我们构造的payload,应该是往password传我们构造好的字符,而在username传入的为计算好的000个数,

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

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

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

我所选择的地方就是需要被吞噬的部分,然后才能使得后边的代码全部逃逸,长度为23,计算后发现需要8个000,但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个000:

000000000000000000000000

最终payload:

?a=000000000000000000000000&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中:

publicfunction filter($string){

$escape = array( ''', '');

$escape = '/'. implode( '|', $escape) . '/';

$string = preg_replace($escape, '_', $string);

$safe = array( 'select', 'insert', 'update', 'delete', 'where');

$safe = '/'. implode( '|', $safe) . '/i';

returnpreg_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

相关实验:PHP反序列化漏洞实验

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

责任编辑:

PHP反序列化由浅入深,细说php反序列化字符逃逸相关推荐

  1. CTF-PHP反序列化漏洞5-反序列化字符逃逸

    作者:Eason_LYC 悲观者预言失败,十言九中. 乐观者创造奇迹,一次即可. 一个人的价值,在于他所拥有的.可以不学无术,但不能一无所有! 技术领域:WEB安全.网络攻防 关注WEB安全.网络攻防 ...

  2. 一道ctf题关于php反序列化字符逃逸

    0x01 前言 无意间做应该是0ctf2016的一道web题,get新点,总计一下. 0x02 代码审计 进去之后是一个登录界面,试了一下register.php发现可以注册,注册完成后登录跳转到up ...

  3. Wmm的学习日记(浅学PHP反序列化字符逃逸)

    11月的第一个星期浅浅学习了一下PHP反序列化字符逃逸,也算是给11月开了个好头,作为一只刚刚开始学习网络安全的小白 ,基础知识不太行,如果有不对的地方欢迎大家指正,阿里嘎多,但是看了一些老师的视频和 ...

  4. 0CTF-2016-piapiapia(PHP反序列化字符逃逸)

    0CTF-2016-piapiapia(PHP反序列化字符逃逸) 0x01 前言 开学果然是对更新博客没得想法,趁着闲工夫,做了一下这个题,之前XCTF新春赛也出现了PHP反序列化逃逸,不过没做出来. ...

  5. php反序列化字符逃逸

    文章目录 php反序列化字符逃逸 php反序列化字符逃逸的原理 php反序列化字符逃逸分类 过滤后字符变多 过滤后字符串变少 参考文章: php反序列化字符逃逸 php反序列化字符逃逸的原理 当开发者 ...

  6. [0CTF 2016]piapiapia总结(PHP序列化长度变化导致尾部字符逃逸)

    这道题感觉很难,要是比赛中出这种题我肯定做不来,所以我耐着性子慢慢分析这道题,最后居然自己做了个七七八八,只剩下一点点就完全做出来了. 下面把我做这道题时的思路一步一步记录下来,希望能够彻底巩固. 一 ...

  7. [0CTF 2016]piapiapia(字符逃逸详解)

    目录 知识点 信息收集 尝试SQL注入 源码目录扫描 代码审计 payload生成 知识点 信息泄露 参数传递数组绕过字符串检测 反序列化字符逃逸 信息收集 收集到了一只超可爱的小喵 尝试SQL注入 ...

  8. java反序列化weblogic_[Todo]Java反序列化-weblogic

    从weblogic开始 weblogic是什么 中间件(Middleware),Oracle定义中间件的组成包括Web服务器.应用程序服务器.内容管理系统及支持应用程序开发和交付的类似工具,它通常基于 ...

  9. php反序列化漏洞原理,PHP反序列化原理及漏洞解析

    什么是PHP序列化 PHP序列化与反序列化的过程 一个反序列化漏洞的例子 CVE-2016-7124 一. 什么是PHP序列化与反序列化 1. PHP序列化 PHP序列化是指把变量转化成可保存或传输的 ...

最新文章

  1. 聊一聊今年实例分割领域的进展和未来展望
  2. 如何查看ubuntu下的分区命令
  3. Windows Phone 7的启动器和选择器
  4. Docker导入导出镜像两种方式
  5. (原創) 标准的makefile写法 (C/C++)
  6. 常用作图与图片处理工具
  7. C++:类中的赋值函数
  8. go中使用type关键字来定义类型别名
  9. 正则表达式校验例子[原创]
  10. 使用shell脚本实现在liunx上进行svn的上传下载更新功能
  11. spring 与 guice 的区别好玩的好法(转)
  12. python设置window系统ip
  13. java怎么发布版本号_java 实现比较版本号功能
  14. 数据仓库专题(16)-分布式数据仓库实践指南-目录篇
  15. pcie16x能插1x的卡嘛?_关于电脑能正常进系统但是进bios黑屏的解决办法(DP线连接)...
  16. 论文写不下去时怎么办?
  17. 祝爸爸妈妈中秋节快乐
  18. 输入两个正整数,求其最大公约数。
  19. 提供聚合物水凝胶的用途和结构式(供应胶原-聚乙烯醇(PVA)复合/P(DMAA-co-MMA)/Nano-SiO2复合水凝胶/聚乙烯醇PVA基复合水凝胶/纤维素/聚谷氨酸(BC/PGA)复合水凝胶)
  20. git小乌龟TortoiseGit的使用

热门文章

  1. 差速轮轮速计建模和优化量求导
  2. CODEVS1214
  3. 四、NPP/VIIRS夜间灯光数据校正之连续性校正
  4. linux time效率,time(),gettimeofday()及GetTickCount()效率比较
  5. JEP解读与尝鲜系列4 - Java 16 中对于 Project Valhalla 的铺垫
  6. HEVC一些工具汇总
  7. Android5.0,6.0,7.0新特性整理
  8. 叶黄素对眼睛有什么好处和作用?
  9. VS2019通过ADO连接access数据库(详细)
  10. 基于PHP的校园视频点播系统,基于ThinkPHP框架的IPv6视频点播系统的实现