路径遍历漏洞,也被称为目录遍历漏洞,是一种常见的安全漏洞类型,攻击者可以通过该漏洞访问或修改应用程序之外的目录或文件。
这种漏洞通常由于应用程序在接受用户输入时没有正确过滤或验证用户提供的文件路径导致。攻击者可以通过构造特定的输入,使得应用程序执行意外的操作,例如读取敏感文件、修改应用程序之外的文件或删除文件等。
假设有人向 IAP GCS 代理发送以下请求:
curl https://gcs-iap-proxy.company.com/../another_bucket/super_important_file.txt
如果不对用于输入的路径进行过滤,那么上面的请求路径将被路由到其他桶,导致重要数据泄露。
路径遍历攻击是一种常见的Web安全漏洞,攻击者利用该漏洞可以访问应用程序的文件系统,执行任意文件操作。
为了防止路径遍历攻击,应用程序可以采取以下措施:
路径遍历漏洞可能导致以下危害:
这些攻击可能导致数据泄露、数据破坏、服务拒绝等严重后果,严重影响应用程序的可用性、完整性和机密性。
在 Golang 中,可以使用 path/filepath 包中的 Clean() 或 Join() 函数来避免路径遍历漏洞。
Clean() 函数可以清除路径中的冗余信息,例如 . 和 …,从而避免路径遍历攻击。
从文档(和源代码注释)中可以看出 filepath.Clean() 做了如下几件事情。
例如:
package main
import (
"fmt"
"path/filepath"
)
func main() {
strs := []string{
".",
"..",
"/foo/./../bar",
"foo/../bar",
"..foo/./../bar",
"foo/../../../bar/baz",
}
for _, s := range strs {
fmt.Println(filepath.Clean(s))
}
}
运行输出:
.
..
/bar
bar
bar
../../bar/baz
路径中的 . 和内部的 … 均被清除了。
使用 filepath.Clean() 还有一点需要注意的是,如果以 …/ 字符串开始时没有前导分隔符,则该字符串将保持不变。
fmt.Println(filepath.Clean("../../foo"))
输出:
../../foo
Join 将任意数量的路径元素连接到一个路径中,用操作系统特定的分隔符将它们分开。 空元素将被忽略。 结果是干净的。 但是,如果参数列表为空或其所有元素都为空,则 Join 返回空字符串。 在 Windows 上,如果第一个非空元素是 UNC(Universal Naming Convention)路径,则结果只会是 UNC 路径。
如果需要对路径清理,建议将路径分隔与待清洗的路径使用 Join 拼接起来,这样非法的路径元素会自动被清除。然后再去除根目录便得到合法的路径。
package main
import (
"fmt"
"path/filepath"
"strings"
)
func main() {
strs := []string{
".",
"..",
"/foo/./../bar",
"foo/../bar",
"..foo/./../bar",
"foo/../../../bar/baz",
"../../foo",
}
for _, s := range strs {
fmt.Println(strings.TrimPrefix(filepath.Join(string(filepath.Separator), s), string(filepath.Separator)))
}
}
运行输出:
bar
bar
bar
bar/baz
foo
“.” 和 “…” 和路径分隔符拼接后的结果均是 “/”,所以去除分隔符后变成空串。
另外可以看到,以 …/ 开头的路径也被成功地清理了。
路径遍历漏洞一种常见的 Web 安全漏洞,在很多业务场景都有可能发生。
但路径遍历漏洞不仅存在于 Web 应用程序,比如解压一个文件时,如果没有对文件名称进行清理,也会被坏人利用漏洞发起路径遍历攻击,将恶意文件解压至指定目录或覆盖原有的文件。
所以在处理用户输入的路径时,要多加小心。
OpenAI ChatGPT Preventing path traversal in Golang - Matous Dzivjak github.com/golang/go:proposal: path/filepath: addition of SecureJoin helper