文件包含概念

定义

通过文件包含函数将文件包含起来,直接使用包含文件的代码

成因

在包含文件时候,为了灵活包含文件,将被包含文件设置为变量,通过动态变量来引入需要包含的文件时,用户可以对变量的值可控而服务器端未对变量值进行合理地校验或者校验被绕过,这样就导致了文件包含漏洞。通常文件包含漏洞出现在PHP语言中

示例代码

1
2
3
4
5
<?php
$file = $_GET['file']; // 1. 获取用户输入
include($file); // 2. 直接包含并执行该文件
// ......
?>

文件包含函数

函数 失败时的处理方式 重复包含检查
include 产生警告(Warning),脚本继续执行 会重复包含同一文件
include_once 产生警告(Warning),脚本继续执行 只会包含一次(如果已包含则跳过)
require 产生致命错误(Fatal Error),脚本停止执行 会重复包含同一文件
require_once 产生致命错误(Fatal Error),脚本停止执行 只会包含一次

分类

本地文件包含(当前服务器)

远程文件包含(http url)

allow_url_fopen:为 ON 时,能读取远程文件。例如 file_get_contents() 就能读取远程文件。

allow_url_include:为 ON 时,就可使用 includerequire 等方式包含远程文件

相对路径和绝对路径

特性 绝对路径 相对路径
路径写法 /home/user/documents/test.txt ./test.txttest.txt
起点 系统的根目录 当前所在的工作目录
灵活性 较差,文件夹结构变了就得改代码 较好,只要文件间相对位置不变就行
安全性 较高(不容易产生歧义) 较低(在 Web 安全中易导致目录遍历漏洞)

和文件上传的区别

特性 文件上传 (File Upload) 文件包含 (File Inclusion)
本质行为 客户端向服务器写入文件。 服务器读取并运行已存在的文件。
漏洞成因 没检查上传文件的后缀名或内容 没检查被包含文件的路径或变量值
利用前提 需要一个上传接口(如头像上传、附件)。 需要代码中存在 includerequire 等函数。
执行后缀 通常需要文件是 .php 格式才能被解析执行。 不看后缀。即便包含的是 .txt.jpg,只要里面有 PHP 代码,就会被执行。
后果 直接在服务器生成一个 Webshell。 泄露敏感文件(LFI)或执行远程代码(RFI)。

利用方式

伪协议

语法上和http区别不大

file 读取路径上的某个文件

php://filter 能够读文件+编码

php://input 读取post数据的参数,并且在php代码里执行

zip://通过#访问

data:// 类似input,让用户控制输入流

00截断

长度截断 win256 linux4096 最大读取

包含日志文件 有ip,时间等

包含session

简单文件包含

获取系统敏感文件

?cmd=c:\\boot.ini

获取webshell

?cmd=phpinfo.php 当前目录

?cmd=../../../phpinfo.php父目录,相对路径

试一试看看哪个路径有

和文件类型没关系,文件里只要是php代码就能执行

00截断

.用来拼接字符串

参数后面加%00,会被当成空格,截断后面的内容

?cmd=c:\\boot.ini%00

点加斜杠绕过

substr 截断字符串

参数 -4 4 从后往前数第4个,开始取后面的4个参数

过滤了.php

去掉后缀名绕过

·addslashes()

PHP addslashes() 函数

单引号 (') → 变成 \'

双引号 (") → 变成 \"

反斜杠 (\) → 变成 \\

NULL 字节 (NUL) → 变成 \0

?cmd=phpinfo

双写绕过

….//

和sql注入的双写绕过一样

写shell

一句话木马<?php ?>');?>

fopen('shell.php', 'w'): 在当前目录下打开(如果不存在则创建)一个名为 shell.php 的文件,并准备写入内容

fputs(...): 向这个新创建的 shell.php 文件中写入内容:<?php eval($_POST[shell])?>

结果: 执行完这个母脚本后,服务器上会多出一个“真正”的一句话木马 shell.php

包含文件日志获取shell