简单实现一个文件读取小功能,常见的场景就是上传头像图片后,后端自动展示出来。代码示例如下:
if (isset($_GET['filename'])){
$filename = $_GET['filename'];
header('Content-Type: image/jpeg');
readfile($filename);
}
<meta charset="utf-8">
<html lang="en">
<head>
<title>文件读取漏洞</title>
</head>
<body>
<div style="text-align: center;">
<h1>File Read Vulnerability labs-1</h1>
<a href="?filename=flag.jpg">
<img border="0" src="flag.jpg" alt="image load..." width="420" height="400"></a>
</div>
</body>
</html>
01 不安全的过滤示例
1、没有任何过滤
基本读取代码示例如下:
由于header 设置了图片格式,所以通过浏览器不能显示出来,此时可通过bp 抓包工具,或者另存为txt文件去查看读取内容。
2、目录限制
说明:在基本上增加目录限制,但是没有任何过滤。
利用示例:如果没有过滤../../ 可以进行目录穿越读取文件
3、str_replace过滤../
说明:在上面基础上增加使用str_replace 函数过滤../
利用示例:通过....// 或者.. 进行读取
4、str_replace过滤../ ./ .. .
说明:在上面基础上增加使用str_replace 函数过滤../ ./ .. .
利用示例:方法同上
5、str_replace过滤../ ./ .. . 替换成###
说明:在上面基础上增加使用str_replace 函数过滤../ ./ .. . 替换成###
利用示例:虽然把../.. 替换了###,没法进行穿越目录进行读取文件,但是在没有进行目录限制的情况下可以使用伪协议读取内容。
6、preg_relace 过滤../../ 过滤file 协议
说明:增加preg_relace 过滤../../ 和file://,使用伪协议读取文件 http://
利用示例:使用 http://协议去读取文件
7、使用base64解密读取
说明:使用preg_replace 函数进行正则过滤,加base64加密
利用示例:上面存在逻辑问题,因此可以使用base64加密../flag/flag.txt (Li4vZmxhZy9mbGFnLnR4dA==)然后去读取文件
8、使用base64解密读取+preg_replace 过滤../
说明:在上基本上先解密后过滤。
利用示例:使用伪协议的方法进行加密后读取
9、目录可控
说明:增加目录路径传参
利用示例:$type= $_GET['type'] ? $type : 'img';
10、yxcms_v9文件读取案例绕过&q=
利用示例:通过../../ 绕过&q=
02
安全建议
防止任意文件读取漏洞,可以采取以下措施:
1.输入验证和过滤:对用户提供的文件路径进行严格的验证和过滤,只接受有效的文件路径。可以使用白名单或正则表达式来限制允许的文件路径格式。
2.安全文件访问函数:使用安全的文件访问函数,如file_exists、is_readable和realpath,来检查文件的存在性和可读性。
3.限制文件访问权限:确保服务器上的文件和目录设置了适当的权限,只允许有必要访问的用户或进程读取文件。
4.隔离文件系统:将应用程序的文件存储区与应用程序代码隔离开来,限制文件读取的范围。
5.定期更新和维护:及时更新和维护服务器上运行的应用程序、框架和相关组件,以修复已知的漏洞。
最重要的是,进行安全审计和定期漏洞扫描,以发现和修复潜在的任意文件读取漏洞。同时,保持对最新安全威胁和安全最佳实践的了解,以及对代码进行安全审查和测试,有助于提高应用程序的安全性。
03
修复示例
1.文件路径限制:确保只允许访问应用程序的特定目录下的文件,通过将文件路径限制在应用程序根目录或指定目录内来减少潜在的风险。
2.文件权限控制:仔细设置文件系统权限,确保只有应用程序需要访问的文件才具有适当的读取权限,限制其他用户或进程的访问。
3.输入过滤和验证:对用户提供的输入进行严格过滤和验证,确保文件路径只包含所需的字符和格式,并排除任何恶意输入,以防止路径遍历和其他漏洞。
4.沙盒环境:将文件读取操作限制在一个沙盒环境中,使用操作系统的安全机制,例如使用 chroot 环境或虚拟化技术,以限制对文件系统的访问。
5.文件白名单:维护一个白名单,只允许读取预先定义的文件列表,而不是根据用户输入或动态构建的文件路径。
6.文件内容校验:在读取文件内容之前,对文件进行内容校验,确保文件内容符合预期的格式和结构,以防止恶意文件的执行或利用。
7.日志记录和监测:实施适当的日志记录和监测机制,记录所有文件读取操作,并及时检测和响应异常或可疑的读取行为。
得到
示例一、目录白名单+正则过滤../ 和 多余的//
示例二:增加白名单后缀名
pathinfo() 是一个 PHP 内置函数,用于解析文件路径的信息并返回一个关联数组。它接受一个文件路径作为参数,并返回包含以下信息的关联数组:
dirname:文件路径中的目录部分(不包括文件名)。
basename:文件路径中的文件名部分(包括文件扩展名)。
extension:文件路径中的文件扩展名部分(不包括点号)。
filename:文件路径中的文件名部分(不包括文件扩展名)。
以下是 pathinfo() 函数的基本语法:
$pathInfo = pathinfo($path);
其中,$path 是要解析的文件路径。函数将返回一个关联数组,可以通过数组键访问相应的信息。
示例如下:
示例三:增加日志记录(访问日志记录)
在上述示例中,
file_put_contents() 函数将
$logMessage 的内容追加到名为
access.txt 的文件末尾。通过指定
FILE_APPEND 标志,确保新的数据追加到现有文件内容之后,而不是覆盖文件内容。
示例四:错误记录
错误日志记录是一种常见的安全实践,它可以帮助我们捕获和记录应用程序中发生的错误和异常情况,以便进行故障排除和修复。下面是一个简单的错误日志记录示例:
// 启用错误日志记录
ini_set('log_errors', 1);
ini_set('error_log', 'path/to/error.log');
// 示例错误日志记录
try {
// 代码块可能会引发异常
// ...
} catch (Exception $e) {
$errorMessage = 'An error occurred: ' . $e->getMessage();
// 记录错误信息到日志文件
error_log($errorMessage);
}
在上述示例中,我们首先通过 ini_set() 函数启用错误日志记录。设置 log_errors 为 1 表示启用错误日志记录,设置 error_log 为日志文件的路径和名称。
接下来,我们使用 try-catch 块来捕获可能发生的异常。在 catch 块中,我们获取异常的错误信息,并将其记录到日志文件中,使用 error_log() 函数写入日志。
通过将错误信息记录到日志文件,您可以随时查看和分析发生的错误,以便调试和修复应用程序中的问题。请确保日志文件的路径和名称是适当的,并且具有正确的访问权限。
此外,您还可以根据需要设置其他配置选项,如 error_reporting 来定义所需的错误报告级别,以及使用 date 函数添加时间戳等更多的日志信息。根据实际需求和应用程序的规模,您可以进一步定制错误日志记录的方式。
End
原文始发于微信公众号(贝雷帽SEC):WEB 安全—深入学习文件读取漏洞 (二)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论