参考:
https://www.cnblogs.com/0daybug/p/12365559.html
https://www.jianshu.com/p/0cc01ee0d247
简介
程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这中文件调用的过程一般被称为文件包含。
程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但正是由于这种灵活性,从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。
几乎所有脚本语言都会提供文件包含的功能,但文件包含漏洞在PHP Web Application中居多,而在JSP、ASP、ASP.NET程序中却非常少,甚至没有,这是有些语言设计的弊端。
在PHP中经常出现包含漏洞,但这并不意味这其他语言不存在。
常见文件包含函数
1 | include():执行到include时才包含文件,找不到被包含文件时只会产生警告,脚本将继续执行 |
利用条件
- 程序用include()等文件包含函数通过动态变量的范式引入需要包含的文件
- 用户能够控制该动态变量
注意:PHP中只要文件内容符合PHP语法规范,包含时不管扩展名是什么都会被PHP解析,若文件内容不符合PHP语法规范则会暴漏其源码。包含不存在的文件则可能暴露路径
漏洞危害
- 执行任意代码
- 读取文件源码或敏感信息
- 包含恶意文件控制网站
- 甚至控制服务器
漏洞分类
本地文件包含:可以包含本地文件,在条件允许时甚至能执行代码
- 读敏感文件,读PHP文件
- 包含日志文件GetShell
- 上传图片马,然后包含从而GetShell
- 包含/proc/self/envion文件GetShell
- 包含data:或php://input等伪协议
- 若有phpinfo则可以包含临时文件
远程文件包含:可以直接执行任意代码
- 要保证php.ini中allow_url_fopen和allow_url_include要为On
常见的敏感路径
- Windows
C:\boot.ini //查看系统版本
C:\windows\system32\inetsrv\MetaBase.xml //IIS 配置文件
C:\windows\repair\sam //存储 windows 系统初次安装的密码
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 配置文件
- UNIX/Linux
/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 配置文件
常用的伪协议
- php://filter
利用条件:
只是读取,所以只需要开启allow_url_fopen,对allow_url_include不做要求
用法:
1 | index.php?file=php://filter/read=convert.base64-encode/resource=xxx.php |
通过指定末尾文件,可以读取经base64加密后的文件源码,虽然不能直接获取shell等,但能够读取敏感文件,危害还是是挺大的。
- php://input
可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行
利用条件:
需要开启allow_url_include=on,对allow_url_fopen不做要求
用法:?file=php://input 数据利用POST传过去。
- zip://伪协议
zip://可以访问压缩文件中的文件
条件: 使用zip协议,需要将#编码为%23,所以需要PHP 的版本> =5.3.0,要是因为版本的问题无法将#编码成%23,可以手动把#改成%23。
用法:?file=zip://[压缩文件路径]#[压缩文件内的子文件名] zip://xxx.png#shell.php
- phar://伪协议
与zip://协议类似,但用法不同,zip://伪协议中是用#把压缩文件路径和压缩文件的子文件名隔开,而phar://伪协议中是用/把压缩文件路径和压缩文件的子文件名隔开,即?file=phar://[压缩文件路径]/[压缩文件内的子文件名]
- data:text/plain
和php伪协议的input类似,也可以执行任意代码,但利用条件和用法不同
条件:allow_url_fopen参数与allow_url_include都需开启
用法1:?file=data:text/plain,<?php 执行内容 ?>
用法2:?file=data:text/plain;base64,编码后的php代码
- file://伪协议
file:// 用于访问本地文件系统,且不受allow_url_fopen与allow_url_include的影响。
用法:?file=file://文件绝对路径
常见的容易造成命令执行的函数和命令连接符
- exec():不输出结果,返回最后一行shell结果
- system():输出并返回最后一行shell结果
- popen():不会直接返回执行结果,而是返回一个文件指针
- passthru():调用命令,把命令的运行结果原样返回,直接输出到标准输出设备上,常用在所执行的Linux命令输出二进制数据时
- proc_open():不直接返回执行结果,而是返回一个文件指针
- pcntl_exec():执行发生错误时返回FALSE,无错误时不返回
- shell_exec():将完整的输出以字符串的方式返回
- ;
- |
- &
- %0a
- ``
命令执行的防护
- escapeshellarg():给字符串增加一个单引号且能引用或者转码任何已经存在的单引号,以确保能够直接将一个字符串传入shell函数,并且还是确保安全的
- escapeshellcmd():对字符串中可能会欺骗shell命令执行任意命令的字符进行转义,保证用户输入的数据在传送到exec()或system()函数或执行操作符前进行转义
- 黑名单(过滤特殊字符或者替换字符)