freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

由一个萌妹子引发的CTF Writeup
2019-03-11 09:00:47
所属地 北京

前言

前几天在刷 CTF 题的时候遇到一个比较有意思的题,题目本身难度一般,但是涉及到的几个点还是值得记录一下的,于是便有了此文。

不一样的图片加载方式

题目给出的 URL 链接形式为:http://www.XXXX.com/index.php?jpg=hh.jpg浏览器打开显示动漫美少女图片。

通过查看源码发现图片是以 base64 编码的方式载入的

对于不需要更新内容的图片来说,可以直接将文件内容以 base64 编码的方式写入到网页文件中,这样做的好处是节省了一个 HTTP 请求。当然对于本题来说肯定不是为了这个目的。

文件读取漏洞

通过 URL 的链接形式和源码返回内容我们可以猜测一下后端的实现过程:

首先,通过 jpg 参数接收 hh.jpg 值定位到硬盘上的图片文件;

然后,将图片内容读取出来进行 base64 编码;

最后,输出到返回文件中。

如果我们猜测没错的话,这里面存在一个文件读取的过程,读取的文件通过 jpg 参数控制,这里如果 jpg 的参数值没有进行过滤限制,就可能存在任意文件读取漏洞。为了验证漏洞,我们尝试读取 index.php 文件。构造链接:

http://www.XXXX.com/index.php?jpg=index.php

果然返回了 index.php 的 base64 编码内容  

进行 base64 解码后的内容:

从 index.php 源码中也验证了我们刚才猜测的处理过程。

两个疑点

index.php 源码内容里面有两个比较可疑的点。

1、 注释内容,CTF 题目中通常会采用注释作为一种提示手段,说明注释内容中有解题的关键点。

2、 对 file 变量的值进行了正则和字符串替换。

针对疑点一

注释里面有两个时间和一个版权信息,时间通常和密码有关,目前没发现密码相关的地方,所以先从版权信息入手,查一下 PhpStorm。通过搜索得知 PhpStorm 是一个 php 的集成开发软件,在通过它创建项目时会自动创建一个.idea 文件夹,在该文件夹下面存在项目的一些配置文件,尝试访问其中的 workspace.xml 

这里面出现了 fl3g_ichuqiu.php 和 config.php 两个新文件。其中 fl3g_ichuqiu.php 文件应该就是我们获取 flag 的关键文件。我们可以利用文件读取漏洞去读取该文件。

针对疑点二

当我们看到 fl3g_ichuqiu.php 和 config.php 这两个文件的名字的时候,疑点二里面的两个过滤语句的目的就比较明显了。

根据可疑点 2 中的正则替换的目的,就是不希望我们构造http://www.XXXX.com/index.php?jpg=fl3g_ichuqiu.php来读取 fl3g_ichuqiu.php 中的内容,因为 fl3g_ichuqiu.php 中的」_」不属于 [a-zA-Z0-9],会被替换为空。而第二个字符串过滤的目的,是不希望我们直接读取 config.php 文件,这里面明显存在关键信息。

但是我们正好可以利用」config」替换 fl3g_ichuqiu.php 中的」_」, 来绕过正则对「_」的过滤。构造http://www.XXXX.com/index.php?jpg=fl3gconfigichuqiu.php。来读取 fl3g_ichuqiu.php 的内容。

一个加解密算法

fl3g_ichuqiu.php 解码后的内容如下:

这是一个加解密函数,得到 flag 的关键是计算出「system」的加密值。已知条件是「guest」的加密值。关键是得到 key,可以看出 key 是在 config.php 文件里面定义的,而因为字符串过滤条件,我们没有办法直接读取 config.php 文件,只能利用加解密函数算出结果。

分析加密函数如下:

1、 先将待加密字符串 txt 的每位对应的 ascii 值加 10,转换为新的字符串。

2、 取随机 4 位由大小写字母或数字组成的 rnd 与参数 key 拼接,取 md5 作为加密 key

3、 将待加密字符串与加密 key 的前 n 位(n 为 txt 的长度)进行按位异或得到 ttmp

4、 将 rnd 与 ttmp 拼接进行 base64 编码获得加密后的值。

根据加密函数的算法和已知的 guest 加密对,我们可以算出 rnd 的值和加密 key 的前 5(guest 字符串的长度)位,而我们要获得 system 的加密值,需要知道 rnd 和 key 的前 6(system 的长度)位,因此需要对加密 key 的第 6 位进行爆破。

具体爆破脚本如下: 

编码的坑

然而在爆破脚本运行之后结果却是比较失望 

并没有如期获取到 flag,接下来就是漫长的调试和分析问题。

首先验证 python 脚本的加密算法是否存在问题,利用固定的 key 值(998771)和 rnd 值(suNF)对「system」进行加密,加密结果与用相同的 key 值和 rnd 值的原始 php 加密函数结果进行对比,发现结果果然存在差异。

Php 运行结果为:c3VORkS6RUlYRg==

Python 结果为:c3VORkTCukVJWEY=

在 base64 中「=」用于补位,两个结果中的补位符不同,说明 base64 编码前的二进制字节数不同。我们回到 base64 编码前的内容看看到底是什么?

 如图中,编码的内容是 rnd+ttmp,分别用 php 和 python 输出 rnd+ttmp 的内容如下:

Php 结果:suNFDºEIXF

Python 结果:b'suNFD\xc2\xbaEIXF'

这个结果差异很明显,在 php 中显示为字符的「º」在 python 中被编码为两个字节。这也就是为什么 php 中的 base64 编码结果需要 2 个字节补位,而 python 结果中只需要一个,这里 python 多出了一个字节。

这里的主要原因是在 python 中我们对字符进行了 utf-8 的编码方式,「º」字符的十进制数为 186,大于 127,在 utf-8 中会被编为两个字节。而 php 中应该是采用了单字节的编码方式,导致了差异的产生,知道了差异在哪里,就很好解决了,我们在 python 中将 utf-8 换成 latin-1 后运行脚本。

成功获得了 Flag。

总结

题目虽然没有涉及太深的技术,但是确实涵盖了一些 CTF 中的基本考察点。

 图片的 base64 编码方式

 常规的文件读取漏洞

 集成环境的信息泄露问题

 正则和字符串的过滤绕过

 加解密逆向

 爆破的思想

 不同字符编码的问题(这个应该是个意外)

*本文作者:京东安全,转载请注明来自FreeBuf.COM

# CTF # 萌妹子
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者