对于文件包含漏洞的知识梳理

  |  

近日刷题发现对基础知识掌握有点不牢固,故逐步整理温习.今天还是先整理下文件包含漏洞.

文件包含是指:程序开发人员把经常使用代码写到一个文件里,在使用时直接调用那个文件而无需重新编写代码的过程称为文件包含.在c语言中的调用头文件和python import调用模块本质上就是一种文件包含。而文件包含漏洞(RFI)是指通过函数包含文件时,没有对包含的文件进行处理导致包含某些敏感文件或恶意文件。

0x01文件包含漏洞的存在点

文件包含漏洞一般出现在文件系统函数的地方。比如include、require、include_once、require_once、highlight_file 、show_source 、readfile 、file_get_contents 、fopen 、file等文件系统函数。其中include、require、include_once、require_once四个函数在包含一个文件时,会执行里面的有php标记的代码。

最简单的,例如:

1
2
3
<?php
include($_GET['lexs']); #可以控制lexs的参数内容来达到目的
?>

0x02远程文件包含

当PHP的配置文件allow_url_fopen和allow_url_include设置为ON,include等包含函数可以加载远程文件。通常是被恶意人士用来远程包含一个恶意脚本。

1
2
3
4
allow_url_fopen = On (允许打开URL文件,预设启用)
allow_url_fopen = Off (禁止打开URL文件)
allow_url_include = Off (禁止引用URL文件,新版增加功能,预设关闭)
allow_url_include = On (允许引用URL文件,新版增加功能)

image-20200605165003940

0x03本地文件包含

本地文件包含指包含服务器上的文件。这个方法来用来读取服务器上某些文件的敏感信息或包含执行上传的恶意脚本。

(1)利用目录遍历漏洞来进行文件包含

目录遍历漏洞按我理解就是通过相对路径的方式访问文件.(通过url地址中’../‘ 表上一级目录’./‘表当前目录’/‘表下一级目录).例:访问zhuce.php的上级目录下的flag.php.

image-20200605212506017

但要注意php配置中的include_path与open_basedir的配置:

1.include_path

当寻找要包含的文件时,PHP会分别考虑包含路径中的每个条目。它将检查第一个路径,如果找不到,请检查下一个路径,直到找到包含的文件或返回警告 或错误为止 。

1
2
3
4
5
6
; UNIX: "/path1:/path2"
include_path = ".:/php/includes"
;在UNIX,下在包含时先找当前目录下面的文件,如果找不到找/php/includes目录下的文件,若再找不到则报错。
; Windows: "\path1;\path2"
include_path = ".;c:\php\includes"
;在Windows,下在包含时先找当前目录下面的文件,如果找不到找c:\php\includes目录下的文件,若再找不到则报错。

2.open_basedir

将PHP可以访问的文件限制为指定的目录树,包括文件本身。这个指令是不是由安全模式打开或者关闭的影响。在open_basedir为配置时可以用任意遍历目录但有了open_basedir的设置就能够包含设置下的目录。

image-20200605221901168

image-20200605221707515

(2)利用绝对路径来进行文件包含

我们可以通过绝对路径来进行文件包含:

image-20200605223232782

但用绝对路径然而受到open_basedir的限制:

image-20200605221551100

常见的敏感信息的默认绝对路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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/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 配置文件

(3)利用日志文件机制来进行文件包含

因为服务器日志用记录下我们访问信息与发送的数据.

利用日志文件机制这个机制通过报错将报错的信息写入日志,再通过文件包含包含日志.

image-20200606151047308

(4)利用 .htaccess来进行文件包含

php.ini中auto_prepend_file和auto_append_file分别可以在作用范围内的php文件在文件头/尾自动include指定文件并且可以支持php伪协议.

1
2
auto_prepend_file 在页面顶部加载文件
auto_append_file 在页面底部加载文件

注意:auto_prepend_file 与 auto_append_file 只能包含一个php文件,但这个php文件内可以包含多个其他的php文件。

在 .htaccess文件中php_value 可以设置php.ini里的选项,并只在 .htaccess文件所在的文件夹下生效。

1
2
php_value auto_prepend_file  lexsd6.php
php_value auto_append_file "php://filter/convert.base64decode/resource=lexsd6.php"

故可以把代码入.htaccess文件中,再通过auto_prepend_file/auto_append_file包含。即:

image-20200612215358056

同时不仅可以通过.htaccess文件来改变open_basedir来让包含路径不受限制,还可以通过与include_path来改变包含路径。

1
2
php_value open_basedir   xxx1(允许的路径)
php_value include_path xxx2(包含路径)

0x04利用php协议进行包含

在文件包含时可以通过php协议,来绕过一些限制从而进行包含.

PHP中支持的伪协议:

1
2
3
4
5
6
7
8
9
10
11
12
*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:// — 处理交互式的流

大佬总结的图如下:

image-20200606151558443

file://协议

file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响.

用法: file:// [文件的绝对路径和文件名]

例: file://C:/phpstudy_pro/WWW/flag.php

php://协议

php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。

(1)php://filter

php://filter与file://协议相似在双off的情况下也可以正常使用.

用法: php://filter/筛选过滤方式/resource=<文件>

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

其中

1
2
3
4
resource=<要过滤的数据流>     这个参数是必须的。它指定了你要筛选过滤的数据流。
read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。
<;两个链的筛选列表> 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。

(2)php://input

php://input 是个可以访问请求的原始数据的只读流,可以读取到post没有解析的原始数据, 将post请求中的数据作为PHP代码执行。因为它不依赖于特定的 php.ini 指令。
ps:enctype=”multipart/form-data” 或allow_url_include=off 的时候 php://input 是无效的。

用法:php://input (post 方式提交php代码)

data://协议

又称为RFC 2397 协议,data://协议在‘allow_url_fopen =on ’与v‘allow_url_include:on’
且php 版本大于等于 php5.2 才能生效。

用法 data://资源类型;编码,内容 (‘data://’也可以写成‘data:’)

例:

1
2
3
4
5
6
7
8
http://127.0.0.1/test.php?a=data://text/plain,<?php phpinfo()?>
or
http://127.0.0.1/test.php?a=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

或者
http://127.0.0.1/test.php?file=data:text/plain,<?php phpinfo()?>
or
http://127.0.0.1/test.php?file=data:text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=

0x00参考资料

https://www.php.net/manual/zh/ini.core.php

https://www.smi1e.top/%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB%E6%BC%8F%E6%B4%9E%E4%B8%8Ephp%E4%BC%AA%E5%8D%8F%E8%AE%AE/

文章目录
  1. 0x01文件包含漏洞的存在点
  2. 0x02远程文件包含
  3. 0x03本地文件包含
    1. (1)利用目录遍历漏洞来进行文件包含
      1. 1.include_path
      2. 2.open_basedir
    2. (2)利用绝对路径来进行文件包含
    3. (3)利用日志文件机制来进行文件包含
    4. (4)利用 .htaccess来进行文件包含
  4. 0x04利用php协议进行包含
    1. file://协议
    2. php://协议
    3. data://协议
  • 0x00参考资料
  • |