Use ofKernel.open,IO.read or similar sinks with user-controlled input¶
ID: rb/kernel-openKind: path-problemSecurity severity: 9.8Severity: errorPrecision: highTags: - correctness - security - external/cwe/cwe-078 - external/cwe/cwe-088 - external/cwe/cwe-073Query suites: - ruby-code-scanning.qls - ruby-security-extended.qls - ruby-security-and-quality.qls
Click to see the query in the CodeQL repository
IfKernel.open is given a file name that starts with a| character, it will execute the remaining string as a shell command. If a malicious user can control the file name, they can execute arbitrary code. The same vulnerability applies toIO.read,IO.write,IO.binread,IO.binwrite,IO.foreach,IO.readlines andURI.open.
Recommendation¶
UseFile.open instead ofKernel.open, as the former does not have this vulnerability. Similarly, use the methods from theFile class instead of theIO class e.g.File.read instead ofIO.read.
Instead ofURI.open useURI(..).open or an HTTP Client.
Example¶
The following example shows code that callsKernel.open on a user-supplied file path.
require"open-uri"classUsersController<ActionController::Basedefcreatefilename=params[:filename]open(filename)# BADweb_page=params[:web_page]URI.open(web_page)# BAD - calls `Kernel.open` internallyendend
Instead,File.open should be used, as in the following example.
classUsersController<ActionController::Basedefcreatefilename=params[:filename]File.open(filename)web_page=params[:web_page]Net::HTTP.get(URI.parse(web_page))endend
References¶
OWASP:Command Injection.Ruby on Rails Cheat Sheet: Command Injection.
Example CVE:Command Injection in RDoc.
Common Weakness Enumeration:CWE-78.
Common Weakness Enumeration:CWE-88.
Common Weakness Enumeration:CWE-73.