什么是文件包含(漏洞)?
程序开发人员一般会把重复使用的函数写到单个文件中,需要使用某个函数时直接调用此文件,而无需再次编写,这种文件调用的过程一般被称为文件包含。
而此时如果没有对文件来源进行严格审查,就会导致任意文件读取或者任意命令执行,php中与文件包含的有关的函数为 (include(),require()和include_once(),require_once())它们的区别如下
include():只有代码执行到该函数时才会包含文件进来,发生错误时只给出一个警告并继续向下执行。 include_once():和include()功能相同,区别在于当重复调用同一文件时,程序只调用一次。 require():只要程序执行就包含文件进来,发生错误时会输出错误结果并终止运行。 require_once():和require()功能相同,区别在于当重复调用同一文件时,程序只调用一次。
文件包含(漏洞)分为本地包含和远程包含,想要远程包含时需要在php.ini配置文件中将allow_url_fopen设置为On(开启状态)。
文件包含(漏洞)读文件
下面以DVWA文件包含模块进行举例,首先查看一下,low级别的源代码
php // The page we wish to display $file = $_GET[ 'page' ]; ?>
我们发现代码中没有对接收的page参数做任何处理,所以参数page是不可控的,这样就会造成任意文件读取和任意命令执行。先看一下原始的URL
http://www.test.com/DVWA-master/vulnerabilities/fi/?page=include.php
我们将include.php替换成不存在的来看一下,我们发现报错了,并且报出了绝对路径。如下图
接下来咱们构造如下URL,发现读取到了配置文件php.ini
http://www.test.com/DVWA-master/vulnerabilities/fi/?page=D:\phpstudy_pro\WWW\www.test.com\DVWA-master\php.ini
如下图
接下来咱们看一下中级别的源代码
php // The page we wish to display $file = $_GET[ 'page' ]; // Input validation $file = str_replace( array( "http://", "https://" ), "", $file ); $file = str_replace( array( "../", "..\"" ), "", $file ); ?>
发现中级别的使用的str_replace函数,将http:// https:// ../ ..\ 都替换为空格,也就是相当于删除了,但是这种安全措施,很容易绕过,你不是删除吗,那我双写,比如,可以将前面内容构造成htthttp://p://,这个函数将中间的http://删除,剩下的内容重新构成http://,这样就绕过了,执行了构造的恶意链接。
../和..\同样的道理,这是用这样的方式,如下图,咱们依然读取了php.ini配置文件。
下面咱们看一下高级别的源代码
php // The page we wish to display $file = $_GET[ 'page' ]; // Input validation if( !fnmatch( "file*", $file ) && $file != "include.php" ) { // This isn't the page we want! echo "ERROR: File not found!"; exit; } ?>
发现高级别的源代码用了fnmatch函数,对page参数进行检查,如果包含的文件后缀,不是include.php,那就要求page参数的开头必须是file,服务器才会去包含相应的文件。这样咱们还是有方法绕过,可以使用file协议绕过。
再看一下最高级别的核心源代码
php // The page we wish to display $file = $_GET[ 'page' ]; // Only allow include.php or file{1..3}.php if( $file != "include.php" && $file != "file1.php" && $file != "file2.php" && $file != "file3.php" ) { // This isn't the page we want! echo "ERROR: File not found!"; exit; } ?>
最高级别的只允许包含上面三个文件,杜绝了文件包含漏洞。
包含日志文件
而有些时候,当发现本地包含漏洞,普通方法咱们都试过了发现无法利用,这时候可以换一种思路,可以利用日志文件来进行入侵。这里以Apache举例,Apache服务器运行后会生成两个日志文件,这两个文件是access.log(访问日志)和error.log(错误日志),apache的日志文件记录下我们的操作,并且写到访问日志文件access.log之中,这时候咱们直接在参数后加上咱们的恶意代码,页面报错,这个错误信息就会记录到access.log中,里面包含了恶意代码,这时候只要知道日志的路径,就可以使用菜刀链接,直接getwebshell。
PHP内置协议
PHP带有很多内置URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和filesize()的文件系统函数。有想要了解的小伙伴可以去PHP官网,官网地址http://www.php.net/manual/zh/wrappers.php。这里列出了一些
File:// /*访问本地文件系统*/ htt[p:// /*访问HTTP(s)网址*/ ftp:// /*访问FTP(s)URLS*/ php:// /*访问各个输入/输出流(I/o streams) zlib:// /*压缩流*/ data:// /*数据(RFC2397)*/ ssh2:// /*Secure Shell 2*/ expect:// /*处理交互式的流*/
实例
说明:通过本地包含直接getwebshell,直接控制整个网站权限。大体思路:构造错误页面,里面包含恶意代码,利用thinkphp的错误日志功能,直接菜刀连接。
实战环境是,易酷cms2.5 源码下载地址 https://dl.pconline.com.cn/download/1492133.html
我已经下载源码,本地搭建好了,直接开始,搭建好的页面显示如图
接下来构造错误页面,如下图
接下来,在url的后面结合thinkphp的模板语法构造一句话为:{~eval($_POST[-7])},结果如下图,发现咱们的一句话木马已经插入到错误日志中
可以找到/temp/logs/目录下找到这个文件,咱们确定一下看看错误日志里到底有没有咱们的木马,发现确实存在
然后菜刀连接,成功getwebshell