Merge pull request #12832 from maikypedia/maikypedia/pg-sqli

Ruby: Add SQL Injection Sinks
This commit is contained in:
Alex Ford
2023-05-26 11:36:17 +01:00
committed by GitHub
6 changed files with 184 additions and 0 deletions

View File

@@ -2814,6 +2814,7 @@
| file://:0:0:0:0 | parameter position 0 of File.realdirpath | file://:0:0:0:0 | [summary] to write: return (return) in File.realdirpath |
| file://:0:0:0:0 | parameter position 0 of File.realpath | file://:0:0:0:0 | [summary] to write: return (return) in File.realpath |
| file://:0:0:0:0 | parameter position 0 of Hash[] | file://:0:0:0:0 | [summary] read: argument position 0.any element in Hash[] |
| file://:0:0:0:0 | parameter position 0 of PG.new() | file://:0:0:0:0 | [summary] to write: return (return) in PG.new() |
| file://:0:0:0:0 | parameter position 0 of String.try_convert | file://:0:0:0:0 | [summary] to write: return (return) in String.try_convert |
| file://:0:0:0:0 | parameter position 0 of \| | file://:0:0:0:0 | [summary] read: argument position 0.any element in \| |
| file://:0:0:0:0 | parameter position 1.. of File.join | file://:0:0:0:0 | [summary] to write: return (return) in File.join |

View File

@@ -0,0 +1,70 @@
class FooController < ActionController::Base
def some_request_handler
# A string tainted by user input is inserted into a query
# (i.e a remote flow source)
name = params[:name]
# Establish a connection to a PostgreSQL database
conn = PG::Connection.open(:dbname => 'postgresql', :user => 'user', :password => 'pass', :host => 'localhost', :port => '5432')
# .exec() and .async_exec()
# BAD: SQL statement constructed from user input
qry1 = "SELECT * FROM users WHERE username = '#{name}';"
conn.exec(qry1)
conn.async_exec(qry1)
# .exec_params() and .async_exec_params()
# BAD: SQL statement constructed from user input
qry2 = "SELECT * FROM users WHERE username = '#{name}';"
conn.exec_params(qry2)
conn.async_exec_params(qry2)
# .exec_params() and .async_exec_params()
# GOOD: SQL statement constructed from sanitized user input
qry2 = "SELECT * FROM users WHERE username = $1;"
conn.exec_params(qry2, [name])
conn.async_exec_params(qry2, [name])
# .prepare() and .exec_prepared()
# BAD: SQL statement constructed from user input
qry3 = "SELECT * FROM users WHERE username = '#{name}';"
conn.prepare("query_1", qry3)
conn.exec_prepared('query_1')
# .prepare() and .exec_prepared()
# GOOD: SQL statement constructed from sanitized user input
qry3 = "SELECT * FROM users WHERE username = $1;"
conn.prepare("query_2", qry3)
conn.exec_prepared('query_2', [name])
# .prepare() and .exec_prepared()
# NOT EXECUTED: SQL statement constructed from user input but not executed
qry3 = "SELECT * FROM users WHERE username = '#{name}';"
conn.prepare("query_3", qry3)
end
end
class BarController < ApplicationController
def safe_paths
name1 = params["name1"]
# GOOD: barrier guard prevents taint flow
if name == "admin"
qry_bar1 = "SELECT * FROM users WHERE username = '%s';" % name
else
qry_bar1 = "SELECT * FROM users WHERE username = 'none';"
end
conn.exec_params(qry_bar1)
name2 = params["name2"]
# GOOD: barrier guard prevents taint flow
name2 = if ["admin", "guest"].include? name2
name2
else
name2 = "none"
end
qry_bar2 = "SELECT * FROM users WHERE username = '%s';" % name
conn.exec_params(qry_bar2)
end
end

View File

@@ -55,6 +55,18 @@ edges
| ArelInjection.rb:4:5:4:8 | name | ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." |
| ArelInjection.rb:4:12:4:17 | call to params | ArelInjection.rb:4:12:4:29 | ...[...] |
| ArelInjection.rb:4:12:4:29 | ...[...] | ArelInjection.rb:4:5:4:8 | name |
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:13:5:13:8 | qry1 |
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:19:5:19:8 | qry2 |
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:31:5:31:8 | qry3 |
| PgInjection.rb:6:5:6:8 | name | PgInjection.rb:43:5:43:8 | qry3 |
| PgInjection.rb:6:12:6:17 | call to params | PgInjection.rb:6:12:6:24 | ...[...] |
| PgInjection.rb:6:12:6:24 | ...[...] | PgInjection.rb:6:5:6:8 | name |
| PgInjection.rb:13:5:13:8 | qry1 | PgInjection.rb:14:15:14:18 | qry1 |
| PgInjection.rb:13:5:13:8 | qry1 | PgInjection.rb:15:21:15:24 | qry1 |
| PgInjection.rb:19:5:19:8 | qry2 | PgInjection.rb:20:22:20:25 | qry2 |
| PgInjection.rb:19:5:19:8 | qry2 | PgInjection.rb:21:28:21:31 | qry2 |
| PgInjection.rb:31:5:31:8 | qry3 | PgInjection.rb:32:29:32:32 | qry3 |
| PgInjection.rb:43:5:43:8 | qry3 | PgInjection.rb:44:29:44:32 | qry3 |
nodes
| ActiveRecordInjection.rb:8:25:8:28 | name | semmle.label | name |
| ActiveRecordInjection.rb:8:31:8:34 | pass | semmle.label | pass |
@@ -133,6 +145,19 @@ nodes
| ArelInjection.rb:4:12:4:17 | call to params | semmle.label | call to params |
| ArelInjection.rb:4:12:4:29 | ...[...] | semmle.label | ...[...] |
| ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." | semmle.label | "SELECT * FROM users WHERE nam..." |
| PgInjection.rb:6:5:6:8 | name | semmle.label | name |
| PgInjection.rb:6:12:6:17 | call to params | semmle.label | call to params |
| PgInjection.rb:6:12:6:24 | ...[...] | semmle.label | ...[...] |
| PgInjection.rb:13:5:13:8 | qry1 | semmle.label | qry1 |
| PgInjection.rb:14:15:14:18 | qry1 | semmle.label | qry1 |
| PgInjection.rb:15:21:15:24 | qry1 | semmle.label | qry1 |
| PgInjection.rb:19:5:19:8 | qry2 | semmle.label | qry2 |
| PgInjection.rb:20:22:20:25 | qry2 | semmle.label | qry2 |
| PgInjection.rb:21:28:21:31 | qry2 | semmle.label | qry2 |
| PgInjection.rb:31:5:31:8 | qry3 | semmle.label | qry3 |
| PgInjection.rb:32:29:32:32 | qry3 | semmle.label | qry3 |
| PgInjection.rb:43:5:43:8 | qry3 | semmle.label | qry3 |
| PgInjection.rb:44:29:44:32 | qry3 | semmle.label | qry3 |
subpaths
#select
| ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | ActiveRecordInjection.rb:70:23:70:28 | call to params | ActiveRecordInjection.rb:10:33:10:67 | "name='#{...}' and pass='#{...}'" | This SQL query depends on a $@. | ActiveRecordInjection.rb:70:23:70:28 | call to params | user-provided value |
@@ -159,3 +184,9 @@ subpaths
| ActiveRecordInjection.rb:177:43:177:104 | "SELECT * FROM users WHERE id ..." | ActiveRecordInjection.rb:173:5:173:10 | call to params | ActiveRecordInjection.rb:177:43:177:104 | "SELECT * FROM users WHERE id ..." | This SQL query depends on a $@. | ActiveRecordInjection.rb:173:5:173:10 | call to params | user-provided value |
| ActiveRecordInjection.rb:178:35:178:96 | "SELECT * FROM users WHERE id ..." | ActiveRecordInjection.rb:173:5:173:10 | call to params | ActiveRecordInjection.rb:178:35:178:96 | "SELECT * FROM users WHERE id ..." | This SQL query depends on a $@. | ActiveRecordInjection.rb:173:5:173:10 | call to params | user-provided value |
| ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." | ArelInjection.rb:4:12:4:17 | call to params | ArelInjection.rb:6:20:6:61 | "SELECT * FROM users WHERE nam..." | This SQL query depends on a $@. | ArelInjection.rb:4:12:4:17 | call to params | user-provided value |
| PgInjection.rb:14:15:14:18 | qry1 | PgInjection.rb:6:12:6:17 | call to params | PgInjection.rb:14:15:14:18 | qry1 | This SQL query depends on a $@. | PgInjection.rb:6:12:6:17 | call to params | user-provided value |
| PgInjection.rb:15:21:15:24 | qry1 | PgInjection.rb:6:12:6:17 | call to params | PgInjection.rb:15:21:15:24 | qry1 | This SQL query depends on a $@. | PgInjection.rb:6:12:6:17 | call to params | user-provided value |
| PgInjection.rb:20:22:20:25 | qry2 | PgInjection.rb:6:12:6:17 | call to params | PgInjection.rb:20:22:20:25 | qry2 | This SQL query depends on a $@. | PgInjection.rb:6:12:6:17 | call to params | user-provided value |
| PgInjection.rb:21:28:21:31 | qry2 | PgInjection.rb:6:12:6:17 | call to params | PgInjection.rb:21:28:21:31 | qry2 | This SQL query depends on a $@. | PgInjection.rb:6:12:6:17 | call to params | user-provided value |
| PgInjection.rb:32:29:32:32 | qry3 | PgInjection.rb:6:12:6:17 | call to params | PgInjection.rb:32:29:32:32 | qry3 | This SQL query depends on a $@. | PgInjection.rb:6:12:6:17 | call to params | user-provided value |
| PgInjection.rb:44:29:44:32 | qry3 | PgInjection.rb:6:12:6:17 | call to params | PgInjection.rb:44:29:44:32 | qry3 | This SQL query depends on a $@. | PgInjection.rb:6:12:6:17 | call to params | user-provided value |