[0CTF 2016]piapiapia

很有意思的一道题

访问页面之后是登录界面

尝试弱口令登录一下,无果

查看源代码之后也没有什么提示,扫描敏感目录,发现有源码泄露。

这里我用御剑没有扫出来源码泄露,可能跟扫描线程太快了有关,查看www.zip里面泄露的源代码

class.php里面定义了user和mysql两个类

config.php里面是服务器搭建环境的时候设置的参数,如果读者有自己本地搭建环境的经验就会知道,我们下载下来源码之后,还需要根据自己本地的环境进行相应的配置,比如说我们需要在config.php里面设置自己本地数据库的用户名和密码,这些在下载下来的config.php的源代码里面都是暂时空缺的。

所以题目环境docker下发的时候,一定也设置了自己本地的$flag的值,于是我们的目标就是需要读取服务器端config.php文件,就能够得到flag了。

在register.php里面,可以看到是注册一个用户,输入用户名和密码,接着跳转到index.php界面进行登录

在index.php里面我们输入用户名和密码进行登录,接着跳转到profile.php页面。

在此之前我们需要传递$profile的值

这里对我们输入的phone,email,nickname都进行了过滤,在源码的注释里面我已经进行了说明,很明显最后一个if语句的判断跟前两者有所不同,前两者如果phone为数组的话,匹配失败则为null,取反后就die,而第三个if当nickname为数组的时候,它不会匹配到非数字字母的值,也就为false,长度处使用数组strlen函数也会失效,返回NULL,则绕过了此处的if过滤。

这里添加一个知识点,正则表达式[]内的^表示匹配不存在这类字符的,如图上的第三个if里面的,表示匹配非数字字母的值,在[]外的^表示匹配字符串开头。

所以对于输入的nickname的值我们是可控的。

再去看profile.php

可以看到这里对$profile的值进行了反序列化,接着依次读取,此时对于$photo有一个file_get_contents()文件读取函数,所以这里是我们破题的关键。

值得一提的是,在class.php的mysql类的定义中,过滤函数为

可以看出来将黑名单数组里面的值都换成了hacker

现在我们整理一下思路,update.php中有一个$profile数组变量,这个数组里有$phone, $email, $nickname, $photo几个变量,序列化后profile字段存入数据库,当我们访问profile.php的时候,则会从数据库里面读取profile字段同时反序列化,我们需要控制$photo为config.php,才可以在访问的时候获取到base64编码之后的有flag值的服务器端的config.php

而我们唯一能够控制的变量则是之前说到的nickname,参考了很多师傅的WP之后,写一下这道题的主要知识点:

PHP序列化长度变化导致字符逃逸

首先, PHP反序列化中值的字符读取多少其实是由表示长度的数字控制的,而且只要整个字符串的前一部分能够成功反序列化,这个字符串后面剩下的一部分将会被丢弃

简单举几个例子大家就明白了


得到这个结果很正常

接着我们改变一点点

得到的结果变成了hello woxxx

我们可以看到,原来的字符串hello world内被填充了几个字符串,即xxx”;},在PHP进行反序列化时,由字符串初始位置向后读取8个字符,即使遇到字符串分解符单双引号也会继续向下读,此处读取到 woxxx ,而后遇到了正常的结束符”;},达成了正常反序列化的条件,反序列化结束,后面的 rld”;}  几个字符均被丢弃。

我们用另外一个例子来学习一下这个知识点的应用

可以看到bad_str函数会将序列化之后的单引号转换成为字符串no,实际上这里就已经有了长度的变化,因为单引号长度是1,而no字符串长度是2

接着,我们修改用户的签名

这里偷一张别的师傅的图,虽然输入的值不同,但是思想是相同的

在我们这里,则是想将hello world改变掉。

于是构造

输出的结果跟我们想要的是相同的,hello world变成了hhh

参考一下大佬博客里面对此的解释

在反序列化输出之前,我们的字符串是在某过滤函数的过滤替换之后得到的,在经过过滤处理了之后,字符串的某一部分会加长,但是描述其长度的数字没有发生改变(由反序列化时变量的属性决定),这就可能导致PHP在按描述其长度的数字读取相应长度的字符串之后,本该属于该字符串的内容逃逸出了该字符串的管辖范围。轻则反序列化失败,重则自成一家成为一个独立于源字符串的变量,若是这个独立出来的变量末尾是个结束符";},则可能导致反序列化成功结束,而后面的内容也顺理成章的被丢弃了,此处能够逃逸出的字符串长度由过滤后字符串增加的长度决定,如上图第四个语句,@号内就是我们要逃逸出来的字符串,长度为33,百分号内为我们输入的username变量,要想让@号内的字符串逃逸,我们就需要原来的字符串增加33,这样的话@号内的字符串就会被挤出它原来所在的位置,username的正常部分和增长的部分正好被php解析成一整个变量,@号内的内容就被解析成一个独立的变量,而且因为它的最后有";},所以使反序列化成功结束。

再回到我在本地的例子上面,我们为了使hhh替换掉hello world,于是这一段是需要逃逸出来的字符串

";i:1;s:3:"hhh";}

长度为17,而单引号替换成no之后长度只是增加1,所以为了增加17个长度,我们需要17个单引号,这样才能够将逃逸字符串挤出原来的位置。

紧接着,17*no+test,一共是38个字符,所以在s处我们填写长度为38

最后的$fakes就为

a:2:{i:0;s:38:"test‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘";i:1;s:3:"hhh";};i:1;s:11:"hello world";}

所以在此处我们最终字符串替换成为了hhh

先闭合了一个变量的正确格式,又写入了一个变量的正确格式,最后闭合了一个反序列化的操作。该挤出的被挤出逃逸了,该丢弃的丢弃了,最后想要达成的目标也实现了。

于是我们再回归到题目里面来,因为我们最后是从数据库里面读取反序列化之后的结果,所以我们先在本地搭建序列化,看看序列化的格式之后编写相应的payload

可以看到,根据泄露的源码序列化之后的结果为

a:4:{s:5:"phone";s:6:"123456";s:5:"email";s:12:"[email protected]";s:8:"nickname";a:1:{i:0;s:4:"hell";}s:5:"photo";s:5:"hello";}

我们能够构造的是nickname,在这里我已经是传递数组给他了

我们需要将photo的值hello改变成config.php

根据之前的基础知识,本地的直接构造为:

a:4:{s:5:"phone";s:6:"123456";s:5:"email";s:12:"[email protected]";s:8:"nickname";a:1:{i:0;s:72:"hell‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘";}s:5:"photo";s:10:"config.php";}s:5:"photo";s:5:"hello";}

需要逃逸的字符串为

";}s:5:"photo";s:10:"config.php";}

长度为34,所以添加34个单引号,长度为34*2+4即72

可以看到本地的查看的文件已经修改为了config.php

我们在题目里面使用相同的思想

因为where转换成hacker会由5–>6,字符有一个增加,所以我们为了逃逸34个字符,就添加34*where

警告无伤大雅,因为我们传递的是数组类型的值,所以这里会有警告

源代码里面的base64编码就是config.php的base64编码,解码即可

可以看到成功读取了config.php,里面有flag的值

贴上参考的师傅的博客链接

 https://www.jianshu.com/p/3b44e72444c1 

原文地址:https://www.cnblogs.com/Cl0ud/p/12177095.html

时间: 2024-08-30 09:54:34

[0CTF 2016]piapiapia的相关文章

刷题记录:[0CTF 2016]piapiapia(欠)

目录 刷题记录:[0CTF 2016]piapiapia 刷题记录:[0CTF 2016]piapiapia 今天可能要欠着了 原文地址:https://www.cnblogs.com/20175211lyz/p/11444134.html

# [0CTF 2016]piapiapia解题详细思路及复现

[0CTF 2016]piapiapia解题详细思路及复现 题目链接 https://buuoj.cn/challenges#[0CTF%202016]piapiapia 1. 知识点 信息泄露 参数传递数组绕过字符串检测 反序列化字符逃逸 2. 开始复现 2.1 初探题目 开打题目连接我们可以看到是一个登录页面 不知道为啥我一看到登录页面就想SQL注入一波,我还是太年轻了.这道题没有给出提示,SQL注入也不是没有可能,尝试一波之后放弃了,CTF直接登录框就注入的还是不多. 注册账号 看来我们还

聊一聊前端模板与渲染那些事儿

欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面(不仅仅是代码): https://segmentfault.com/blog/frontenddriver 作为现代应用,ajax的大量使用,使得前端工程师们日常的开发少不了拼装模板,渲染模板.我们今天就来聊聊,拼装与渲染模板的那些事儿. 如果喜欢本文请点击右侧的推荐哦,你的推荐会变为我继续更文的动力 1 页面级的渲染 在刚有web的时候,前端与后端的交互,非常直白,浏览器端发出URL,后端返回一张拼好了的HTML串

使用 Raspberry Pi 上的传感器在 Node.js 中创建一个 IoT Bluemix 应用程序

先决条件 一个IBM Bluemix 帐号,一个 Raspberry Pi 2 或 3,一个 PIR 运动传感器 适用于本文的 Github 存储库 如果您是一位精明的 Bluemix 开发人员,您可能只想看看如何在 node.js 中与 IoT 建立连接,或者只想了解如何从此 github 存储库中拉取我的代码. git clone https://github.com/nicolefinnie/iot-nodejs-tutorial 以下是实现与 IBM IoT 平台连接在一起的 4 个 R

爱奇艺、优酷、腾讯视频竞品分析报告2016(一)

1 背景 1.1 行业背景 1.1.1 移动端网民规模过半,使用时长份额超PC端 2016年1月22日,中国互联网络信息中心 (CNNIC)发布第37次<中国互联网络发展状况统计报告>,报告显示,网民的上网设备正在向手机端集中,手机成为拉动网民规模增长的主要因素.截至2015年12月,我国手机网民规模达6.20亿,有90.1%的网民通过手机上网. 图 1  2013Q1~2015Q3在线视频移动端和PC端有效使用时长份额对比 根据艾瑞网民行为监测系统iUserTracker及mUserTrac

China Operating System 电脑操作系统 2016全球互联网排名

韩梦飞沙  韩亚飞  [email protected]  yue31313  han_meng_fei_sha 电脑操作系统 China Operating System 2016全球互联网排名 ========

在vSphere环境下简单测试Windows 2016 S2D (1)

伴随这两年SDDC(软件定义的数据中心)越来越热,作为其中重要的建设区块的软件定义存储(SDS)也越来越多地被各行业,各类规模的数据中心所使用.作为SDS厂商之一的微软,面对这块蛋糕当然不甘人后,从Windows Server 2012开始,微软隆重推出了他的SDS解决方案--Storage Space.该版本还是需要建立在共享磁盘柜(JBOD)的基础上,和其他主流SDS厂商一样,其目的是通过将JBOD里各类磁盘加入到一个或多个存储池,再从存储池里划分存储空间(Storage Space)给单台

2016年度总结

2016年度总结 四季交替,冬去春来,不知不觉间,2016年又过去了.2016年是平静的一年,也是充满故事的一年. 16年6月之前,我的生活和15年一样,在保税区机房昼夜交替值班.身体依然上火严重,睡眠和饮食质量依然不佳.上班处理服务器硬件故障.搜集服务器故障日志.巡检.上下架服务器.拉网线光纤线.登记更新各种表格信息.下班睡觉.爬山.跑步.做仰卧起坐.每个月的生活几乎一样,唯一在变的是一去不复返的时光.      16年6月 ,我调岗了.由原来的机房值班岗位,调岗到公司总部开始了周一到周五每天

我的2016,我的盲路

转眼2016已经过去明天就是除夕了,坐在家里的火炕上看完正在追的剧半夜倾城,觉得心里一阵空虚明天我就23了,人能生有多少个23呢,回忆着过去的一年突然想写这篇文章总结一下过去的自己. 记得2016年刚开学的时候,我给自己定下了三个目标,第一,一定要拿下驾照,第二,大学英语怎么也得过四级的,第三就是希望可以拿下软考的中级,如今这三个目标我完成了俩唯一的遗憾就是软考没有过,我的大学是一个民办的三本,自从上大学以后我就觉得特别的丢人家里是东北的别人一问你是哪个学校的我就感觉内心极度的自卑,好在学了个我