mirror of
https://github.com/github/codeql.git
synced 2026-02-23 18:33:42 +01:00
Merge pull request #21341 from owen-mc/rb/accept-mad-sanitizers
Ruby: Accept MaD sanitizers for queries with MaD sinks and convert some existing sanitizers
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* We now track taint flow through `Shellwords.escape` and `Shellwords.shellescape` for all queries except command injection, for which they are sanitizers.
|
||||
@@ -9,6 +9,7 @@ private import codeql.ruby.CFG
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.dataflow.internal.DataFlowImplSpecific
|
||||
private import codeql.ruby.Frameworks
|
||||
private import codeql.ruby.frameworks.data.internal.ApiGraphModels
|
||||
private import codeql.ruby.dataflow.RemoteFlowSources
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.Regexp as RE
|
||||
@@ -95,6 +96,10 @@ module SqlSanitization {
|
||||
abstract class Range extends DataFlow::Node { }
|
||||
}
|
||||
|
||||
private class ExternalSqlInjectionSanitizer extends SqlSanitization::Range {
|
||||
ExternalSqlInjectionSanitizer() { ModelOutput::barrierNode(this, "sql-injection") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A data-flow node that executes a regular expression.
|
||||
*
|
||||
|
||||
11
ruby/ql/lib/codeql/ruby/frameworks/Mysql2.model.yml
Normal file
11
ruby/ql/lib/codeql/ruby/frameworks/Mysql2.model.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ['Mysql2::Client!', 'Method[escape]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: barrierModel
|
||||
data:
|
||||
- ['Mysql2::Client!', 'Method[escape].ReturnValue', 'sql-injection']
|
||||
@@ -48,26 +48,4 @@ module Mysql2 {
|
||||
|
||||
override DataFlow::Node getSql() { result = query }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `Mysql2::Client.escape`, considered as a sanitizer for SQL statements.
|
||||
*/
|
||||
private class Mysql2EscapeSanitization extends SqlSanitization::Range {
|
||||
Mysql2EscapeSanitization() {
|
||||
this = API::getTopLevelMember("Mysql2").getMember("Client").getAMethodCall("escape")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flow summary for `Mysql2::Client.escape()`.
|
||||
*/
|
||||
private class EscapeSummary extends SummarizedCallable::Range {
|
||||
EscapeSummary() { this = "Mysql2::Client.escape()" }
|
||||
|
||||
override MethodCall getACall() { result = any(Mysql2EscapeSanitization c).asExpr().getExpr() }
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[0]" and output = "ReturnValue" and preservesValue = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
11
ruby/ql/lib/codeql/ruby/frameworks/Sqlite3.model.yml
Normal file
11
ruby/ql/lib/codeql/ruby/frameworks/Sqlite3.model.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ['SQLite3::Database!', 'Method[quote]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: barrierModel
|
||||
data:
|
||||
- ['SQLite3::Database!', 'Method[quote].ReturnValue', 'sql-injection']
|
||||
@@ -76,26 +76,4 @@ module Sqlite3 {
|
||||
|
||||
override DataFlow::Node getSql() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `SQLite3::Database.quote`, considered as a sanitizer for SQL statements.
|
||||
*/
|
||||
private class SQLite3QuoteSanitization extends SqlSanitization {
|
||||
SQLite3QuoteSanitization() {
|
||||
this = API::getTopLevelMember("SQLite3").getMember("Database").getAMethodCall("quote")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flow summary for `SQLite3::Database.quote()`.
|
||||
*/
|
||||
private class QuoteSummary extends SummarizedCallable::Range {
|
||||
QuoteSummary() { this = "SQLite3::Database.quote()" }
|
||||
|
||||
override MethodCall getACall() { result = any(SQLite3QuoteSanitization c).asExpr().getExpr() }
|
||||
|
||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||
input = "Argument[0]" and output = "ReturnValue" and preservesValue = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
extensions:
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: summaryModel
|
||||
data:
|
||||
- ['Shellwords!', 'Method[escape,shellescape]', 'Argument[0]', 'ReturnValue', 'taint']
|
||||
|
||||
- addsTo:
|
||||
pack: codeql/ruby-all
|
||||
extensible: barrierModel
|
||||
data:
|
||||
- ['Shellwords!', 'Method[escape,shellescape].ReturnValue', 'command-injection']
|
||||
@@ -118,4 +118,8 @@ module CodeInjection {
|
||||
private class ExternalCodeInjectionSink extends Sink {
|
||||
ExternalCodeInjectionSink() { ModelOutput::sinkNode(this, "code-injection") }
|
||||
}
|
||||
|
||||
private class ExternalCodeInjectionSanitizer extends Sanitizer {
|
||||
ExternalCodeInjectionSanitizer() { ModelOutput::barrierNode(this, "code-injection") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,13 +43,11 @@ module CommandInjection {
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `Shellwords.escape` or `Shellwords.shellescape` sanitizes its input.
|
||||
* A call to `String#shellescape` sanitizes its input.
|
||||
*/
|
||||
class ShellwordsEscapeAsSanitizer extends Sanitizer {
|
||||
ShellwordsEscapeAsSanitizer() {
|
||||
this = API::getTopLevelMember("Shellwords").getAMethodCall(["escape", "shellescape"])
|
||||
or
|
||||
// The method is also added as `String#shellescape`.
|
||||
// The `Shellwords.shellescape` method is also added as `String#shellescape`.
|
||||
this.(DataFlow::CallNode).getMethodName() = "shellescape"
|
||||
}
|
||||
}
|
||||
@@ -57,4 +55,8 @@ module CommandInjection {
|
||||
private class ExternalCommandInjectionSink extends Sink {
|
||||
ExternalCommandInjectionSink() { ModelOutput::sinkNode(this, "command-injection") }
|
||||
}
|
||||
|
||||
private class ExternalCommandInjectionSanitizer extends Sanitizer {
|
||||
ExternalCommandInjectionSanitizer() { ModelOutput::barrierNode(this, "command-injection") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,10 @@ class HtmlEscapingAsSanitizer extends Sanitizer {
|
||||
HtmlEscapingAsSanitizer() { this = any(HtmlEscaping esc).getOutput() }
|
||||
}
|
||||
|
||||
private class ExternalLogInjectionSanitizer extends Sanitizer {
|
||||
ExternalLogInjectionSanitizer() { ModelOutput::barrierNode(this, "log-injection") }
|
||||
}
|
||||
|
||||
private module LogInjectionConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
|
||||
@@ -57,4 +57,8 @@ module PathInjection {
|
||||
private class ExternalPathInjectionSink extends Sink {
|
||||
ExternalPathInjectionSink() { ModelOutput::sinkNode(this, "path-injection") }
|
||||
}
|
||||
|
||||
private class ExternalPathInjectionSanitizer extends Sanitizer {
|
||||
ExternalPathInjectionSanitizer() { ModelOutput::barrierNode(this, "path-injection") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,4 +46,8 @@ module ServerSideRequestForgery {
|
||||
private class ExternalRequestForgerySink extends Sink {
|
||||
ExternalRequestForgerySink() { ModelOutput::sinkNode(this, "request-forgery") }
|
||||
}
|
||||
|
||||
private class ExternalRequestForgerySanitizer extends Sanitizer {
|
||||
ExternalRequestForgerySanitizer() { ModelOutput::barrierNode(this, "request-forgery") }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,6 +125,10 @@ module UrlRedirect {
|
||||
*/
|
||||
class StringInterpolationAsSanitizer extends PrefixedStringInterpolation, Sanitizer { }
|
||||
|
||||
private class ExternalUrlRedirectSanitizer extends Sanitizer {
|
||||
ExternalUrlRedirectSanitizer() { ModelOutput::barrierNode(this, "url-redirection") }
|
||||
}
|
||||
|
||||
/**
|
||||
* These methods return a new `ActionController::Parameters` or a `Hash` containing a subset of
|
||||
* the original values. This may still contain user input, so the results are tainted.
|
||||
|
||||
@@ -2921,13 +2921,11 @@
|
||||
| file://:0:0:0:0 | [summary param] position 0 in File.realdirpath | file://:0:0:0:0 | [summary] to write: ReturnValue in File.realdirpath |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in File.realpath | file://:0:0:0:0 | [summary] to write: ReturnValue in File.realpath |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in Hash[] | file://:0:0:0:0 | [summary] read: Argument[0].Element[any] in Hash[] |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in Mysql2::Client.escape() | file://:0:0:0:0 | [summary] to write: ReturnValue in Mysql2::Client.escape() |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in Mysql2::Client.new() | file://:0:0:0:0 | [summary] to write: ReturnValue in Mysql2::Client.new() |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in Net::LDAP.new | file://:0:0:0:0 | [summary] to write: ReturnValue in Net::LDAP.new |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in Net::LDAP::Filter | file://:0:0:0:0 | [summary] to write: ReturnValue in Net::LDAP::Filter |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in PG.new() | file://:0:0:0:0 | [summary] to write: ReturnValue in PG.new() |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in Rack::Utils.parse_query | file://:0:0:0:0 | [summary] to write: ReturnValue in Rack::Utils.parse_query |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in SQLite3::Database.quote() | file://:0:0:0:0 | [summary] to write: ReturnValue in SQLite3::Database.quote() |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in Sequel.connect | file://:0:0:0:0 | [summary] to write: ReturnValue in Sequel.connect |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in String.try_convert | file://:0:0:0:0 | [summary] to write: ReturnValue in String.try_convert |
|
||||
| file://:0:0:0:0 | [summary param] position 0 in \| | file://:0:0:0:0 | [summary] read: Argument[0].Element[any] in \| |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class UsersController < ActionController::Base
|
||||
def mysql2_handler(event:, context:)
|
||||
name = params[:user_name]
|
||||
name = params[:user_name] # $ Source[rb/sql-injection]
|
||||
|
||||
conn = Mysql2::Client.new(
|
||||
host: "127.0.0.1",
|
||||
@@ -10,7 +10,7 @@ class UsersController < ActionController::Base
|
||||
results1 = conn.query("SELECT * FROM users")
|
||||
|
||||
# BAD: SQL statement constructed from user input
|
||||
results2 = conn.query("SELECT * FROM users WHERE username='#{name}'")
|
||||
results2 = conn.query("SELECT * FROM users WHERE username='#{name}'") # $ Alert[rb/sql-injection]
|
||||
|
||||
# GOOD: user input is escaped
|
||||
escaped = Mysql2::Client.escape(name)
|
||||
@@ -21,10 +21,10 @@ class UsersController < ActionController::Base
|
||||
results4 = statement1.execute(1, name, :as => :array)
|
||||
|
||||
# BAD: SQL statement constructed from user input
|
||||
statement2 = conn.prepare("SELECT * FROM users WHERE username='#{name}' AND password = ?")
|
||||
statement2 = conn.prepare("SELECT * FROM users WHERE username='#{name}' AND password = ?") # $ Alert[rb/sql-injection]
|
||||
results4 = statement2.execute("password", :as => :array)
|
||||
|
||||
# NOT EXECUTED
|
||||
statement3 = conn.prepare("SELECT * FROM users WHERE username = ?")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#select
|
||||
| Mysql2.rb:13:27:13:72 | "SELECT * FROM users WHERE use..." | Mysql2.rb:3:12:3:17 | call to params | Mysql2.rb:13:27:13:72 | "SELECT * FROM users WHERE use..." | This SQL query depends on a $@. | Mysql2.rb:3:12:3:17 | call to params | user-provided value |
|
||||
| Mysql2.rb:24:31:24:93 | "SELECT * FROM users WHERE use..." | Mysql2.rb:3:12:3:17 | call to params | Mysql2.rb:24:31:24:93 | "SELECT * FROM users WHERE use..." | This SQL query depends on a $@. | Mysql2.rb:3:12:3:17 | call to params | user-provided value |
|
||||
edges
|
||||
| Mysql2.rb:3:5:3:8 | name | Mysql2.rb:13:27:13:72 | "SELECT * FROM users WHERE use..." | provenance | AdditionalTaintStep |
|
||||
| Mysql2.rb:3:5:3:8 | name | Mysql2.rb:24:31:24:93 | "SELECT * FROM users WHERE use..." | provenance | AdditionalTaintStep |
|
||||
| Mysql2.rb:3:12:3:17 | call to params | Mysql2.rb:3:12:3:29 | ...[...] | provenance | |
|
||||
| Mysql2.rb:3:12:3:29 | ...[...] | Mysql2.rb:3:5:3:8 | name | provenance | |
|
||||
nodes
|
||||
| Mysql2.rb:3:5:3:8 | name | semmle.label | name |
|
||||
| Mysql2.rb:3:12:3:17 | call to params | semmle.label | call to params |
|
||||
| Mysql2.rb:3:12:3:29 | ...[...] | semmle.label | ...[...] |
|
||||
| Mysql2.rb:13:27:13:72 | "SELECT * FROM users WHERE use..." | semmle.label | "SELECT * FROM users WHERE use..." |
|
||||
| Mysql2.rb:24:31:24:93 | "SELECT * FROM users WHERE use..." | semmle.label | "SELECT * FROM users WHERE use..." |
|
||||
subpaths
|
||||
@@ -0,0 +1,4 @@
|
||||
query: queries/security/cwe-089/SqlInjection.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -0,0 +1,12 @@
|
||||
#select
|
||||
| sqlite3.rb:29:16:29:67 | "select * from table where cat..." | sqlite3.rb:25:16:25:21 | call to params | sqlite3.rb:29:16:29:67 | "select * from table where cat..." | This SQL query depends on a $@. | sqlite3.rb:25:16:25:21 | call to params | user-provided value |
|
||||
edges
|
||||
| sqlite3.rb:25:5:25:12 | category | sqlite3.rb:29:16:29:67 | "select * from table where cat..." | provenance | AdditionalTaintStep |
|
||||
| sqlite3.rb:25:16:25:21 | call to params | sqlite3.rb:25:16:25:32 | ...[...] | provenance | |
|
||||
| sqlite3.rb:25:16:25:32 | ...[...] | sqlite3.rb:25:5:25:12 | category | provenance | |
|
||||
nodes
|
||||
| sqlite3.rb:25:5:25:12 | category | semmle.label | category |
|
||||
| sqlite3.rb:25:16:25:21 | call to params | semmle.label | call to params |
|
||||
| sqlite3.rb:25:16:25:32 | ...[...] | semmle.label | ...[...] |
|
||||
| sqlite3.rb:29:16:29:67 | "select * from table where cat..." | semmle.label | "select * from table where cat..." |
|
||||
subpaths
|
||||
@@ -0,0 +1,4 @@
|
||||
query: queries/security/cwe-089/SqlInjection.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
@@ -2,9 +2,11 @@ sqlite3SqlConstruction
|
||||
| sqlite3.rb:5:1:5:17 | call to execute | sqlite3.rb:5:12:5:17 | <<-SQL |
|
||||
| sqlite3.rb:12:8:12:41 | call to prepare | sqlite3.rb:12:19:12:41 | "select * from numbers" |
|
||||
| sqlite3.rb:17:3:19:5 | call to execute | sqlite3.rb:17:15:17:35 | "select * from table" |
|
||||
| sqlite3.rb:29:7:29:40 | call to execute | sqlite3.rb:29:19:29:39 | "select * from table" |
|
||||
| sqlite3.rb:29:5:29:68 | call to execute | sqlite3.rb:29:16:29:67 | "select * from table where cat..." |
|
||||
| sqlite3.rb:33:5:33:78 | call to execute | sqlite3.rb:33:16:33:77 | "select * from table where cat..." |
|
||||
sqlite3SqlExecution
|
||||
| sqlite3.rb:5:1:5:17 | call to execute | sqlite3.rb:5:12:5:17 | <<-SQL |
|
||||
| sqlite3.rb:14:1:14:12 | call to execute | sqlite3.rb:12:19:12:41 | "select * from numbers" |
|
||||
| sqlite3.rb:17:3:19:5 | call to execute | sqlite3.rb:17:15:17:35 | "select * from table" |
|
||||
| sqlite3.rb:29:7:29:40 | call to execute | sqlite3.rb:29:19:29:39 | "select * from table" |
|
||||
| sqlite3.rb:29:5:29:68 | call to execute | sqlite3.rb:29:16:29:67 | "select * from table where cat..." |
|
||||
| sqlite3.rb:33:5:33:78 | call to execute | sqlite3.rb:33:16:33:77 | "select * from table where cat..." |
|
||||
|
||||
@@ -20,12 +20,16 @@ SQLite3::Database.new( "data.db" ) do |db|
|
||||
end
|
||||
|
||||
|
||||
class MyDatabaseWrapper
|
||||
def initialize(filename)
|
||||
@db = SQLite3::Database.new(filename, results_as_hash: true)
|
||||
end
|
||||
class SqliteController < ActionController::Base
|
||||
def sqlite3_handler
|
||||
category = params[:category] # $ Source[rb/sql-injection]
|
||||
db = SQLite3::Database.new "test.db"
|
||||
|
||||
def select_rows(category)
|
||||
@db.execute("select * from table")
|
||||
end
|
||||
# BAD: SQL injection vulnerability
|
||||
db.execute("select * from table where category = '#{category}'") # $ Alert[rb/sql-injection]
|
||||
|
||||
# GOOD: Sanitized by SQLite3::Database.quote
|
||||
sanitized_category = SQLite3::Database.quote(category)
|
||||
db.execute("select * from table where category = '#{sanitized_category}'")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,46 @@
|
||||
#select
|
||||
| CodeInjection.rb:8:10:8:13 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:8:10:8:13 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:11:10:11:15 | call to params | CodeInjection.rb:11:10:11:15 | call to params | CodeInjection.rb:11:10:11:15 | call to params | This code execution depends on a $@. | CodeInjection.rb:11:10:11:15 | call to params | user-provided value |
|
||||
| CodeInjection.rb:20:20:20:23 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:20:20:20:23 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:23:21:23:24 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:23:21:23:24 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:29:15:29:18 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:29:15:29:18 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:32:19:32:22 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:32:19:32:22 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:38:10:38:28 | call to escape | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:38:10:38:28 | call to escape | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:41:40:41:43 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:41:40:41:43 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:81:16:81:19 | code | CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:81:16:81:19 | code | This code execution depends on a $@. | CodeInjection.rb:78:12:78:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:90:10:90:37 | ... + ... | CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:90:10:90:37 | ... + ... | This code execution depends on a $@. | CodeInjection.rb:78:12:78:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:93:10:93:32 | "prefix_#{...}_suffix" | CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:93:10:93:32 | "prefix_#{...}_suffix" | This code execution depends on a $@. | CodeInjection.rb:78:12:78:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:96:10:96:13 | code | CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:96:10:96:13 | code | This code execution depends on a $@. | CodeInjection.rb:78:12:78:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:118:10:118:13 | @foo | CodeInjection.rb:111:12:111:17 | call to params | CodeInjection.rb:118:10:118:13 | @foo | This code execution depends on a $@. | CodeInjection.rb:111:12:111:17 | call to params | user-provided value |
|
||||
edges
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:8:10:8:13 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:20:20:20:23 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:23:21:23:24 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:29:15:29:18 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:32:19:32:22 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:38:24:38:27 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:41:40:41:43 | code | provenance | |
|
||||
| CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:5:12:5:24 | ...[...] | provenance | |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] | CodeInjection.rb:5:5:5:8 | code | provenance | |
|
||||
| CodeInjection.rb:38:24:38:27 | code | CodeInjection.rb:38:10:38:28 | call to escape | provenance | MaD:1 |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:81:16:81:19 | code | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:90:10:90:37 | ... + ... | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:90:22:90:25 | code | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:93:10:93:32 | "prefix_#{...}_suffix" | provenance | AdditionalTaintStep |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:96:10:96:13 | code | provenance | |
|
||||
| CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:78:12:78:24 | ...[...] | provenance | |
|
||||
| CodeInjection.rb:78:12:78:24 | ...[...] | CodeInjection.rb:78:5:78:8 | code | provenance | |
|
||||
| CodeInjection.rb:90:10:90:25 | ... + ... : [collection] [element] | CodeInjection.rb:90:10:90:37 | ... + ... | provenance | |
|
||||
| CodeInjection.rb:90:22:90:25 | code | CodeInjection.rb:90:10:90:25 | ... + ... : [collection] [element] | provenance | |
|
||||
| CodeInjection.rb:107:3:108:5 | self in index : PostsController [@foo] | CodeInjection.rb:117:3:119:5 | self in baz : PostsController [@foo] | provenance | |
|
||||
| CodeInjection.rb:111:5:111:8 | [post] self [@foo] | CodeInjection.rb:114:3:115:5 | self in bar : PostsController [@foo] | provenance | |
|
||||
| CodeInjection.rb:111:12:111:17 | call to params | CodeInjection.rb:111:12:111:23 | ...[...] | provenance | |
|
||||
| CodeInjection.rb:111:12:111:23 | ...[...] | CodeInjection.rb:111:5:111:8 | [post] self [@foo] | provenance | |
|
||||
| CodeInjection.rb:114:3:115:5 | self in bar : PostsController [@foo] | CodeInjection.rb:107:3:108:5 | self in index : PostsController [@foo] | provenance | |
|
||||
| CodeInjection.rb:117:3:119:5 | self in baz : PostsController [@foo] | CodeInjection.rb:118:10:118:13 | self : PostsController [@foo] | provenance | |
|
||||
| CodeInjection.rb:118:10:118:13 | self : PostsController [@foo] | CodeInjection.rb:118:10:118:13 | @foo | provenance | |
|
||||
models
|
||||
| 1 | Summary: Regexp!; Method[escape,quote]; Argument[0]; ReturnValue; taint |
|
||||
nodes
|
||||
| CodeInjection.rb:5:5:5:8 | code | semmle.label | code |
|
||||
| CodeInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
|
||||
@@ -14,59 +57,18 @@ nodes
|
||||
| CodeInjection.rb:78:5:78:8 | code | semmle.label | code |
|
||||
| CodeInjection.rb:78:12:78:17 | call to params | semmle.label | call to params |
|
||||
| CodeInjection.rb:78:12:78:24 | ...[...] | semmle.label | ...[...] |
|
||||
| CodeInjection.rb:80:16:80:19 | code | semmle.label | code |
|
||||
| CodeInjection.rb:86:10:86:25 | ... + ... : [collection] [element] | semmle.label | ... + ... : [collection] [element] |
|
||||
| CodeInjection.rb:86:10:86:37 | ... + ... | semmle.label | ... + ... |
|
||||
| CodeInjection.rb:86:22:86:25 | code | semmle.label | code |
|
||||
| CodeInjection.rb:88:10:88:32 | "prefix_#{...}_suffix" | semmle.label | "prefix_#{...}_suffix" |
|
||||
| CodeInjection.rb:90:10:90:13 | code | semmle.label | code |
|
||||
| CodeInjection.rb:101:3:102:5 | self in index : PostsController [@foo] | semmle.label | self in index : PostsController [@foo] |
|
||||
| CodeInjection.rb:105:5:105:8 | [post] self [@foo] | semmle.label | [post] self [@foo] |
|
||||
| CodeInjection.rb:105:12:105:17 | call to params | semmle.label | call to params |
|
||||
| CodeInjection.rb:105:12:105:23 | ...[...] | semmle.label | ...[...] |
|
||||
| CodeInjection.rb:108:3:109:5 | self in bar : PostsController [@foo] | semmle.label | self in bar : PostsController [@foo] |
|
||||
| CodeInjection.rb:111:3:113:5 | self in baz : PostsController [@foo] | semmle.label | self in baz : PostsController [@foo] |
|
||||
| CodeInjection.rb:112:10:112:13 | @foo | semmle.label | @foo |
|
||||
| CodeInjection.rb:112:10:112:13 | self : PostsController [@foo] | semmle.label | self : PostsController [@foo] |
|
||||
edges
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:8:10:8:13 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:20:20:20:23 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:23:21:23:24 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:29:15:29:18 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:32:19:32:22 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:38:24:38:27 | code | provenance | |
|
||||
| CodeInjection.rb:5:5:5:8 | code | CodeInjection.rb:41:40:41:43 | code | provenance | |
|
||||
| CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:5:12:5:24 | ...[...] | provenance | |
|
||||
| CodeInjection.rb:5:12:5:24 | ...[...] | CodeInjection.rb:5:5:5:8 | code | provenance | |
|
||||
| CodeInjection.rb:38:24:38:27 | code | CodeInjection.rb:38:10:38:28 | call to escape | provenance | MaD:21 |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:80:16:80:19 | code | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:86:10:86:37 | ... + ... | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:86:22:86:25 | code | provenance | |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:88:10:88:32 | "prefix_#{...}_suffix" | provenance | AdditionalTaintStep |
|
||||
| CodeInjection.rb:78:5:78:8 | code | CodeInjection.rb:90:10:90:13 | code | provenance | |
|
||||
| CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:78:12:78:24 | ...[...] | provenance | |
|
||||
| CodeInjection.rb:78:12:78:24 | ...[...] | CodeInjection.rb:78:5:78:8 | code | provenance | |
|
||||
| CodeInjection.rb:86:10:86:25 | ... + ... : [collection] [element] | CodeInjection.rb:86:10:86:37 | ... + ... | provenance | |
|
||||
| CodeInjection.rb:86:22:86:25 | code | CodeInjection.rb:86:10:86:25 | ... + ... : [collection] [element] | provenance | |
|
||||
| CodeInjection.rb:101:3:102:5 | self in index : PostsController [@foo] | CodeInjection.rb:111:3:113:5 | self in baz : PostsController [@foo] | provenance | |
|
||||
| CodeInjection.rb:105:5:105:8 | [post] self [@foo] | CodeInjection.rb:108:3:109:5 | self in bar : PostsController [@foo] | provenance | |
|
||||
| CodeInjection.rb:105:12:105:17 | call to params | CodeInjection.rb:105:12:105:23 | ...[...] | provenance | |
|
||||
| CodeInjection.rb:105:12:105:23 | ...[...] | CodeInjection.rb:105:5:105:8 | [post] self [@foo] | provenance | |
|
||||
| CodeInjection.rb:108:3:109:5 | self in bar : PostsController [@foo] | CodeInjection.rb:101:3:102:5 | self in index : PostsController [@foo] | provenance | |
|
||||
| CodeInjection.rb:111:3:113:5 | self in baz : PostsController [@foo] | CodeInjection.rb:112:10:112:13 | self : PostsController [@foo] | provenance | |
|
||||
| CodeInjection.rb:112:10:112:13 | self : PostsController [@foo] | CodeInjection.rb:112:10:112:13 | @foo | provenance | |
|
||||
| CodeInjection.rb:81:16:81:19 | code | semmle.label | code |
|
||||
| CodeInjection.rb:90:10:90:25 | ... + ... : [collection] [element] | semmle.label | ... + ... : [collection] [element] |
|
||||
| CodeInjection.rb:90:10:90:37 | ... + ... | semmle.label | ... + ... |
|
||||
| CodeInjection.rb:90:22:90:25 | code | semmle.label | code |
|
||||
| CodeInjection.rb:93:10:93:32 | "prefix_#{...}_suffix" | semmle.label | "prefix_#{...}_suffix" |
|
||||
| CodeInjection.rb:96:10:96:13 | code | semmle.label | code |
|
||||
| CodeInjection.rb:107:3:108:5 | self in index : PostsController [@foo] | semmle.label | self in index : PostsController [@foo] |
|
||||
| CodeInjection.rb:111:5:111:8 | [post] self [@foo] | semmle.label | [post] self [@foo] |
|
||||
| CodeInjection.rb:111:12:111:17 | call to params | semmle.label | call to params |
|
||||
| CodeInjection.rb:111:12:111:23 | ...[...] | semmle.label | ...[...] |
|
||||
| CodeInjection.rb:114:3:115:5 | self in bar : PostsController [@foo] | semmle.label | self in bar : PostsController [@foo] |
|
||||
| CodeInjection.rb:117:3:119:5 | self in baz : PostsController [@foo] | semmle.label | self in baz : PostsController [@foo] |
|
||||
| CodeInjection.rb:118:10:118:13 | @foo | semmle.label | @foo |
|
||||
| CodeInjection.rb:118:10:118:13 | self : PostsController [@foo] | semmle.label | self : PostsController [@foo] |
|
||||
subpaths
|
||||
#select
|
||||
| CodeInjection.rb:8:10:8:13 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:8:10:8:13 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:11:10:11:15 | call to params | CodeInjection.rb:11:10:11:15 | call to params | CodeInjection.rb:11:10:11:15 | call to params | This code execution depends on a $@. | CodeInjection.rb:11:10:11:15 | call to params | user-provided value |
|
||||
| CodeInjection.rb:20:20:20:23 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:20:20:20:23 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:23:21:23:24 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:23:21:23:24 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:29:15:29:18 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:29:15:29:18 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:32:19:32:22 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:32:19:32:22 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:38:10:38:28 | call to escape | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:38:10:38:28 | call to escape | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:41:40:41:43 | code | CodeInjection.rb:5:12:5:17 | call to params | CodeInjection.rb:41:40:41:43 | code | This code execution depends on a $@. | CodeInjection.rb:5:12:5:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:80:16:80:19 | code | CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:80:16:80:19 | code | This code execution depends on a $@. | CodeInjection.rb:78:12:78:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:86:10:86:37 | ... + ... | CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:86:10:86:37 | ... + ... | This code execution depends on a $@. | CodeInjection.rb:78:12:78:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:88:10:88:32 | "prefix_#{...}_suffix" | CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:88:10:88:32 | "prefix_#{...}_suffix" | This code execution depends on a $@. | CodeInjection.rb:78:12:78:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:90:10:90:13 | code | CodeInjection.rb:78:12:78:17 | call to params | CodeInjection.rb:90:10:90:13 | code | This code execution depends on a $@. | CodeInjection.rb:78:12:78:17 | call to params | user-provided value |
|
||||
| CodeInjection.rb:112:10:112:13 | @foo | CodeInjection.rb:105:12:105:17 | call to params | CodeInjection.rb:112:10:112:13 | @foo | This code execution depends on a $@. | CodeInjection.rb:105:12:105:17 | call to params | user-provided value |
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
queries/security/cwe-094/CodeInjection.ql
|
||||
query: queries/security/cwe-094/CodeInjection.ql
|
||||
postprocess:
|
||||
- utils/test/PrettyPrintModels.ql
|
||||
- utils/test/InlineExpectationsTestQuery.ql
|
||||
|
||||
@@ -2,13 +2,13 @@ require 'active_job'
|
||||
|
||||
class UsersController < ActionController::Base
|
||||
def create
|
||||
code = params[:code]
|
||||
code = params[:code] # $ Source
|
||||
|
||||
# BAD
|
||||
eval(code)
|
||||
eval(code) # $ Alert
|
||||
|
||||
# BAD
|
||||
eval(params)
|
||||
eval(params) # $ Alert
|
||||
|
||||
# GOOD - user input is in second argument, which is not evaluated as Ruby code
|
||||
send(:sanitize, params[:code])
|
||||
@@ -17,28 +17,28 @@ class UsersController < ActionController::Base
|
||||
Foo.new.bar(code)
|
||||
|
||||
# BAD
|
||||
Foo.class_eval(code)
|
||||
Foo.class_eval(code) # $ Alert
|
||||
|
||||
# BAD
|
||||
Foo.module_eval(code)
|
||||
Foo.module_eval(code) # $ Alert
|
||||
|
||||
# GOOD
|
||||
Bar.class_eval(code)
|
||||
|
||||
# BAD
|
||||
const_get(code)
|
||||
const_get(code) # $ Alert
|
||||
|
||||
# BAD
|
||||
Foo.const_get(code)
|
||||
Foo.const_get(code) # $ Alert
|
||||
|
||||
# GOOD
|
||||
Bar.const_get(code)
|
||||
|
||||
# BAD
|
||||
eval(Regexp.escape(code))
|
||||
eval(Regexp.escape(code)) # $ Alert
|
||||
|
||||
# BAD
|
||||
ActiveJob::Serializers.deserialize(code)
|
||||
ActiveJob::Serializers.deserialize(code) # $ Alert
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -75,19 +75,25 @@ end
|
||||
|
||||
class UsersController < ActionController::Base
|
||||
def create
|
||||
code = params[:code]
|
||||
code = params[:code] # $ Source
|
||||
|
||||
obj().send(code, "foo"); # BAD
|
||||
# BAD
|
||||
obj().send(code, "foo"); # $ Alert
|
||||
|
||||
obj().send("prefix_" + code + "_suffix", "foo"); # GOOD
|
||||
# GOOD
|
||||
obj().send("prefix_" + code + "_suffix", "foo");
|
||||
|
||||
obj().send("prefix_#{code}_suffix", "foo"); # GOOD
|
||||
# GOOD
|
||||
obj().send("prefix_#{code}_suffix", "foo");
|
||||
|
||||
eval("prefix_" + code + "_suffix"); # BAD
|
||||
# BAD
|
||||
eval("prefix_" + code + "_suffix"); # $ Alert
|
||||
|
||||
eval("prefix_#{code}_suffix"); # BAD
|
||||
# BAD
|
||||
eval("prefix_#{code}_suffix"); # $ Alert
|
||||
|
||||
eval(code); # BAD
|
||||
# BAD
|
||||
eval(code); # $ Alert
|
||||
end
|
||||
end
|
||||
|
||||
@@ -102,13 +108,13 @@ class PostsController < ActionController::Base
|
||||
end
|
||||
|
||||
def foo
|
||||
@foo = params[:foo]
|
||||
@foo = params[:foo] # $ Source
|
||||
end
|
||||
|
||||
def bar
|
||||
end
|
||||
|
||||
def baz
|
||||
eval(@foo)
|
||||
eval(@foo) # $ Alert
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user