文件包含漏洞详解:原理、危害与防护
文件包含漏洞详解:原理、危害与防护
文件包含漏洞是Web安全领域一个重要的漏洞类型,主要发生在PHP等服务器端脚本语言中。本文将详细介绍文件包含的概念、文件包含漏洞的原理和危害,以及如何利用PHP伪协议进行攻击。通过本文的学习,读者可以更好地理解这一漏洞类型,并采取相应的防护措施。
一.什么是文件包含
文件包含是指在PHP中引入其他文件的过程,文件包含可以用于引入其他PHP文件、HTML文件、文本文件等。被引入的文件可以包含变量、函数、类等内容,被引入文件中的代码可以在主文件中使用。
文件包含可简化重复性代码编写,开发人员通常会将重复使用的函数写入到单个文件中,在使用某些函数时直接调用此函数,无需再次编写,如下所示将数据库登录信息写入到单个文件中,调用数据库登录信息文件的过程称为文件包含。
演示案例:
文件b.php中的代码在文件a.php中执行
#b.php
<?php
echo "hacker";
?>
#a.php
<?php
include('b.php');
echo "Hello World"
?>
PHP中常见的文件包含函数
include():用于将指定文件包含到当前文件中,如果包含失败,会发出一个警告。
require():用法与include()类似,但如果包含失败,会产生一个致命错误,脚本会停止执行。
include_once():与include()类似,但只会包含一次文件,即使多次调用也不会重复包含。
require_once():与require()类似,但只会包含一次文件,即使多次调用也不会重复包含。
二.什么是文件包含漏洞
文件包含漏洞利用文件包含的特性在单个文件中写入恶意代码,利用服务器的文件包含功能加载和执行这些代码。这样做可能会导致攻击者能够执行任意操作,包括读取、修改或删除服务器上的文件,甚至获取对服务器的完全控制权。
本地文件包含漏洞:
当用户发起一个前端的请求时,便会将请求的这个文件的值(如文件名称)传递到后台,后台再执行其对应的文件。在这个过程中,如果后台没有对前端传递进来的值进行安全校验,则攻击者可能会通过“../”这样的手段让后台打开或执行其它一些文件,从而导致后他服务器上其它目录的文件结果被遍历出来,形成目录遍历漏洞。
演示案例:
远程文件包含漏洞
攻击者可以通过构造恶意的URL参数来包含一个远程文件,从而执行任意的代码。例如,攻击者可以构造一个带有木马的服务器的URL,让被攻击者的服务器包含该URL即访问该URL,木马服务器回显给被攻击者服务器一个木马脚本(如一句话木马生成脚本),被攻击者的服务器执行该木马生成脚本就会在本地的服务器生成木马文件。
利用该漏洞需要本地服务器有如下配置(PHP服务为例):
allow_url_include:开启 magic_quotes_gpc 关闭
演示案例
下面是演示靶场的正常页面和文件包含漏洞靶场的配置文件
案例 1:无安全校验
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
?>
当后端程序未对用户输入的内容进行过滤时,攻击者就可在URL中输入恶意的参数(如在page参数中输入恶意网站URL)服务器收到后会解析参数并将结果回显给前端页面,如下所示利用该漏洞成功访问百度网页。
案例2--初级校验:
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\\" ), "", $file );
?>
案例3--高级校验:
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>
双写绕过:
案例4--无懈可击:
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Only allow include.php or file{1..3}.php
if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>
三.什么是PHP伪协议
PHP伪协议详解
PHP伪协议是指一种特殊的协议格式,用于在PHP中访问和操作各种资源,如文件、网络资源、数据库等。通常,PHP伪协议以特定的协议前缀开始,并通过URL的形式指定具体的资源路径或参数。
常见的PHP伪协议包括:
file://:用于读取本地文件系统上的文件。
http://和https://:用于访问网络上的文件或资源。
ftp://:用于通过FTP协议访问远程文件。
data://:用于将数据直接嵌入到代码中,而不必从外部文件读取。
php://input:用于读取通过POST请求传递的原始流数据。
php://output:用于将输出内容直接发送到浏览器。
使用PHP伪协议可以在不直接打开文件或连接资源的情况下,通过简单的URL形式进行读取、写入、上传、下载等操作,为PHP开发者提供了便利和灵活性。然而,使用PHP伪协议也需要注意安全性,避免被恶意利用。
演示案例:php://input
演示文件:include,php
<?php
include('flag.php');
$a = $_GET["a"];
if(isset($a)&&(file_get_contents($a,'r')) === 'I want flag'){
echo "success\n";
echo $flag;
}else {
die('no no no ');
}
注释:在PHP中,file_get_contents()函数用于获取指定文件的内容,并将其作为字符串返回。
file_get_contents()函数中的可接收两种参数:1.文件名 2.流数据
演示文件按:flag.pjp
<?php
echo "能否在本地查询到文件名:";
$flag = 'flag{测试成功}';
?>
这段PHP代码的主要作用是尝试从一个外部输入(通过GET请求的参数
a
)中获取查询的文件名,通过file_get_contents()函数获取本地“a”文件的内容并检查这个内容是否严格等于字符串
'I want flag'
。如果条件满足,它会输出一个成功消息
"success\n"
,并显示一个名为
$flag
的变量的内容,这个变量在代码的开始部分通过
include('flag.php');
语句被包含进来。如果条件不满足,它会输出
'no no no '
并终止脚本的执行。
在这个案例中如果本地含有文件“a”并且内容是“
I want flag
”,输出成功下消息;如果本地没有文件“a” 我们又想要输出结果是success,则需要用到php://input伪协议;
我们使用BurpSuit将POST请求的内容改为PHP代码比对的内容“I want flag”,伪协议php://input读取POST请求传递的原始流数据“I want flag”并且传递给file_get_contents()函数,该读取流数据“I want flag”进行一个比对,最后成功输出success。