CodeQL 文档

路径表达式中使用不受控数据

ID: swift/path-injection
Kind: path-problem
Security severity: 7.5
Severity: error
Precision: high
Tags:
   - security
   - external/cwe/cwe-022
   - external/cwe/cwe-023
   - external/cwe/cwe-036
   - external/cwe/cwe-073
   - external/cwe/cwe-099
Query suites:
   - swift-code-scanning.qls
   - swift-security-extended.qls
   - swift-security-and-quality.qls

点击查看 CodeQL 代码库中的查询

访问由用户控制的路径可能会将资源暴露给攻击者。

从用户控制的数据中天真地构建的路径可能包含意外的特殊字符,例如 ..。这样的路径可能指向文件系统上的任何目录。

建议

在使用用户输入来构建文件路径之前验证用户输入。理想情况下,请遵循以下规则:

  • 不允许出现超过一个 . 字符。

  • 不允许使用目录分隔符,例如 /\(取决于文件系统)。

  • 不要依赖于简单地替换 ../ 这样的问题序列。例如,将此过滤器应用于 .../...// 后,结果字符串仍然是 ../

  • 使用已知良好模式的白名单。

示例

以下代码展示了两个不良示例。

let fm = FileManager.default
let path = try String(contentsOf: URL(string: "http://example.com/")!)

// BAD
return fm.contents(atPath: path)

// BAD
if (path.hasPrefix(NSHomeDirectory() + "/Library/Caches")) {
    return fm.contents(atPath: path)
}

第一个示例从 HTTP 请求中读取文件名,然后使用该文件名来访问文件。在这种情况下,恶意响应可能会包含一个文件名,该文件名是一个绝对路径,例如 "/Applications/(current_application)/Documents/sensitive.data"

第二个不良示例中,用户似乎被限制在 "/Library/Caches" 主目录中打开文件。在这种情况下,恶意响应可能会包含一个文件名,该文件名包含特殊字符。例如,字符串 "../../Documents/sensitive.data" 将导致代码读取位于 "/Applications/(current_application)/Library/Caches/../../Documents/sensitive.data" 的文件,其中包含用户的敏感数据。然后,此文件可能被攻击者访问,从而使他们能够访问所有这些数据。

在以下(良好)示例中,用于访问文件系统的路径在与已知前缀进行检查之前被规范化。这确保了无论用户输入如何,结果路径都是安全的。

let fm = FileManager.default
let path = try String(contentsOf: URL(string: "http://example.com/")!)

// GOOD
let filePath = FilePath(stringLiteral: path)
if (filePath.lexicallyNormalized().starts(with: FilePath(stringLiteral: NSHomeDirectory() + "/Library/Caches"))) {
    return fm.contents(atPath: path)
}

参考资料

  • ©GitHub, Inc.
  • 条款
  • 隐私