## 漏洞概述 ### SSI 简介 SSI(Server Side Includes,服务端包含)是 Apache 通过 `mod_include` 模块提供的一项服务端模板功能。当用户访问 `.shtml` 后缀的文件时,Apache 会在响应前解析文件中的 SSI 指令并替换为动态内容。 SSI 设计初衷是在纯 HTML 中嵌入简单的动态逻辑(如页眉页脚包含、文件修改日期),但其 `#exec` 指令可以直接执行系统命令——当攻击者能将恶意 `.shtml` 文件写入启用了 SSI 的目录时,即可实现远程命令执行。 ### 漏洞信息 | 项目 | 内容 | | -------- | --------------------------------------------------------------------------- | | 漏洞类型 | 文件上传限制绕过 + SSI 远程命令执行 | | 根因 | 上传检测仅屏蔽`.php` 未屏蔽 `.shtml`,且上传目录启用了 `Includes` 选项 | | 影响范围 | Apache 2.x +`mod_include` 模块启用 + 文件上传点未校验 `.shtml` | | 利用条件 | 1) 存在文件上传点;2) 上传目录允许 SSI 解析;3)`mod_include` 未限制 `#exec` | | 复现环境 | Apache 支持 SSI 与 CGI 的 Docker 靶场 | | 靶机 | http://192.168.50.134:8080/upload.php | ### 漏洞原理 #### mod_include 工作原理 Apache 处理请求时,如果文件后缀为 `.shtml`(或通过 `AddHandler` / `AddType` 配置的任意后缀),`mod_include` 模块会介入 HTML 输出流,逐行扫描并解析以下格式的指令: ```html ``` #### 攻击链 ``` 攻击者上传 .shtml 文件 │ ▼ ┌──────────────────────────────────┐ │ POST /upload.php │ │ 上传 shell.shtml │ │ 内容: │ │ 扩展名白名单绕过(仅封.php) │ └──────────────┬───────────────────┘ │ ▼ ┌──────────────────────────────────┐ │ 文件保存至 uploads/ 目录 │ │ Apache 配置: Options +Includes │ │ 该目录启用 SSI 解析 │ └──────────────┬───────────────────┘ │ ▼ ┌──────────────────────────────────┐ │ 攻击者访问 │ │ /uploads/shell.shtml │ └──────────────┬───────────────────┘ │ ▼ ┌──────────────────────────────────┐ │ mod_include 解析 SSI 指令 │ │ │ │ → shell_exec("id") │ │ → 输出插入响应体中 │ └──────────────┬───────────────────┘ │ ▼ 命令执行结果回显 ``` #### 为什么这不被视为 Apache 漏洞 SSI 是 Apache 的**文档化功能**,而非安全缺陷。`#exec` 指令在以下条件下是合法功能: - 被授权管理员主动启用 - 用于受控的内部服务器环境 实际上这属于**配置不当(Misconfiguration)**导致的安全问题——管理员同时开放了文件上传和 SSI 执行能力,且未充分限制上传文件类型。 --- ## 环境搭建 启动一个同时支持 SSI(`mod_include`)和 CGI 的 Apache 靶场容器。 核心 Apache 配置(靶场中的不安全配置): ```apache DocumentRoot /var/www/html # 为 .shtml 文件启用 SSI 解析 AddType text/html .shtml AddHandler server-parsed .shtml Options +Includes # ← 允许 #exec cmd 指令 ``` | 配置项 | 安全选项 | 不安全选项(靶场) | | --------- | ------------------------ | --------------------------- | | `Options` | `IncludesNOEXEC` | `+Includes` | | 含义 | 允许 SSI 但不允许`#exec` | 允许完整 SSI,含`#exec cmd` | > 靶机地址:http://192.168.50.134:8080/upload.php --- ## 漏洞复现 ### Step 1: 探测上传限制 访问 `http://192.168.50.134:8080/upload.php`,可看到一个文件上传表单。直接上传 `.php` 文件被拒绝,但 `.shtml` 文件不受限制: ```html ```  ### Step 2: 构造恶意 .shtml 文件 ```html ``` **payload 结构说明:** | 组成部分 | 说明 | | ----------- | ---------------------------------------- | | `` | SSI 指令结束标记,标准 HTML 注释语法包裹 | ### Step 3: 访问上传文件触发执行 上传成功后,直接访问该 `.shtml` 文件的 URL,Apache 会解析其中的 SSI 指令并执行命令: ``` http://192.168.50.134:8080/uploads/shell.shtml ```  --- ## SSI 指令完全参考 ### 核心指令速查 | 指令 | 语法 | 说明 | 风险等级 | | ------------------ | ------------------------------------------ | ------------------------------ | -------- | | `#exec cmd` | `` | 执行系统命令并输出结果 | **严重** | | `#exec cgi` | `` | 执行 CGI 程序 | **严重** | | `#include virtual` | `` | 包含服务器本地文件(绝对路径) | **高** | | `#include file` | `` | 包含相对路径文件 | **高** | | `#echo var` | `` | 输出服务器环境变量 | 中 | | `#fsize` | `` | 输出文件大小 | 低 | | `#flastmod` | `` | 输出文件修改时间 | 低 | | `#config` | `` | 配置日期格式 | 无 | | `#printenv` | `` | 打印所有环境变量 | 中 | | `#set` | `` | 设置变量 | 低 | ### 常用攻击 Payload ```html ``` ### 利用条件判断 并非所有 `.shtml` 文件都会触发 SSI 解析,需要满足以下任一条件: 1. 文件后缀为 `.shtml`(Apache 默认配置) 2. Apache 配置了 `AddHandler server-parsed .html`(所有 `.html` 也解析 SSI) 3. Apache 配置了 `XBitHack on`(有执行权限的文件自动启用 SSI) 4. 目录配置了 `Options +Includes` 或 `Options +IncludesNOEXEC` 可通过以下方式探测 SSI 是否启用: ```html ``` --- ## 延伸阅读 ### 浏览器端 vs 服务器端 SSI | 对比维度 | 客户端 SSI | 服务端 SSI (mod_include) | | ---------- | ------------------------- | ---------------------------- | | 注释语法 | `` | `` | | 解析位置 | 浏览器(如旧版 IE) | Apache 服务器 | | 代码可见性 | F12 可见源码 | 不可见(HTML 中已替换) | | 风险 | 无(浏览器无 shell 权限) | **高(服务器级别命令执行)** | | 实际场景 | 几乎已绝迹 | 遗留系统 / 托管平台 | ### 类似攻击手法对比 | 攻击方式 | 上传后缀 | 解析组件 | 利用效果 | | -------------- | ----------------- | ------------- | -------------------- | | **SSI 注入** | `.shtml` | `mod_include` | `#exec cmd` 命令执行 | | PHP 上传 | `.php` / `.phtml` | `mod_php` | PHP 代码执行 | | CGI 上传 | `.cgi` / `.pl` | `mod_cgi` | Perl/Shell 脚本执行 | | JSP 上传 | `.jsp` / `.jspx` | Tomcat | Java 代码执行 | | .htaccess 覆盖 | `.htaccess` | Apache Core | 修改服务器配置 | ### 修复与加固建议 #### 1. 使用 IncludesNOEXEC 替代 Includes ```apache # 错误配置: Options +Includes # ← 允许 #exec cmd,危险! # 正确配置: Options +IncludesNOEXEC # ← 允许 SSI 但禁用 #exec ``` #### 2. 禁用不必要的 mod_include 模块 ```bash # 检查是否加载了 mod_include apachectl -M | grep include # 卸载模块 sudo a2dismod include sudo systemctl restart apache2 ``` #### 3. 文件上传白名单校验 ```php // 推荐:白名单方式,只允许确需的扩展名 $allowed = ['jpg', 'jpeg', 'png', 'gif', 'pdf']; $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); if (!in_array($ext, $allowed)) { die("不允许的文件类型"); } // 危险:黑名单方式,极易被遗漏扩展名绕过 $blocked = ['php', 'php5', 'phtml']; // ← 漏了 .shtml! if (in_array($ext, $blocked)) { die("不允许的文件类型"); } ``` #### 4. 上传目录独立配置 上传文件应当存放在**独立的静态资源目录**中,该目录不应启用任何服务端脚本解析: ```apache # 移除所有 Handler RemoveHandler .shtml .html .php .phtml .cgi .pl # 设置默认 MIME 类型 ForceType application/octet-stream # 禁用所有脚本执行选项 Options -ExecCGI -Includes -Indexes ``` #### 5. 内容安全检测 对上传文件内容进行扫描,拦截包含 SSI 指令特征的文件: ```python # 简易检测脚本 ssi_patterns = [ r'