修复路径穿越、任意文件写入漏洞
背景
前段时间随手写的一个文件上传服务,在公司的渗透测试下漏洞百出,其中少不了路径穿越和任意文件写入漏洞。其实这两个漏洞的修复并不复杂,只要对入参进行两个条件的校验就可以了。
问题分析
先来了解一下这两个漏洞是什么
路径穿越漏洞
路径穿越(Path Traversal)是一种常见的安全漏洞,攻击者通过该漏洞可以访问系统中未授权的文件或目录。修复该漏洞的方法包括以下几个步骤:
- 验证输入:首先,需要对所有输入进行严格的验证。攻击者通常会利用路径穿越漏洞通过输入特定字符来访问系统中的敏感文件或目录。因此,在代码中验证输入是非常重要的。
- 检查路径:在使用输入来构造路径之前,需要检查路径是否存在于预期的目录中。如果路径指向系统中未授权访问的目录,应该立即停止程序的执行,并返回错误。
- 使用绝对路径:为了避免路径穿越攻击,最好使用绝对路径而不是相对路径。相对路径可能会导致程序访问不想访问的目录。使用绝对路径可以确保程序只访问所期望的目录。
- 限制访问:最后,为了保护系统中的文件和目录,应该限制程序的访问权限。程序只应该访问必要的文件和目录,不应该访问不需要的文件或目录。
通过上述步骤,可以有效修复路径穿越漏洞,并提高系统的安全性。
任意文件写入漏洞
任意文件写入漏洞(Arbitrary File Write)是一种常见的安全漏洞,攻击者可以利用此漏洞将任意数据写入到服务器上的任意位置,从而可能导致服务器上的敏感信息泄漏或系统被控制。
攻击者通常利用应用程序中存在的缺陷或漏洞来进行攻击,例如:
- 输入验证不充分:如果应用程序没有对用户输入的数据进行充分的验证和过滤,攻击者可以将恶意代码或脚本注入到应用程序中,从而使其执行任意操作,包括写入任意文件。
- 路径遍历攻击:攻击者可以利用路径遍历漏洞来绕过应用程序的安全检查,从而写入到系统上的任意文件,例如 /etc/passwd 文件。
- 错误的文件权限:如果应用程序具有写入某些目录的权限,而该目录的权限过于宽松(例如,目录的权限为777),攻击者可以将任意数据写入该目录。
为了防止任意文件写入漏洞,开发人员可以采取以下几个措施:
- 输入验证:开发人员应该对输入的数据进行充分的验证和过滤,以避免攻击者能够注入恶意代码或脚本。
- 文件权限控制:开发人员应该限制应用程序的访问权限,例如仅允许访问特定目录,并使用适当的文件权限设置,以确保只有授权用户才能访问该目录。
- 安全编程实践:开发人员应该遵循安全编程实践,例如使用编程语言提供的安全函数,如 Java 中的
File.createTempFile()
或 Python 中的tempfile.mkstemp()
,以确保应用程序在创建临时文件时安全可靠。 - 日志监控:监控应用程序的访问日志,以及服务器上的文件系统活动,以及对文件系统进行的任何非正常操作,例如对未知目录的写入操作。这有助于尽早发现潜在的任意文件写入漏洞并进行修复。
说白了,路径穿越就是别人攻击你的时候,文件名带有
/
、
\
、
../
这类的相对路径,篡改了你保存文件的目录;任意文件写入就是,攻击你的服务器时,比如说你原先只能上传图片的,它给你上传了一个shell脚本到服务器的敏感位置,那你的数据安全就别妄想了。
问题解决
基于上面的分析,我们很容易想到了,对传入的文件名进行两道校验:
- 文件名只能包含数字、英文(大小写)、下划线、横杠、小数点
- 后缀只能支持指定的文件类型
我们来编码实现一下这两个功能
publicclassUploadCheckUtil{// 检查文件名是否合法publicstaticbooleancheckFileName(String fileName){String reg ="^[a-zA-Z0-9][a-zA-Z0-9._-]*\\.[a-zA-Z0-9]+$";Pattern p =Pattern.compile(reg);return p.matcher(fileName).find();}// 检查文件类型publicstaticbooleancheckSuffix(String fileName){int index = fileName.lastIndexOf(".");String suffix = index ==-1?"": fileName.substring(index +1);String reg ="(jpg|jpeg|gif|png|mp4|flv|avi|rm|wmv)";Pattern p =Pattern.compile(reg);return p.matcher(fileName).find();}}
^[a-zA-Z0-9][a-zA-Z0-9._-]*\.[a-zA-Z0-9]+$
这个正则表达式的含义是:
- ^ 和 $ 表示匹配整个字符串,不能有额外的字符;
- [a-zA-Z0-9]+ 表示文件名由至少一个字母或数字组成;
- ([.-][a-zA-Z0-9]+) 表示文件名中可以包含多个分隔符(.、*、-),以及一个或多个字母或数字;
- . 表示文件名和文件类型之间有一个点号;
- [a-zA-Z0-9]+ 表示文件类型由至少一个字母或数字组成。 这个正则表达式可以匹配例如 test.png、test_image.jpg、document.txt 这样的文件名,但不能匹配 …/test.png 这样的包含路径遍历符号的文件名。可能有些同学就很疑惑我为什么都是写0-9、a-z、A-Z这种,通配符我是不是不懂,质疑我
\w
、\d
是否有了解过。那是因为如果用通配符攻击者可能会将路径信息编码成文件名中的特殊字符。如果文件名可为中文字符的话,可添加\u4e00-\u9fa5
。\u4e00
表示中文第一个字符,/u9fa5
表示中文最后一个字符。
(jpg|jpeg|gif|png|mp4|flv|avi|rm|wmv)
匹配的是其中的任意一个短语。你可以替换成你实际开发需要限制的文件类型。
在使用时,我们只需要把上传的文件名进行传入,当两个校验都通过时,方可进行transfer,否则抛出文件名不合规的异常即可。
这个正则表达式可以有效地预防路径穿越攻击,但并不能彻底地预防路径穿越攻击。
总结
正则表达式的作用主要是限制上传的文件名只包含特定的字符和格式,从而减少路径穿越攻击的风险。但是,如果攻击者利用其他漏洞(例如文件上传的身份验证绕过漏洞)来绕过这个限制,仍然可以上传包含路径遍历符号的恶意文件。
因此,防止路径穿越攻击需要综合考虑多种安全措施,包括但不限于:
对上传的文件进行验证,确保文件类型和大小符合预期。
对上传的文件进行存储限制,防止上传可执行文件或恶意脚本。
对上传的文件进行安全性检查,例如扫描病毒、检查文件内容是否包含恶意代码等。
对上传的文件进行隔离,避免上传的文件对其他文件和系统资源产生影响。
综上所述,虽然正则表达式可以有效地预防路径穿越攻击,但是仍然需要综合考虑多种安全措施来保护系统安全。
版权归原作者 InterestAndFun 所有, 如有侵权,请联系我们删除。