Skip to content

Commit e803e98

Browse files
authored
Merge pull request #13585 from alexrford/rb/rack-env-query-string
Ruby: add rack `env['QUERY_STRING']` as a remote flow input
2 parents a1aa16f + 27ee72c commit e803e98

File tree

4 files changed

+35
-4
lines changed

4 files changed

+35
-4
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The `'QUERY_STRING'` field of a Rack `env` parameter is now recognized as a source of remote user input.

ruby/ql/lib/codeql/ruby/frameworks/rack/internal/App.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
private import codeql.ruby.AST
66
private import codeql.ruby.ApiGraphs
7+
private import codeql.ruby.Concepts
78
private import codeql.ruby.DataFlow
89
private import codeql.ruby.typetracking.TypeTracker
910
private import Response::Private as RP
@@ -77,4 +78,20 @@ module App {
7778
/** Gets a response returned from this request handler. */
7879
RP::PotentialResponseNode getAResponse() { result = resp }
7980
}
81+
82+
/** A read of the query string via `env['QUERY_STRING']`. */
83+
private class EnvQueryStringRead extends Http::Server::RequestInputAccess::Range {
84+
EnvQueryStringRead() {
85+
this =
86+
any(RequestHandler h)
87+
.getEnv()
88+
.getAnElementRead(ConstantValue::fromStringlikeValue("QUERY_STRING"))
89+
}
90+
91+
override string getSourceType() { result = "Rack env" }
92+
93+
override Http::Server::RequestInputKind getKind() {
94+
result = Http::Server::parameterInputKind()
95+
}
96+
}
8097
}

ruby/ql/test/library-tests/frameworks/rack/Rack.expected

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ rackRequestHandlers
33
| rack.rb:17:3:21:5 | call | rack.rb:17:12:17:18 | the_env | rack.rb:20:5:20:27 | call to [] |
44
| rack.rb:30:3:36:5 | call | rack.rb:30:12:30:14 | env | rack.rb:35:5:35:26 | call to [] |
55
| rack.rb:40:3:44:5 | call | rack.rb:40:12:40:14 | env | rack.rb:43:5:43:45 | call to [] |
6-
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:66:7:66:22 | call to [] |
7-
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:73:5:73:21 | call to [] |
6+
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:66:7:66:24 | call to [] |
7+
| rack.rb:60:3:62:5 | call | rack.rb:60:12:60:14 | env | rack.rb:73:5:73:23 | call to [] |
88
| rack.rb:79:3:81:5 | call | rack.rb:79:17:79:19 | env | rack.rb:93:5:93:78 | call to finish |
99
| rack.rb:98:3:107:5 | call | rack.rb:98:12:98:14 | env | rack.rb:110:5:110:28 | call to [] |
1010
| rack.rb:98:3:107:5 | call | rack.rb:98:12:98:14 | env | rack.rb:114:5:114:30 | call to [] |
11+
| rack.rb:119:3:123:5 | call | rack.rb:119:12:119:14 | env | rack.rb:122:5:122:42 | call to [] |
1112
| 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 [] |
1213
| 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 [] |
1314
| rack_apps.rb:21:14:21:50 | -> { ... } | rack_apps.rb:21:17:21:19 | env | rack_apps.rb:21:24:21:48 | call to [] |
@@ -22,3 +23,4 @@ requestInputAccesses
2223
| rack.rb:100:18:100:28 | call to cookies |
2324
| rack.rb:103:14:103:23 | call to params |
2425
| rack.rb:104:18:104:32 | ...[...] |
26+
| rack.rb:120:14:120:32 | ...[...] |

ruby/ql/test/library-tests/frameworks/rack/rack.rb

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ def call(env)
6363

6464
def run(env)
6565
if env[:foo] == "foo"
66-
[200, {}, "foo"]
66+
[200, {}, ["foo"]]
6767
else
6868
error
6969
end
7070
end
7171

7272
def error
73-
[400, {}, "nope"]
73+
[400, {}, ["nope"]]
7474
end
7575
end
7676

@@ -114,3 +114,11 @@ def reuse_session(name, password)
114114
[200, {}, "reuse session"]
115115
end
116116
end
117+
118+
class UsesEnvQueryParams
119+
def call(env)
120+
params = env['QUERY_STRING']
121+
user = Rack::Utils.parse_query(params)["user"]
122+
[200, {}, [lookup_user_profile(user)]]
123+
end
124+
end

0 commit comments

Comments
 (0)