mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Merge pull request #8272 from hmac/hmac/tainted-format-string
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Methods like <code>Kernel.printf</code> accept a format string that is used to format
|
||||
the remaining arguments by providing inline format specifiers. If the format string
|
||||
contains unsanitized input from an untrusted source, then that string may contain
|
||||
unexpected format specifiers that cause garbled output or throw an exception.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Either sanitize the input before including it in the format string, or use a
|
||||
<code>%s</code> specifier in the format string, and pass the untrusted data as corresponding
|
||||
argument.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following program snippet logs information about an unauthorized access attempt. The
|
||||
log message includes the user name, and the user's IP address is passed as an additional
|
||||
argument to <code>Kernel.printf</code> to be appended to the message:
|
||||
</p>
|
||||
<sample src="examples/tainted_format_string_bad.rb"/>
|
||||
<p>
|
||||
However, if a malicious user provides a format specified such as <code>%s</code>
|
||||
as their user name, <code>Kernel.printf</code> will throw an exception as there
|
||||
are too few arguments to satisfy the format. This can result in denial of
|
||||
service or leaking of internal information to the attacker via a stack trace.
|
||||
</p>
|
||||
<p>
|
||||
Instead, the user name should be included using the <code>%s</code> specifier:
|
||||
</p>
|
||||
<sample src="examples/tainted_format_string_good.rb"/>
|
||||
|
||||
<p>
|
||||
Alternatively, string interpolation should be used exclusively:
|
||||
</p>
|
||||
<sample src="examples/tainted_format_string_interpolation.rb"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Ruby documentation for <a href="https://docs.ruby-lang.org/en/3.1/Kernel.html#method-i-sprintf">format strings</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
21
ruby/ql/src/queries/security/cwe-134/TaintedFormatString.ql
Normal file
21
ruby/ql/src/queries/security/cwe-134/TaintedFormatString.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* @name Use of externally-controlled format string
|
||||
* @description Using external input in format strings can lead to garbled output.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 7.3
|
||||
* @precision high
|
||||
* @id rb/tainted-format-string
|
||||
* @tags security
|
||||
* external/cwe/cwe-134
|
||||
*/
|
||||
|
||||
import ruby
|
||||
import codeql.ruby.DataFlow
|
||||
import codeql.ruby.security.TaintedFormatStringQuery
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where cfg.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "$@ flows here and is used in a format string.",
|
||||
source.getNode(), "User-provided value"
|
||||
@@ -0,0 +1,5 @@
|
||||
class UsersController < ActionController::Base
|
||||
def index
|
||||
printf("Unauthorised access attempt by #{params[:user]}: %s", request.ip)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class UsersController < ActionController::Base
|
||||
def index
|
||||
printf("Unauthorised access attempt by %s: %s", params[:user], request.ip)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class UsersController < ActionController::Base
|
||||
def index
|
||||
puts "Unauthorised access attempt by #{params[:user]}: #{request.ip}"
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user