Merge branch 'main' into maikypedia/ldap-injection

This commit is contained in:
Alex Ford
2023-07-31 16:00:41 +01:00
committed by GitHub
472 changed files with 18820 additions and 4118 deletions

View File

@@ -2818,6 +2818,7 @@
| 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 |

View File

@@ -3,9 +3,12 @@ rackRequestHandlers
| rack.rb:17:3:21:5 | call | rack.rb:17:12:17:18 | the_env | rack.rb:20:5:20:27 | call to [] |
| rack.rb:30:3:36:5 | call | rack.rb:30:12:30:14 | env | rack.rb:35:5:35:26 | call to [] |
| rack.rb:40:3:44:5 | call | rack.rb:40:12:40:14 | env | rack.rb:43:5:43:45 | call to [] |
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:66:7:66:22 | call to [] |
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:73:5:73:21 | call to [] |
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:66:7:66:24 | call to [] |
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:73:5:73:23 | call to [] |
| rack.rb:79:3:81:5 | call | rack.rb:79:17:79:19 | env | rack.rb:93:5:93:78 | call to finish |
| rack.rb:98:3:107:5 | call | rack.rb:98:12:98:14 | env | rack.rb:110:5:110:28 | call to [] |
| rack.rb:98:3:107:5 | call | rack.rb:98:12:98:14 | env | rack.rb:114:5:114:30 | call to [] |
| rack.rb:119:3:123:5 | call | rack.rb:119:12:119:14 | env | rack.rb:122:5:122:42 | call to [] |
| rack_apps.rb:6:3:12:5 | call | rack_apps.rb:6:12:6:14 | env | rack_apps.rb:10:12:10:34 | call to [] |
| rack_apps.rb:16:3:18:5 | call | rack_apps.rb:16:17:16:19 | env | rack_apps.rb:17:5:17:28 | call to [] |
| rack_apps.rb:21:14:21:50 | -> { ... } | rack_apps.rb:21:17:21:19 | env | rack_apps.rb:21:24:21:48 | call to [] |
@@ -16,3 +19,8 @@ rackResponseContentTypes
redirectResponses
| rack.rb:43:5:43:45 | call to [] | rack.rb:42:30:42:40 | "/foo.html" |
| rack.rb:93:5:93:78 | call to finish | rack.rb:93:60:93:70 | redirect_to |
requestInputAccesses
| rack.rb:100:18:100:28 | call to cookies |
| rack.rb:103:14:103:23 | call to params |
| rack.rb:104:18:104:32 | ...[...] |
| rack.rb:120:14:120:32 | ...[...] |

View File

@@ -1,4 +1,5 @@
private import codeql.ruby.AST
private import codeql.ruby.Concepts
private import codeql.ruby.frameworks.Rack
private import codeql.ruby.DataFlow
@@ -17,3 +18,5 @@ query predicate rackResponseContentTypes(
query predicate redirectResponses(Rack::Response::RedirectResponse resp, DataFlow::Node location) {
location = resp.getRedirectLocation()
}
query predicate requestInputAccesses(Http::Server::RequestInputAccess ria) { any() }

View File

@@ -63,14 +63,14 @@ class Baz
def run(env)
if env[:foo] == "foo"
[200, {}, "foo"]
[200, {}, ["foo"]]
else
error
end
end
def error
[400, {}, "nope"]
[400, {}, ["nope"]]
end
end
@@ -93,3 +93,32 @@ class Qux
Rack::Response.new(['redirecting'], 302, 'Location' => redirect_to).finish
end
end
class UsesRequest
def call(env)
req = Rack::Request.new(env)
if session = req.cookies['session']
reuse_session(session)
else
name = req.params['name']
password = req['password']
login(name, password)
end
end
def login(name, password)
[200, {}, "new session"]
end
def reuse_session(name, password)
[200, {}, "reuse session"]
end
end
class UsesEnvQueryParams
def call(env)
params = env['QUERY_STRING']
user = Rack::Utils.parse_query(params)["user"]
[200, {}, [lookup_user_profile(user)]]
end
end

View File

@@ -0,0 +1,59 @@
require 'libxml'
class FooController < ActionController::Base
def libxml_handler(event:, context:)
name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = LibXML::XML::Document.string(xml)
# GOOD: XPath query is not constructed from user input
results1 = doc.find_first('//foo')
# BAD: XPath query is constructed from user input
results2 = doc.find_first("//#{name}")
# GOOD: XPath query is not constructed from user input
results3 = doc.find('//foo')
# BAD: XPath query is constructed from user input
results4 = doc.find("//#{name}")
end
end
class BarController < ActionController::Base
def libxml_safe_handler(event:, context:)
safe_name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = REXML::Document.new(xml)
# GOOD: barrier guard prevents taint flow
safe_name = if ["foo", "foo2"].include? safe_name
safe_name
else
safe_name = "foo"
end
# GOOD: XPath query is not constructed from unsanitized user input
results5 = doc.find_first("//#{safe_name}")
# GOOD: XPath query is not constructed from unsanitized user input
results6 = doc.find("//#{safe_name}")
end
end

View File

@@ -0,0 +1,88 @@
require 'nokogiri'
class FooController < ActionController::Base
def nokogiri_handler(event:, context:)
name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = Nokogiri::XML.parse(xml)
# GOOD: XPath query is not constructed from user input
results1 = doc.at('//foo')
# BAD: XPath query is constructed from user input
results2 = doc.at("//#{name}")
# GOOD: XPath query is not constructed from user input
results3 = doc.xpath('//foo')
# BAD: XPath query is constructed from user input
results4 = doc.xpath("//#{name}")
# GOOD: XPath query is not constructed from user input
results5 = doc.at_xpath('//foo')
# BAD: XPath query is constructed from user input
results6 = doc.at_xpath("//#{name}")
# GOOD: XPath query is not constructed from user input
doc.xpath('//foo').each do |element|
puts element.text
end
# BAD: XPath query constructed from user input
doc.xpath("//#{name}").each do |element|
puts element.text
end
# GOOD: XPath query is not constructed from user input
doc.search('//foo').each do |element|
puts element.text
end
# BAD: XPath query constructed from user input
doc.search("//#{name}").each do |element|
puts element.text
end
end
end
class BarController < ActionController::Base
def nokogiri_safe_handler(event:, context:)
safe_name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = Nokogiri::XML.parse(xml)
# GOOD: barrier guard prevents taint flow
safe_name = if ["foo", "foo2"].include? safe_name
safe_name
else
safe_name = "foo"
end
# GOOD: XPath query is not constructed from unsanitized user input
results7 = doc.at("//#{safe_name}")
# GOOD: XPath query is not constructed from unsanitized user input
results8 = doc.xpath("//#{safe_name}")
# GOOD: XPath query is not constructed from unsanitized user input
results9 = doc.at_xpath("//#{safe_name}")
end
end

View File

@@ -0,0 +1,69 @@
require 'rexml'
class FooController < ActionController::Base
def rexml_handler(event:, context:)
name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = REXML::Document.new(xml)
# GOOD: XPath query is not constructed from user input
results1 = REXML::XPath.first(doc, "//foo")
# BAD: XPath query is constructed from user input
results2 = REXML::XPath.first(doc, "//#{name}")
# GOOD: XPath query is not constructed from user input
results3 = REXML::XPath.match(doc, "//foo", nil)
# BAD: XPath query is constructed from user input
results4 = REXML::XPath.match(doc, "//#{name}", nil)
# GOOD: XPath query is not constructed from user input
REXML::XPath.each(doc, "//foo") do |element|
puts element.text
end
# BAD: XPath query constructed from user input
REXML::XPath.each(doc, "//#{name}") do |element|
puts element.text
end
end
end
class BarController < ActionController::Base
def rexml_safe_handler(event:, context:)
safe_name = params[:user_name]
xml = <<-XML
<root>
<foo>bar</foo>
<password>THIS IS SECRET</password>
</root>
XML
# Parse the XML
doc = REXML::Document.new(xml)
# GOOD: barrier guard prevents taint flow
safe_name = if ["foo", "foo2"].include? safe_name
safe_name
else
safe_name = "foo"
end
# GOOD: XPath query is not constructed from unsanitized user input
results5 = REXML::XPath.first(doc, "//#{safe_name}")
# GOOD: XPath query is not constructed from unsanitized user input
results6 = REXML::XPath.match(doc, "//#{safe_name}", nil)
end
end

View File

@@ -0,0 +1,49 @@
edges
| LibxmlInjection.rb:5:5:5:8 | name | LibxmlInjection.rb:21:31:21:41 | "//#{...}" |
| LibxmlInjection.rb:5:5:5:8 | name | LibxmlInjection.rb:27:25:27:35 | "//#{...}" |
| LibxmlInjection.rb:5:12:5:17 | call to params | LibxmlInjection.rb:5:12:5:29 | ...[...] |
| LibxmlInjection.rb:5:12:5:29 | ...[...] | LibxmlInjection.rb:5:5:5:8 | name |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:21:23:21:33 | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:27:26:27:36 | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:33:29:33:39 | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:41:15:41:25 | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | NokogiriInjection.rb:51:16:51:26 | "//#{...}" |
| NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:5:12:5:29 | ...[...] |
| NokogiriInjection.rb:5:12:5:29 | ...[...] | NokogiriInjection.rb:5:5:5:8 | name |
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:21:40:21:50 | "//#{...}" |
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:27:40:27:50 | "//#{...}" |
| RexmlInjection.rb:5:5:5:8 | name | RexmlInjection.rb:35:28:35:38 | "//#{...}" |
| RexmlInjection.rb:5:12:5:17 | call to params | RexmlInjection.rb:5:12:5:29 | ...[...] |
| RexmlInjection.rb:5:12:5:29 | ...[...] | RexmlInjection.rb:5:5:5:8 | name |
nodes
| LibxmlInjection.rb:5:5:5:8 | name | semmle.label | name |
| LibxmlInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
| LibxmlInjection.rb:5:12:5:29 | ...[...] | semmle.label | ...[...] |
| LibxmlInjection.rb:21:31:21:41 | "//#{...}" | semmle.label | "//#{...}" |
| LibxmlInjection.rb:27:25:27:35 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:5:5:5:8 | name | semmle.label | name |
| NokogiriInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
| NokogiriInjection.rb:5:12:5:29 | ...[...] | semmle.label | ...[...] |
| NokogiriInjection.rb:21:23:21:33 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:27:26:27:36 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:33:29:33:39 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:41:15:41:25 | "//#{...}" | semmle.label | "//#{...}" |
| NokogiriInjection.rb:51:16:51:26 | "//#{...}" | semmle.label | "//#{...}" |
| RexmlInjection.rb:5:5:5:8 | name | semmle.label | name |
| RexmlInjection.rb:5:12:5:17 | call to params | semmle.label | call to params |
| RexmlInjection.rb:5:12:5:29 | ...[...] | semmle.label | ...[...] |
| RexmlInjection.rb:21:40:21:50 | "//#{...}" | semmle.label | "//#{...}" |
| RexmlInjection.rb:27:40:27:50 | "//#{...}" | semmle.label | "//#{...}" |
| RexmlInjection.rb:35:28:35:38 | "//#{...}" | semmle.label | "//#{...}" |
subpaths
#select
| LibxmlInjection.rb:21:31:21:41 | "//#{...}" | LibxmlInjection.rb:5:12:5:17 | call to params | LibxmlInjection.rb:21:31:21:41 | "//#{...}" | XPath expression depends on a $@. | LibxmlInjection.rb:5:12:5:17 | call to params | user-provided value |
| LibxmlInjection.rb:27:25:27:35 | "//#{...}" | LibxmlInjection.rb:5:12:5:17 | call to params | LibxmlInjection.rb:27:25:27:35 | "//#{...}" | XPath expression depends on a $@. | LibxmlInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:21:23:21:33 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:21:23:21:33 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:27:26:27:36 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:27:26:27:36 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:33:29:33:39 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:33:29:33:39 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:41:15:41:25 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:41:15:41:25 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| NokogiriInjection.rb:51:16:51:26 | "//#{...}" | NokogiriInjection.rb:5:12:5:17 | call to params | NokogiriInjection.rb:51:16:51:26 | "//#{...}" | XPath expression depends on a $@. | NokogiriInjection.rb:5:12:5:17 | call to params | user-provided value |
| RexmlInjection.rb:21:40:21:50 | "//#{...}" | RexmlInjection.rb:5:12:5:17 | call to params | RexmlInjection.rb:21:40:21:50 | "//#{...}" | XPath expression depends on a $@. | RexmlInjection.rb:5:12:5:17 | call to params | user-provided value |
| RexmlInjection.rb:27:40:27:50 | "//#{...}" | RexmlInjection.rb:5:12:5:17 | call to params | RexmlInjection.rb:27:40:27:50 | "//#{...}" | XPath expression depends on a $@. | RexmlInjection.rb:5:12:5:17 | call to params | user-provided value |
| RexmlInjection.rb:35:28:35:38 | "//#{...}" | RexmlInjection.rb:5:12:5:17 | call to params | RexmlInjection.rb:35:28:35:38 | "//#{...}" | XPath expression depends on a $@. | RexmlInjection.rb:5:12:5:17 | call to params | user-provided value |

View File

@@ -0,0 +1 @@
experimental/xpath-injection/XpathInjection.ql

View File

@@ -1,7 +1,7 @@
edges
| app/controllers/foo/stores_controller.rb:8:5:8:6 | dt | app/controllers/foo/stores_controller.rb:9:22:9:23 | dt |
| app/controllers/foo/stores_controller.rb:8:5:8:6 | dt | app/controllers/foo/stores_controller.rb:13:55:13:56 | dt |
| app/controllers/foo/stores_controller.rb:8:10:8:29 | call to read | app/controllers/foo/stores_controller.rb:8:5:8:6 | dt |
| app/controllers/foo/stores_controller.rb:9:22:9:23 | dt | app/controllers/foo/stores_controller.rb:13:55:13:56 | dt |
| app/controllers/foo/stores_controller.rb:9:22:9:23 | dt | app/views/foo/stores/show.html.erb:37:3:37:16 | @instance_text |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt | app/views/foo/stores/show.html.erb:2:9:2:20 | call to display_text |
| app/controllers/foo/stores_controller.rb:13:55:13:56 | dt | app/views/foo/stores/show.html.erb:5:9:5:21 | call to local_assigns [element :display_text] |