一,原理和定义
(1). 包含和文件包含漏洞
包含:开发人员通常会把重复使用的函数写到单个文件中,使用时直接调用此文件,而无需再次编写,这种调用文件的过程一般称为包含。
- 服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码,并且当PHP来执行,这会为开发者节省大量的时间。这意味着您可以创建供所有网页引用的标准页眉或菜单文件。当页眉需要更新时,您只更新一个包含文件就可以了,或者当您向网站添加一张新页面时,仅仅需要修改一下菜单文件(而不是更新所有网页中的链接)。
为什么会造成文件包含漏洞:因为将被包含的文件设置为变量,用来进行动态调用。正是这种灵活性, 从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
- 文件包含函数的参数没有经过过滤,可以被攻击者控制,包含其他恶意文件,导致了执行恶意的代码。
(2)PHP中文件包含的函数
PHP中文件包含的函数:
- include():找不到被包含文件,报错,但会继续运行脚本;
.- include_once():与include()类似,区别在于,当重复调用同一文件时,程序只调用一次;
.- require():找不到被包含文件,报错,并且停止运行脚本;
.- require_once() :与require类似,区别在于,当重复调用同一文件时,程序只调用一次;
.
include_once()
和require_once()
这两个函数只包含一次,适用于在脚本执行期想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
当使用这四个函数包含一个新的文件时,该文件将作为PHP代码执行,PHP内核并不会在意该包含的文件是什么类型。(无论是txt、图片文件,远程URL,全都作为PHP代码执行)
不管文件后缀是否是php,都会尝试当做php文件执行,如果文件内容为php则会正常执行并返回结果,如果不是,则会原封不动地打印文件内容,所以文件包含漏洞常常会导致任意文件读取与任意命令执行;
.
①测试非php文件是否打印内容
②测试php文件是否解析成功并执行
(3)文件包含的特征
URL中出现以下参数时,联想到文件包含
?page=
.
?file=
.
?home=
(4)要想成功利漏洞,需的条件
- 1. included等函数通过动态变量的方式引入需要包含的文件;
- 2. 用户能够控制该动态变量.
- 3. 被包含的文件可被访问
(5)本地文件包含
能够打开并包含本地文件的漏洞,被称为本地文件包含漏洞( Local file inclusion,简称LFI).比如下面这段代码,就存在LFI漏洞.
(6)远程文件包含
如果PHP的配置选项
allow url include
为ON的话,则 include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含漏洞( Remote File Inclusion,简称RFⅠ)。如果远程文件没经过严格的过滤,导致了执行恶意文件的代码,这就是远程文件包含漏洞。
允许远程文件包含的配置文件修改内容
allow_url_fopen
= On(是否允许打开远程文件)allow_url_include
= On(是否允许include/require远程文件)
二,常用的本地文件绝对路径
这些路径不是绝对的!!!
Windows系统
c:\boot.ini // 查看系统版本
C:\Windows\System32\config\sam // 存储Windows系统初次安装的密码
c:\ProgramFiles\mysql\my.ini // MySQL配置
c:\ProgramFiles\mysql\data\mysql\user.MYD // MySQL root密码
c:\windows\php.ini // php 配置信息
Linux/Unix系统
/etc/passwd // 账户信息
/etc/shadow // 账户密码文件
/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件
/etc/resolv.conf
/root/.ssh/known_hosts
/usr/local/app/php5/lib/php.ini // PHP相关配置
/etc/httpd/conf/httpd.conf // Apache配置文件
/etc/my.conf // mysql 配置文件
可以写入字典,爆破可返回包的长度来爆破站点的路径
三,漏洞利用方式
(1) 日志文件包含
【前提】
- 知道日志文件的绝对路径(可以通过文件包含漏洞对路径爆破)
【exp】
①构造含有php代码的URL(将php代码上传到日志文件)
由于浏览器会自动转码,导致上传到日志文件的内容不是正规的php代码
.②修改为php代码格式发送
.③包含日志
四,利用PHP伪协议
PHP 带有很多内置 URL 风格的封装协议,可以利用http协议(GET,POST传数据)
File:// 访问本地文件系统
http:// 访问 HTTPs 网址
ftp:// 访 问 ftp URL
php:// 访问输入输出流
Zlib:// 压缩流
data:// 控制输入流数据
input:// 利用POST方式传数据
filter:// 用于本地磁盘文件进行读取
(1)file:// -----读取文件内容
使用条件
- ①PHP版本大于等于5.2
- ②
allow_url_fopen: off/on
&&allow_url_include: off/on
exp时的作用
- ①读取文件内容
- ②可以读取非网页根目录的内容
(2)php://input伪协议
使用条件
- ①PHP版本大于等于5.2
- ②
allow_url_fopen: off/on
&&allow_url_include: on
exp时的作用
- ①可以POST方式传参数
- ②可以写入木马文件
- ③可以在目标上完成命令执行
【实列】
【实验环境:php版本为5.4.45,开启include,apache,Windows】①通过burp suite抓包修改请求方式,传入探针
②通过php函数执行系统命令
③写入木马文件
<?PHP fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd])?>');?>
(3)data://
使用条件
- ①PHP版本大于等于5.2
- ②
allow_url_fopen: on
&&allow_url_include: on
exp时的作用
- 将原本的包含文件流重定向到了用户可控制的输入流中,简单来说就是执行文件的包含方法包含了你的输入流,通过你输入payload来实现目的
- 重定向显示探针等作用
协议介绍
- 数据流封装器
text/html和text/plain的区别
①
text/html
的意思是将文件的content-type设置为text/html的形式,浏览器在获取到这种文件时会自动调用html的解析器对文件进行相应的处理。②
text/plain
的意思是将文件设置为纯文本的形式,浏览器在获取到这种文件时并不会对其进行处理。
(4)php://filter(本地磁盘文件进行读取)
使用条件
- ①PHP版本大于等于5.2
- ②
allow_url_fopen: on/Off
&&allow_url_include: on/Off
exp时的作用
- ①读取重要配置文件(file读不了时),要结合file伪协议
- ②重写配置文件
协议介绍
- 元封装器,设计用于”数据流打开”时的”筛选过滤对本地磁盘文件进行读写。
参数说明 ----->
=php://filter/read=convert.base64-encode/resource=XXXXX
名称 | 描述 |
---|---|
resource | 这个参数必须有,指定操作的数据流 |
read=XXX(读) | 参数可选,指定过滤器名称 |
write=XXX(写) | 参数可选,指定过滤器名称 |
【实列】
【实验环境:php版本位5.4.45,开启include,apache,Windows】
.
①用file读取不了配置文件
.
②结合file和filter
http://192.168.44.131/dvwa/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=file://C:\phpStudy\PHPTutorial\php\php-5.4.45\php.ini
.
③解码查看配置文件
(5)phar://
php解压缩包的一个函数,不管后缀是什么,都会当做压缩包来解压。
.
用法:?file=phar://压缩包/内部文件 phar://xxx.png/shell.php 注意: PHP > =5.3.0 压缩包需要是zip协议压缩,rar不行,
.
将木马文件压缩后,改为其他任意格式的文件都可以正常使用。
.
步骤: 写一个一句话木马文件shell.php,然后用zip协议压缩为shell.zip,然后将后缀改为png等其他格式。
(6)zip://伪协议
zip伪协议和phar协议类似,但是用法不一样。
.
用法:?file=zip://[压缩文件绝对路径]#[压缩文件内的子文件名] zip://xxx.png#shell.php。
.
条件: PHP > =5.3.0,注意在windows下测试要5.3.0<PHP<5.4 才可以
.
#在浏览器中要编码为%23,否则浏览器默认不会传输特殊字符。
优秀文章
伪协议的总结
??若服务器配置了RASP,则无法利用伪协议
五,文件包含漏洞防护措施
1. 包含文件的参数过滤
- ① 文件名过滤:白名单或者黑名单过滤;
- ②不使用动态变量进行包含操作,设置字典等静态处理。
- ③文件名后缀固定
.
2、路径限制
①目录限制,在用户提交的变量前增加固定的路径,限制用户可调用的目录范围;
②目录回退符过滤,避免回退符生效导致路径变化;
.
3、中间件的安全配置
- ①PHP版本小于5.4在php.ini中设置
magic_quotes_gpc=on
(5.4 以后被放弃用)magic_quotes_gpc设置是否自动为GPC(get,post,cookie)传来的数据中的’"\加上反斜线。
- ②限制访问区域:php.ini 中设置
open_basedir
来限制用户访问文件的活动范围等;apache 也有相关配置- ③设置访问权限:限制当前中间件所在用户的访问权限,例如;web 服务器独立用户,并且只拥有访问目录和使用中间件的权限,从而有效避免越权访问其他文件;
.
4.搭建RASP阻止代码注执行
六,几种简单的绕过方法
(1)针对回退符过滤绕过
—☞目录回退符过滤,避免回退符生效导致路径变化
<?php
function filter($str)
{
$str = str_replace("..","",$str);
$str = str_replace(".","",$str);
$str = str_replace("/","",$str);
$str = str_replace("\\","",$str); return $str;
}
$file = $_GET['file'];
$file = filter($file); if($file){
include('/var/www/html/'.$file);
}
?>
无法根本解决,可以通过复写绕过!!!!!
(2)文件名后缀固定绕过
【源码】
<?php
$filename = $_GET['filename'];
include($filename . ".html");
?>
【注意】
这里的设计思路是固定后缀名,但不会影响进行包含操作的函数的解析情况!
①查看源码固定了后缀
.
②测试
【绕过方法】
①%00截断
条件:
magic_quotes_gpc = Off
- php版本<5.3.4
②路径长度截断
【原理】
Windows下目录最大长度为256字节,超出的部分会被丢弃;
.
Linux下目录最大长度为4096字节,超出的部分会被丢弃。
payload
http://192.168.44.131/dvwa/vulnerabilities/fi/?page=a.php/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././.
③? %23
④根据错误信息上传固定后缀的文件绕过
上传a.html文件