文件包含漏洞

文件包含概述

文件包含漏洞主要出现在PHP和JSP应用中,应用在运行过程中动态加载其他脚本文件,且加载的文件路径由外部输入变量控制。

文件包含漏洞分为两类本地文件包含(Local File Inclusion)远程文件包含(Remote File Inclusion)

以PHP为例,常用的文件包含函数有以下四种
require():找不到被包含的文件会产生致命错误,并停止脚本运行
include():找不到被包含的文件只会产生警告,脚本继续执行
**require_once()**与require()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
**include_once()**与include()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含

路径穿越

在文件系统中,通过“…/”可以访问上一级目录。路径穿越是指用户通过这种方式访问应用程序预期之外的目录。例如,假设download.php实现文件下载功能,代码如下:

<?php
$filename = $_GET['filename'];
echo file_get_contents("files/$filename");

如果攻击者提交如下请求:

/download.php?filename=../../../../../etc/passwd

应用程序将返回/etc/passwd文件的内容。这种攻击叫作“路径穿越攻击”或“目录穿越攻击”,也叫“任意文件读取”漏洞。

(如果应用程序拼接了文件后缀名,也可以通过“\0”字符截断后缀名)


常见攻击手段

最常见的路径穿越攻击就是读取任意文件,攻击者可以读取应用程序中包含敏感数据的配置文件或源代码。

另一种常见的路径穿越攻击是执行代码,例如:

<?php
$template = 'blue.php';

if (isset($_COOKIE['TEMPLATE']))
    $template = $_COOKIE['TEMPLATE'];
include("/home/users/phpguru/templates/" . $template);

攻击者事先上传包含PHP代码的图像文件,然后通过路径穿越让应用程序通过include()函数载入文件,实现任意代码执行。


防御配置要点

一些开发者在防御路径穿越攻击时,只是简单判断用户传入的文件名或路径中是否存在..

但在应用程序没有做目录拼接的情况下,如果用户传入的文件名是以“/”开头的,将直接穿越到根目录,因此仍然存在“任意文件读取”漏洞。

在nginx中,如果配置不正确,也存在路径穿越漏洞。例如,在如下配置中:

location /i {
    alias /data/w3/images/;
}

当用户访问/i../app/config.py时,实际读取的是/data/w3/images/../app/config.py文件,即/data/w3/app/config.py。原因是nginx匹配到/i路径后,将后面的内容拼接到alias,但是此时传入的是/i../,nginx并未意识到这是在跨目录,因而不会进行跨目录相关的处理。

正确的配置是,目录名以斜杠“/”结束:

location /i/ {
    alias /data/w3/images/;
}

防御方案:

  • 避免让用户直接提交文件名。维护一个ID与文件的映射关系,用户只提交索引ID。
  • 如果一定要让用户提交文件名,则应校验文件名的合法性,过滤目录分隔符“/”和“\”。更安全的做法是设置文件名白名单,只允许使用特定的文件名或字符。

Session读取

如果PHP应用中存在文件包含漏洞,攻击者将可以读取Session中的数据。

在默认配置下,PHP将Session存储在文件系统中,默认路径为/var/lib/php/sessions。用户通过文件包含漏洞读取属于自己会话的内容,如果其中包含了不应该让用户知道的信息,将造成信息泄露。

例如,在图形验证码场景中,服务端在生成图像后,通常将验证码的明文存储在Session中用于后续校验。攻击者通过文件包含漏洞读取明文验证码,就能绕过人机校验,实现程序自动化操作:

<?php
session_start();
$_SESSION['captcha'] = '9527'; // 用一个固定的验证码作为演示

if (isset($_GET['filename']))
    include($_GET['filename']);

攻击者提交的参数如下(后面的随机字符串是当前的SessionID):

curl 'http://example.com/lfi.php?filename=../../../../../../var/lib/php/sessions/sess_621t0j12g57iumOkimlotv8a10'

返回结果中包含:

captcha|s:4:"9527";

如果用户能够控制Session中的内容,例如Web应用将当前的用户名存储在Session中,并且用户名中允许存在特殊字符,那么攻击者可以设置如下的用户名,就可以通过文件包含漏洞远程执行代码:

<?php phpinfo(); ?>

除了Session外,用户可控的其他内容同样可以用于实现文件包含,如日志文件、临时文件、上传的文件等。


PHP伪协议

常见伪协议:

file:// — 访问本地文件系统
http:// — 访问 HTTP(s) 网址
ftp:// — 访问 FTP(s) URLs
php:// — 访问各个输入/输出流(I/O streams)
zlib:// — 压缩流
data:// — 数据(RFC 2397)
glob:// — 查找匹配的文件路径模式
phar:// — PHP 归档
ssh2:// — Secure Shell 2
rar:// — RAR
ogg:// — 音频流
expect:// — 处理交互式的流

关于php://filter ,可以参考https://www.anquanke.com/post/id/202510#h3-9 ,写的很详细

本地文件包含漏洞(LFI)

当一个Web应用程序接收到用户输入并将其作为文件路径来包含文件时,如果没有进行适当的验证和清理,就可能被攻击者利用来访问或包含服务器上的其他文件。

一些常见的敏感目录信息路径:
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配置文件

文件包含一般会指定后缀,这样我们就需要截断来绕过。

<?php
    $file = $_GET['name'];
    include($file . "html");
?>

在PHP5.2.x中我们可以通过使用%00来截断后面的内容、也可以使用路径长度截断,不过都在php5.3中被修复了。

payload:

http://127.0.0.1/test.php?name=D:\phpstudy\PHPTutorial\MySQL\my.ini%00

利用字符.或者/.或者./来截断。系统文件路径长度限制:windows 259个bytes linux 4096个bytes

1、日志文件利用
当无法包含文件,或者找不到文件上传入口时,可以考虑利用日志文件


远程文件包含漏洞(RFI)

远程文件包含漏洞允许攻击者通过构造特定的URL或请求参数,使得服务器尝试加载一个远程控制的文件。这通常涉及到PHP的include或require语句,这些语句可以用来包含外部文件。如果这些语句没有得到适当的限制,攻击者就可以利用它们来包含恶意文件,如webshell,这是一种可以远程执行命令的脚本。

RFI存在的前提是在php.ini中配置allow_url_includeallow_url_fopen为on。

对于RFI,我们可以使用?截断,不受版本限制:

http://127.0.0.1/test.php?name=http://127.0.0.1/1.txt?


防御方案:

  • 严格校验参数合法性,避免路径穿越。
  • 采用白名单文件名校验方式,或维护一个ID到文件名的映射关系,让客户端传入ID。
  • 禁止远程加载文件,通过设置allow_url_include=0防止远程文件包含。

CTF例题

简单的文件包含

1、源码如下:

2、输入
http://61.147.171.105:54882/?filename=php://filter/convert.base64-encode/resource=check.php 回显do not hack ,说明在check.php内对代码进行了过滤(使用string.rot13过滤器也不行)

3、只能逐个尝试过滤器,过滤器详情可以参考
https://blog.csdn.net/qq_44657899/article/details/109300335
这里尝试使用convert.iconv*,得知使用了正确的过滤器,但是应该是字符编码不符合

4、于是使用burpsuite抓包对字符编码进行爆破,常见的字符编码如下(不全):

UCS-4*
UCS-4BE
UCS-4LE*
UCS-2
UCS-2BE
UCS-2LE
UTF-32*
UTF-32BE*
UTF-32LE*
UTF-16*
UTF-16BE*
UTF-16LE*
UTF-7
UTF7-IMAP
UTF-8*
ASCII*
EUC-JP*
SJIS*
eucJP-win*
SJIS-win*
ISO-2022-JP
ISO-2022-JP-MS
CP932
CP51932
BASE64

5、得知有5种组合方式是有正常回显的,查看响应包,得到check.php的具体内容

6、我们选择EUC-JP和UCS-4作为字符编码,构造payload:
http://61.147.171.105:54882/?filename=php://filter/convert.iconv.EUC-JP*.UCS-4*/resource=check.php ,然后将check.php 改成 flag.php 即可得到flag


日志文件包含

easy_include

1、源代码如下

image-20240725171826807

2、我们使用?file=/var/log/nginx/access.log查看系统日志文件

image-20240725171955456

3、然后使用burpsuite抓包,在UA头处写上一句话木马再重新发包

image-20240725172430170

4、post传参payload以获得flag

image-20240725173218547


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值