使用 Kernel.open 或 IO.read 或类似的接收器与非常量值¶
ID: rb/non-constant-kernel-open
Kind: problem
Security severity: 6.5
Severity: warning
Precision: high
Tags:
   - correctness
   - security
   - external/cwe/cwe-078
   - external/cwe/cwe-088
   - external/cwe/cwe-073
Query suites:
   - ruby-code-scanning.qls
   - ruby-security-extended.qls
   - ruby-security-and-quality.qls
如果 Kernel.open 给定的文件名以 | 字符开头,它将执行剩余的字符串作为 shell 命令。如果恶意用户可以控制文件名,他们可以执行任意代码。相同的漏洞也适用于 IO.read、IO.write、IO.binread、IO.binwrite、IO.foreach、IO.readlines 和 URI.open。
建议¶
使用 File.open 而不是 Kernel.open,因为前者没有这个漏洞。类似地,使用 File 类的 methods 而不是 IO 类,例如使用 File.read 而不是 IO.read。
不要使用 URI.open,而是使用 URI(..).open 或 HTTP 客户端。
示例¶
以下示例展示了在用户提供的文件路径上调用 Kernel.open 的代码。
require "open-uri"
class UsersController < ActionController::Base
  def create
    filename = params[:filename]
    open(filename) # BAD
    web_page = params[:web_page]
    URI.open(web_page) # BAD - calls `Kernel.open` internally
  end
end
相反,应该使用 File.open,如下面的示例所示。
class UsersController < ActionController::Base
  def create
    filename = params[:filename]
    File.open(filename)
    web_page = params[:web_page]
    Net::HTTP.get(URI.parse(web_page))
  end
end
参考资料¶
- OWASP: 命令注入. Ruby on Rails Cheat Sheet: 命令注入. 
- 示例 CVE: RDoc 中的命令注入. 
- 通用弱点枚举: CWE-78. 
- 通用弱点枚举: CWE-88. 
- 通用弱点枚举: CWE-73.