Go中在任何平台上验证给定文件路径位于基本路径内的最安全和最安全的方法是什么?
路径最初是以字符串形式提供的,并使用"/"作为分隔符,但它们是用户提供的,我需要假设有大量恶意输入。我应该执行哪种路径规范化,以确保像".."这样的序列得到评估,这样我就可以安全地对照基本路径进行检查?在各种文件系统和平台上,需要注意哪些例外情况?哪些Go图书馆在这方面应该是安全的?
结果将被馈送到像os.Create
和sqlite3.Open
这样的外部函数,并且任何未能识别出基本路径被留下的情况都将是安全违规。
我相信您可以使用filepath.Rel
(并检查它是否返回以..
开头的值(。
Rel返回一个在词法上等价于targpath的相对路径当使用中间分隔符连接到basepath时。也就是说,Join(basepath,Rel(basepath,targpath((相当于targpath它本身一旦成功,返回的路径将始终相对于basepath,即使basepath和targpath不共享任何元素。错误是如果不能使targpath相对于basepath,或者如果知道当前工作目录将是计算它所必需的对结果调用Clean。
filepath.Rel
还在其输入路径上调用filepath.Clean
,解析任何.
s和..
s。
Clean返回与纯词汇处理。它反复应用以下规则,直到无法进行进一步处理:
- 用单个分隔符元素替换多个分隔符元素
- 消除每个。path name元素(当前目录(
- 消除每个内部。。path name元素(父目录(以及非。。元素
- 消除。。以根路径开头的元素:也就是说,将路径开头的"/.."替换为"/",假设Separator是"/">
您也可以直接使用filepath.Clean
,并在完成后检查前缀。以下是filepath.Clean
:的一些示例输出
ps := []string{
"/a/../b",
"/a/b/./c/../../d",
"/b",
}
for _, p := range ps {
fmt.Println(p, filepath.Clean(p))
}
打印:
/a/../b /b
/a/b/./c/../../d /a/d
/b /b
也就是说,路径操作不应该是您部署的唯一安全机制。如果你真的担心漏洞,可以通过沙盒、创建虚拟文件系统/容器等方式进行深度防御。