Merge pull request #196 from github/active-record-1

Start modelling some potential SQL fragment sinks in ActiveRecord
This commit is contained in:
Alex Ford
2021-06-22 16:05:26 +01:00
committed by GitHub
5 changed files with 247 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
activeRecordModelClasses
| ActiveRecordInjection.rb:1:1:3:3 | UserGroup |
| ActiveRecordInjection.rb:5:1:7:3 | User |
| ActiveRecordInjection.rb:9:1:10:3 | Admin |
activeRecordSqlExecutionRanges
| ActiveRecordInjection.rb:22:21:22:41 | "id = #{...}" |
| ActiveRecordInjection.rb:28:16:28:21 | <<-SQL |
| ActiveRecordInjection.rb:32:35:32:60 | "user.id = #{...}" |
| ActiveRecordInjection.rb:45:21:45:33 | ... + ... |
activeRecordModelClassMethodCalls
| ActiveRecordInjection.rb:19:5:19:45 | call to calculate |
| ActiveRecordInjection.rb:22:5:22:42 | call to delete_all |
| ActiveRecordInjection.rb:25:5:25:45 | call to destroy_all |
| ActiveRecordInjection.rb:28:5:28:35 | call to where |
| ActiveRecordInjection.rb:32:5:32:27 | call to joins |
| ActiveRecordInjection.rb:32:5:32:61 | call to where |
| ActiveRecordInjection.rb:45:5:45:34 | call to delete_all |
potentiallyUnsafeSqlExecutingMethodCall
| ActiveRecordInjection.rb:22:5:22:42 | call to delete_all |
| ActiveRecordInjection.rb:28:5:28:35 | call to where |
| ActiveRecordInjection.rb:32:5:32:61 | call to where |
| ActiveRecordInjection.rb:45:5:45:34 | call to delete_all |

View File

@@ -0,0 +1,12 @@
import codeql_ruby.controlflow.CfgNodes
import codeql_ruby.frameworks.ActiveRecord
query predicate activeRecordModelClasses(ActiveRecordModelClass cls) { any() }
query predicate activeRecordSqlExecutionRanges(ActiveRecordSqlExecutionRange range) { any() }
query predicate activeRecordModelClassMethodCalls(ActiveRecordModelClassMethodCall call) { any() }
query predicate potentiallyUnsafeSqlExecutingMethodCall(PotentiallyUnsafeSqlExecutingMethodCall call) {
any()
}

View File

@@ -0,0 +1,51 @@
class UserGroup < ActiveRecord::Base
has_many :users
end
class User < ApplicationRecord
belongs_to :user_group
end
class Admin < User
end
class FooController < ActionController::Base
MAX_USER_ID = 100_000
# A string tainted by user input is inserted into an SQL query
def some_request_handler
# SELECT AVG(#{params[:column]}) FROM "users"
User.calculate(:average, params[:column])
# DELETE FROM "users" WHERE (id = #{params[:id]})
User.delete_all("id = #{params[:id]}")
# SELECT "users".* FROM "users" WHERE (id = #{params[:id]})
User.destroy_all(["id = #{params[:id]}"])
# SELECT "users".* FROM "users" WHERE id BETWEEN #{params[:min_id]} AND 100000
User.where(<<-SQL, MAX_USER_ID)
id BETWEEN #{params[:min_id]} AND ?
SQL
UserGroup.joins(:users).where("user.id = #{params[:id]}")
end
end
class BarController < ApplicationController
def some_other_request_handler
ps = params
uid = ps[:id]
# DELETE FROM "users" WHERE (id = #{uid})
User.delete_all("id = " + uid)
end
end
class BazController < BarController
end