Merge pull request #10602 from hmac/hmac/actiondispatch-request

Ruby: Model ActionDispatch::Request
This commit is contained in:
Harry Maclean 2022-10-14 22:17:20 +13:00 коммит произвёл GitHub
Родитель 5ce4483a8e e6dc27a7b5
Коммит 7d23170fb2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
14 изменённых файлов: 424 добавлений и 21 удалений

Просмотреть файл

@ -0,0 +1,5 @@
---
category: minorAnalysis
---
* More sources of remote input arising from methods on `ActionDispatch::Request`
are now recognised.

Просмотреть файл

@ -290,6 +290,26 @@ module Http {
}
}
/** A kind of request input. */
class RequestInputKind extends string {
RequestInputKind() { this = ["parameter", "header", "body", "url", "cookie"] }
}
/** Input from the parameters of a request. */
RequestInputKind parameterInputKind() { result = "parameter" }
/** Input from the headers of a request. */
RequestInputKind headerInputKind() { result = "header" }
/** Input from the body of a request. */
RequestInputKind bodyInputKind() { result = "body" }
/** Input from the URL of a request. */
RequestInputKind urlInputKind() { result = "url" }
/** Input from the cookies of a request. */
RequestInputKind cookieInputKind() { result = "cookie" }
/**
* An access to a user-controlled HTTP request input. For example, the URL or body of a request.
* Instances of this class automatically become `RemoteFlowSource`s.
@ -304,6 +324,32 @@ module Http {
* This is typically the name of the method that gives rise to this input.
*/
string getSourceType() { result = super.getSourceType() }
/**
* Gets the kind of the accessed input,
* Can be one of "parameter", "header", "body", "url", "cookie".
*/
RequestInputKind getKind() { result = super.getKind() }
/**
* Holds if this part of the request may be controlled by a third party,
* that is, an agent other than the one who sent the request.
*
* This is true for the URL, query parameters, and request body.
* These can be controlled by a malicious third party in the following scenarios:
*
* - The user clicks a malicious link or is otherwise redirected to a malicious URL.
* - The user visits a web site that initiates a form submission or AJAX request on their behalf.
*
* In these cases, the request is technically sent from the user's browser, but
* the user is not in direct control of the URL or POST body.
*
* Headers are never considered third-party controllable by this predicate, although the
* third party does have some control over the the Referer and Origin headers.
*/
predicate isThirdPartyControllable() {
this.getKind() = [parameterInputKind(), urlInputKind(), bodyInputKind()]
}
}
/** Provides a class for modeling new HTTP request inputs. */
@ -321,6 +367,12 @@ module Http {
* This is typically the name of the method that gives rise to this input.
*/
abstract string getSourceType();
/**
* Gets the kind of the accessed input,
* Can be one of "parameter", "header", "body", "url", "cookie".
*/
abstract RequestInputKind getKind();
}
}
@ -387,6 +439,8 @@ module Http {
RoutedParameter() { this.getParameter() = handler.getARoutedParameter() }
override string getSourceType() { result = handler.getFramework() + " RoutedParameter" }
override RequestInputKind getKind() { result = parameterInputKind() }
}
/**

Просмотреть файл

@ -139,6 +139,8 @@ class ParamsSource extends Http::Server::RequestInputAccess::Range {
ParamsSource() { this.asExpr().getExpr() instanceof Rails::ParamsCall }
override string getSourceType() { result = "ActionController::Metal#params" }
override Http::Server::RequestInputKind getKind() { result = Http::Server::parameterInputKind() }
}
/**
@ -149,6 +151,8 @@ class CookiesSource extends Http::Server::RequestInputAccess::Range {
CookiesSource() { this.asExpr().getExpr() instanceof Rails::CookiesCall }
override string getSourceType() { result = "ActionController::Metal#cookies" }
override Http::Server::RequestInputKind getKind() { result = Http::Server::cookieInputKind() }
}
/** A call to `cookies` from within a controller. */
@ -161,6 +165,140 @@ private class ActionControllerParamsCall extends ActionControllerContextCall, Pa
ActionControllerParamsCall() { this.getMethodName() = "params" }
}
/** Modeling for `ActionDispatch::Request`. */
private module Request {
/**
* A call to `request` from within a controller. This is an instance of
* `ActionDispatch::Request`.
*/
private class RequestNode extends DataFlow::CallNode {
RequestNode() {
this.asExpr().getExpr() instanceof ActionControllerContextCall and
this.getMethodName() = "request"
}
}
/**
* A method call on `request`.
*/
private class RequestMethodCall extends DataFlow::CallNode {
RequestMethodCall() {
any(RequestNode r).(DataFlow::LocalSourceNode).flowsTo(this.getReceiver())
}
}
abstract private class RequestInputAccess extends RequestMethodCall,
Http::Server::RequestInputAccess::Range {
override string getSourceType() { result = "ActionDispatch::Request#" + this.getMethodName() }
}
/**
* A method call on `request` which returns request parameters.
*/
private class ParametersCall extends RequestInputAccess {
ParametersCall() {
this.getMethodName() =
[
"parameters", "params", "GET", "POST", "query_parameters", "request_parameters",
"filtered_parameters"
]
}
override Http::Server::RequestInputKind getKind() {
result = Http::Server::parameterInputKind()
}
}
/** A method call on `request` which returns part or all of the request path. */
private class PathCall extends RequestInputAccess {
PathCall() {
this.getMethodName() =
["path", "filtered_path", "fullpath", "original_fullpath", "original_url", "url"]
}
override Http::Server::RequestInputKind getKind() { result = Http::Server::urlInputKind() }
}
/** A method call on `request` which returns a specific request header. */
private class HeadersCall extends RequestInputAccess {
HeadersCall() {
this.getMethodName() =
[
"authorization", "script_name", "path_info", "user_agent", "referer", "referrer",
"host_authority", "content_type", "host", "hostname", "accept_encoding",
"accept_language", "if_none_match", "if_none_match_etags", "content_mime_type"
]
or
// Request headers are prefixed with `HTTP_` to distinguish them from
// "headers" supplied by Rack middleware.
this.getMethodName() = ["get_header", "fetch_header"] and
this.getArgument(0).asExpr().getExpr().getConstantValue().getString().regexpMatch("^HTTP_.+")
}
override Http::Server::RequestInputKind getKind() { result = Http::Server::headerInputKind() }
}
// TODO: each_header
/**
* A method call on `request` which returns part or all of the host.
* This can be influenced by headers such as Host and X-Forwarded-Host.
*/
private class HostCall extends RequestInputAccess {
HostCall() {
this.getMethodName() =
[
"authority", "host", "host_authority", "host_with_port", "hostname", "forwarded_for",
"forwarded_host", "port", "forwarded_port"
]
}
override Http::Server::RequestInputKind getKind() { result = Http::Server::headerInputKind() }
}
/**
* A method call on `request` which is influenced by one or more request
* headers.
*/
private class HeaderTaintedCall extends RequestInputAccess {
HeaderTaintedCall() {
this.getMethodName() = ["media_type", "media_type_params", "content_charset", "base_url"]
}
override Http::Server::RequestInputKind getKind() { result = Http::Server::headerInputKind() }
}
/** A method call on `request` which returns the request body. */
private class BodyCall extends RequestInputAccess {
BodyCall() { this.getMethodName() = ["body", "raw_post"] }
override Http::Server::RequestInputKind getKind() { result = Http::Server::bodyInputKind() }
}
/**
* A method call on `request` which returns the rack env.
* This is a hash containing all the information about the request. Values
* under keys starting with `HTTP_` are user-controlled.
*/
private class EnvCall extends RequestMethodCall {
EnvCall() { this.getMethodName() = ["env", "filtered_env"] }
}
/**
* A read of a user-controlled parameter from the request env.
*/
private class EnvHttpAccess extends DataFlow::CallNode, Http::Server::RequestInputAccess::Range {
EnvHttpAccess() {
any(EnvCall c).(DataFlow::LocalSourceNode).flowsTo(this.getReceiver()) and
this.getMethodName() = "[]" and
this.getArgument(0).asExpr().getExpr().getConstantValue().getString().regexpMatch("^HTTP_.+")
}
override Http::Server::RequestInputKind getKind() { result = Http::Server::headerInputKind() }
override string getSourceType() { result = "ActionDispatch::Request#env[]" }
}
}
/** A call to `render` from within a controller. */
private class ActionControllerRenderCall extends ActionControllerContextCall, RenderCallImpl {
ActionControllerRenderCall() { this.getMethodName() = "render" }

Просмотреть файл

@ -50,7 +50,9 @@ module UrlRedirect {
/**
* A source of remote user input, considered as a flow source.
*/
class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { }
class HttpRequestInputAccessAsSource extends Source, Http::Server::RequestInputAccess {
HttpRequestInputAccessAsSource() { this.isThirdPartyControllable() }
}
/**
* A HTTP redirect response, considered as a flow sink.

Просмотреть файл

@ -312,9 +312,11 @@ module ReflectedXss {
deprecated predicate isAdditionalXSSTaintStep = isAdditionalXssTaintStep/2;
/**
* A source of remote user input, considered as a flow source.
* A HTTP request input, considered as a flow source.
*/
class RemoteFlowSourceAsSource extends Source, RemoteFlowSource { }
class HttpRequestInputAccessAsSource extends Source, Http::Server::RequestInputAccess {
HttpRequestInputAccessAsSource() { this.isThirdPartyControllable() }
}
}
/** DEPRECATED: Alias for ReflectedXss */

Просмотреть файл

@ -1,17 +1,19 @@
actionControllerControllerClasses
| action_controller/input_access.rb:1:1:50:3 | UsersController |
| action_controller/params_flow.rb:1:1:151:3 | MyController |
| active_record/ActiveRecord.rb:23:1:39:3 | FooController |
| active_record/ActiveRecord.rb:41:1:64:3 | BarController |
| active_record/ActiveRecord.rb:66:1:98:3 | BazController |
| active_record/ActiveRecord.rb:100:1:108:3 | AnnotatedController |
| active_storage/active_storage.rb:39:1:45:3 | PostsController |
| app/controllers/comments_controller.rb:1:1:7:3 | CommentsController |
| app/controllers/comments_controller.rb:1:1:14:3 | CommentsController |
| app/controllers/foo/bars_controller.rb:3:1:46:3 | BarsController |
| app/controllers/photos_controller.rb:1:1:4:3 | PhotosController |
| app/controllers/posts_controller.rb:1:1:10:3 | PostsController |
| app/controllers/tags_controller.rb:1:1:2:3 | TagsController |
| app/controllers/users/notifications_controller.rb:2:3:5:5 | NotificationsController |
actionControllerActionMethods
| action_controller/input_access.rb:2:3:49:5 | index |
| action_controller/params_flow.rb:2:3:4:5 | m1 |
| action_controller/params_flow.rb:6:3:8:5 | m2 |
| action_controller/params_flow.rb:10:3:12:5 | m2 |
@ -59,8 +61,8 @@ actionControllerActionMethods
| active_record/ActiveRecord.rb:101:3:103:5 | index |
| active_record/ActiveRecord.rb:105:3:107:5 | unsafe_action |
| active_storage/active_storage.rb:40:3:44:5 | create |
| app/controllers/comments_controller.rb:2:3:3:5 | index |
| app/controllers/comments_controller.rb:5:3:6:5 | show |
| app/controllers/comments_controller.rb:2:3:10:5 | index |
| app/controllers/comments_controller.rb:12:3:13:5 | show |
| app/controllers/foo/bars_controller.rb:5:3:7:5 | index |
| app/controllers/foo/bars_controller.rb:9:3:18:5 | show_debug |
| app/controllers/foo/bars_controller.rb:20:3:24:5 | show |
@ -222,6 +224,137 @@ paramsSources
| app/controllers/foo/bars_controller.rb:21:21:21:26 | call to params |
| app/controllers/foo/bars_controller.rb:22:10:22:15 | call to params |
| app/views/foo/bars/show.html.erb:5:9:5:14 | call to params |
httpInputAccesses
| action_controller/input_access.rb:3:5:3:18 | call to params | ActionDispatch::Request#params |
| action_controller/input_access.rb:4:5:4:22 | call to parameters | ActionDispatch::Request#parameters |
| action_controller/input_access.rb:5:5:5:15 | call to GET | ActionDispatch::Request#GET |
| action_controller/input_access.rb:6:5:6:16 | call to POST | ActionDispatch::Request#POST |
| action_controller/input_access.rb:7:5:7:28 | call to query_parameters | ActionDispatch::Request#query_parameters |
| action_controller/input_access.rb:8:5:8:30 | call to request_parameters | ActionDispatch::Request#request_parameters |
| action_controller/input_access.rb:9:5:9:31 | call to filtered_parameters | ActionDispatch::Request#filtered_parameters |
| action_controller/input_access.rb:11:5:11:25 | call to authorization | ActionDispatch::Request#authorization |
| action_controller/input_access.rb:12:5:12:23 | call to script_name | ActionDispatch::Request#script_name |
| action_controller/input_access.rb:13:5:13:21 | call to path_info | ActionDispatch::Request#path_info |
| action_controller/input_access.rb:14:5:14:22 | call to user_agent | ActionDispatch::Request#user_agent |
| action_controller/input_access.rb:15:5:15:19 | call to referer | ActionDispatch::Request#referer |
| action_controller/input_access.rb:16:5:16:20 | call to referrer | ActionDispatch::Request#referrer |
| action_controller/input_access.rb:17:5:17:26 | call to host_authority | ActionDispatch::Request#host_authority |
| action_controller/input_access.rb:18:5:18:24 | call to content_type | ActionDispatch::Request#content_type |
| action_controller/input_access.rb:19:5:19:16 | call to host | ActionDispatch::Request#host |
| action_controller/input_access.rb:20:5:20:20 | call to hostname | ActionDispatch::Request#hostname |
| action_controller/input_access.rb:21:5:21:27 | call to accept_encoding | ActionDispatch::Request#accept_encoding |
| action_controller/input_access.rb:22:5:22:27 | call to accept_language | ActionDispatch::Request#accept_language |
| action_controller/input_access.rb:23:5:23:25 | call to if_none_match | ActionDispatch::Request#if_none_match |
| action_controller/input_access.rb:24:5:24:31 | call to if_none_match_etags | ActionDispatch::Request#if_none_match_etags |
| action_controller/input_access.rb:25:5:25:29 | call to content_mime_type | ActionDispatch::Request#content_mime_type |
| action_controller/input_access.rb:27:5:27:21 | call to authority | ActionDispatch::Request#authority |
| action_controller/input_access.rb:28:5:28:16 | call to host | ActionDispatch::Request#host |
| action_controller/input_access.rb:29:5:29:26 | call to host_authority | ActionDispatch::Request#host_authority |
| action_controller/input_access.rb:30:5:30:26 | call to host_with_port | ActionDispatch::Request#host_with_port |
| action_controller/input_access.rb:31:5:31:20 | call to hostname | ActionDispatch::Request#hostname |
| action_controller/input_access.rb:32:5:32:25 | call to forwarded_for | ActionDispatch::Request#forwarded_for |
| action_controller/input_access.rb:33:5:33:26 | call to forwarded_host | ActionDispatch::Request#forwarded_host |
| action_controller/input_access.rb:34:5:34:16 | call to port | ActionDispatch::Request#port |
| action_controller/input_access.rb:35:5:35:26 | call to forwarded_port | ActionDispatch::Request#forwarded_port |
| action_controller/input_access.rb:37:5:37:22 | call to media_type | ActionDispatch::Request#media_type |
| action_controller/input_access.rb:38:5:38:29 | call to media_type_params | ActionDispatch::Request#media_type_params |
| action_controller/input_access.rb:39:5:39:27 | call to content_charset | ActionDispatch::Request#content_charset |
| action_controller/input_access.rb:40:5:40:20 | call to base_url | ActionDispatch::Request#base_url |
| action_controller/input_access.rb:42:5:42:16 | call to body | ActionDispatch::Request#body |
| action_controller/input_access.rb:43:5:43:20 | call to raw_post | ActionDispatch::Request#raw_post |
| action_controller/input_access.rb:45:5:45:30 | ...[...] | ActionDispatch::Request#env[] |
| action_controller/input_access.rb:47:5:47:39 | ...[...] | ActionDispatch::Request#env[] |
| action_controller/params_flow.rb:3:10:3:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:7:10:7:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:11:10:11:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:15:10:15:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:19:10:19:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:23:10:23:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:27:10:27:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:31:10:31:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:35:10:35:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:39:10:39:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:43:10:43:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:47:10:47:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:51:10:51:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:55:10:55:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:59:10:59:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:63:10:63:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:67:10:67:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:71:10:71:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:75:10:75:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:79:10:79:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:83:10:83:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:87:10:87:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:91:10:91:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:95:10:95:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:99:10:99:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:103:10:103:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:107:10:107:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:111:10:111:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:112:23:112:28 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:116:10:116:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:117:31:117:36 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:121:10:121:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:122:31:122:36 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:126:10:126:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:127:24:127:29 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:130:14:130:19 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:135:10:135:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:136:32:136:37 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:139:22:139:27 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:144:10:144:15 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:145:32:145:37 | call to params | ActionController::Metal#params |
| action_controller/params_flow.rb:148:22:148:27 | call to params | ActionController::Metal#params |
| action_mailer/mailer.rb:3:10:3:15 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:28:30:28:35 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:29:29:29:34 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:30:31:30:36 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:32:21:32:26 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:34:34:34:39 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:35:23:35:28 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:35:38:35:43 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:43:10:43:15 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:50:11:50:16 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:54:12:54:17 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:59:12:59:17 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:62:15:62:20 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:68:21:68:26 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:72:18:72:23 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:76:24:76:29 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:76:49:76:54 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:80:25:80:30 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:80:50:80:55 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:88:21:88:26 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:92:27:92:32 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:92:52:92:57 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:96:28:96:33 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:96:53:96:58 | call to params | ActionController::Metal#params |
| active_record/ActiveRecord.rb:106:59:106:64 | call to params | ActionController::Metal#params |
| active_storage/active_storage.rb:41:21:41:26 | call to params | ActionController::Metal#params |
| active_storage/active_storage.rb:42:24:42:29 | call to params | ActionController::Metal#params |
| app/controllers/comments_controller.rb:3:5:3:18 | call to params | ActionDispatch::Request#params |
| app/controllers/comments_controller.rb:4:5:4:22 | call to parameters | ActionDispatch::Request#parameters |
| app/controllers/comments_controller.rb:5:5:5:15 | call to GET | ActionDispatch::Request#GET |
| app/controllers/comments_controller.rb:6:5:6:16 | call to POST | ActionDispatch::Request#POST |
| app/controllers/comments_controller.rb:7:5:7:28 | call to query_parameters | ActionDispatch::Request#query_parameters |
| app/controllers/comments_controller.rb:8:5:8:30 | call to request_parameters | ActionDispatch::Request#request_parameters |
| app/controllers/comments_controller.rb:9:5:9:31 | call to filtered_parameters | ActionDispatch::Request#filtered_parameters |
| app/controllers/foo/bars_controller.rb:10:27:10:33 | call to cookies | ActionController::Metal#cookies |
| app/controllers/foo/bars_controller.rb:13:21:13:26 | call to params | ActionController::Metal#params |
| app/controllers/foo/bars_controller.rb:14:10:14:15 | call to params | ActionController::Metal#params |
| app/controllers/foo/bars_controller.rb:21:21:21:26 | call to params | ActionController::Metal#params |
| app/controllers/foo/bars_controller.rb:22:10:22:15 | call to params | ActionController::Metal#params |
| app/graphql/mutations/dummy.rb:5:24:5:25 | id | GraphQL RoutedParameter |
| app/graphql/mutations/dummy.rb:9:17:9:25 | something | GraphQL RoutedParameter |
| app/graphql/resolvers/dummy_resolver.rb:6:24:6:25 | id | GraphQL RoutedParameter |
| app/graphql/resolvers/dummy_resolver.rb:10:17:10:25 | something | GraphQL RoutedParameter |
| app/graphql/types/query_type.rb:10:18:10:23 | number | GraphQL RoutedParameter |
| app/graphql/types/query_type.rb:18:23:18:33 | blah_number | GraphQL RoutedParameter |
| app/graphql/types/query_type.rb:27:20:27:25 | **args | GraphQL RoutedParameter |
| app/graphql/types/query_type.rb:36:34:36:37 | arg1 | GraphQL RoutedParameter |
| app/graphql/types/query_type.rb:36:41:36:46 | **rest | GraphQL RoutedParameter |
| app/views/foo/bars/show.html.erb:5:9:5:14 | call to params | ActionController::Metal#params |
cookiesCalls
| app/controllers/foo/bars_controller.rb:10:27:10:33 | call to cookies |
cookiesSources

Просмотреть файл

@ -1,6 +1,8 @@
private import codeql.ruby.AST
private import codeql.ruby.frameworks.ActionController
private import codeql.ruby.frameworks.Rails
private import codeql.ruby.frameworks.ActionView
private import codeql.ruby.Concepts
query predicate actionControllerControllerClasses(ActionControllerControllerClass cls) { any() }
@ -10,6 +12,10 @@ query predicate paramsCalls(Rails::ParamsCall c) { any() }
query predicate paramsSources(ParamsSource src) { any() }
query predicate httpInputAccesses(Http::Server::RequestInputAccess a, string sourceType) {
sourceType = a.getSourceType()
}
query predicate cookiesCalls(Rails::CookiesCall c) { any() }
query predicate cookiesSources(CookiesSource src) { any() }

Просмотреть файл

@ -36,8 +36,8 @@ actionDispatchRoutes
actionDispatchControllerMethods
| app/config/routes.rb:2:3:8:5 | call to resources | app/controllers/posts_controller.rb:2:3:3:5 | index |
| app/config/routes.rb:2:3:8:5 | call to resources | app/controllers/posts_controller.rb:5:3:6:5 | show |
| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:2:3:3:5 | index |
| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:5:3:6:5 | show |
| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:2:3:10:5 | index |
| app/config/routes.rb:3:5:6:7 | call to resources | app/controllers/comments_controller.rb:12:3:13:5 | show |
| app/config/routes.rb:7:5:7:37 | call to post | app/controllers/posts_controller.rb:8:3:9:5 | upvote |
| app/config/routes.rb:27:3:27:48 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show |
| app/config/routes.rb:28:3:28:50 | call to match | app/controllers/photos_controller.rb:2:3:3:5 | show |

Просмотреть файл

@ -0,0 +1,50 @@
class UsersController < ActionController::Base
def index
request.params
request.parameters
request.GET
request.POST
request.query_parameters
request.request_parameters
request.filtered_parameters
request.authorization
request.script_name
request.path_info
request.user_agent
request.referer
request.referrer
request.host_authority
request.content_type
request.host
request.hostname
request.accept_encoding
request.accept_language
request.if_none_match
request.if_none_match_etags
request.content_mime_type
request.authority
request.host
request.host_authority
request.host_with_port
request.hostname
request.forwarded_for
request.forwarded_host
request.port
request.forwarded_port
request.media_type
request.media_type_params
request.content_charset
request.base_url
request.body
request.raw_post
request.env["HTTP_ACCEPT"]
request.env["NOT_USER_CONTROLLED"]
request.filtered_env["HTTP_ACCEPT"]
request.filtered_env["NOT_USER_CONTROLLED"]
end
end

Просмотреть файл

@ -1,7 +1,14 @@
class CommentsController < ApplicationController
def index
request.params
request.parameters
request.GET
request.POST
request.query_parameters
request.request_parameters
request.filtered_parameters
end
def show
end
end
end

Просмотреть файл

@ -10,13 +10,13 @@ edges
| app/controllers/foo/bars_controller.rb:17:21:17:36 | ...[...] : | app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website |
| app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] : |
| app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] : | app/controllers/foo/bars_controller.rb:19:22:19:23 | dt : |
| app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] : | app/controllers/foo/bars_controller.rb:23:53:23:54 | dt : |
| app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] : | app/controllers/foo/bars_controller.rb:24:53:24:54 | dt : |
| app/controllers/foo/bars_controller.rb:19:22:19:23 | dt : | app/views/foo/bars/show.html.erb:41:3:41:16 | @instance_text |
| app/controllers/foo/bars_controller.rb:23:53:23:54 | dt : | app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text |
| app/controllers/foo/bars_controller.rb:23:53:23:54 | dt : | app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] |
| app/controllers/foo/bars_controller.rb:23:53:23:54 | dt : | app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] |
| app/controllers/foo/bars_controller.rb:23:53:23:54 | dt : | app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text |
| app/controllers/foo/bars_controller.rb:23:53:23:54 | dt : | app/views/foo/bars/show.html.erb:44:76:44:87 | call to display_text : |
| app/controllers/foo/bars_controller.rb:24:53:24:54 | dt : | app/views/foo/bars/show.html.erb:5:9:5:20 | call to display_text |
| app/controllers/foo/bars_controller.rb:24:53:24:54 | dt : | app/views/foo/bars/show.html.erb:8:9:8:36 | ...[...] |
| app/controllers/foo/bars_controller.rb:24:53:24:54 | dt : | app/views/foo/bars/show.html.erb:12:9:12:26 | ...[...] |
| app/controllers/foo/bars_controller.rb:24:53:24:54 | dt : | app/views/foo/bars/show.html.erb:36:3:36:14 | call to display_text |
| app/controllers/foo/bars_controller.rb:24:53:24:54 | dt : | app/views/foo/bars/show.html.erb:44:76:44:87 | call to display_text : |
| app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text |
| app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : | app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] |
| app/views/foo/bars/show.html.erb:44:76:44:87 | call to display_text : | app/views/foo/bars/show.html.erb:44:64:44:87 | ... + ... : |
@ -35,7 +35,7 @@ nodes
| app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params : | semmle.label | call to params : |
| app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] : | semmle.label | ...[...] : |
| app/controllers/foo/bars_controller.rb:19:22:19:23 | dt : | semmle.label | dt : |
| app/controllers/foo/bars_controller.rb:23:53:23:54 | dt : | semmle.label | dt : |
| app/controllers/foo/bars_controller.rb:24:53:24:54 | dt : | semmle.label | dt : |
| app/views/foo/bars/_widget.html.erb:5:9:5:20 | call to display_text | semmle.label | call to display_text |
| app/views/foo/bars/_widget.html.erb:8:9:8:36 | ...[...] | semmle.label | ...[...] |
| app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website | semmle.label | @user_website |

Просмотреть файл

@ -20,6 +20,7 @@ class BarsController < ApplicationController
@safe_foo = params[:text]
@safe_foo = "safe_foo"
@html_escaped = ERB::Util.html_escape(params[:text])
@header_escaped = ERB::Util.html_escape(cookies[:foo]) # OK - cookies not controllable by 3rd party
render "foo/bars/show", locals: { display_text: dt, safe_text: "hello" }
end
end

Просмотреть файл

@ -3,14 +3,14 @@ edges
| UrlRedirect.rb:14:17:14:22 | call to params : | UrlRedirect.rb:14:17:14:43 | call to fetch |
| UrlRedirect.rb:19:17:19:22 | call to params : | UrlRedirect.rb:19:17:19:37 | call to to_unsafe_hash |
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:24:17:24:37 | call to filter_params |
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:88:21:88:32 | input_params : |
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:93:21:93:32 | input_params : |
| UrlRedirect.rb:34:20:34:25 | call to params : | UrlRedirect.rb:34:20:34:31 | ...[...] : |
| UrlRedirect.rb:34:20:34:31 | ...[...] : | UrlRedirect.rb:34:17:34:37 | "#{...}/foo" |
| UrlRedirect.rb:58:17:58:22 | call to params : | UrlRedirect.rb:58:17:58:28 | ...[...] |
| UrlRedirect.rb:63:38:63:43 | call to params : | UrlRedirect.rb:63:38:63:49 | ...[...] |
| UrlRedirect.rb:68:38:68:43 | call to params : | UrlRedirect.rb:68:38:68:49 | ...[...] |
| UrlRedirect.rb:73:25:73:30 | call to params : | UrlRedirect.rb:73:25:73:36 | ...[...] |
| UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : |
| UrlRedirect.rb:93:21:93:32 | input_params : | UrlRedirect.rb:94:5:94:29 | call to permit : |
nodes
| UrlRedirect.rb:4:17:4:22 | call to params | semmle.label | call to params |
| UrlRedirect.rb:9:17:9:22 | call to params : | semmle.label | call to params : |
@ -32,10 +32,10 @@ nodes
| UrlRedirect.rb:68:38:68:49 | ...[...] | semmle.label | ...[...] |
| UrlRedirect.rb:73:25:73:30 | call to params : | semmle.label | call to params : |
| UrlRedirect.rb:73:25:73:36 | ...[...] | semmle.label | ...[...] |
| UrlRedirect.rb:88:21:88:32 | input_params : | semmle.label | input_params : |
| UrlRedirect.rb:89:5:89:29 | call to permit : | semmle.label | call to permit : |
| UrlRedirect.rb:93:21:93:32 | input_params : | semmle.label | input_params : |
| UrlRedirect.rb:94:5:94:29 | call to permit : | semmle.label | call to permit : |
subpaths
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:88:21:88:32 | input_params : | UrlRedirect.rb:89:5:89:29 | call to permit : | UrlRedirect.rb:24:17:24:37 | call to filter_params |
| UrlRedirect.rb:24:31:24:36 | call to params : | UrlRedirect.rb:93:21:93:32 | input_params : | UrlRedirect.rb:94:5:94:29 | call to permit : | UrlRedirect.rb:24:17:24:37 | call to filter_params |
#select
| UrlRedirect.rb:4:17:4:22 | call to params | UrlRedirect.rb:4:17:4:22 | call to params | UrlRedirect.rb:4:17:4:22 | call to params | Untrusted URL redirection depends on a $@. | UrlRedirect.rb:4:17:4:22 | call to params | user-provided value |
| UrlRedirect.rb:9:17:9:28 | ...[...] | UrlRedirect.rb:9:17:9:22 | call to params : | UrlRedirect.rb:9:17:9:28 | ...[...] | Untrusted URL redirection depends on a $@. | UrlRedirect.rb:9:17:9:22 | call to params | user-provided value |

Просмотреть файл

@ -83,6 +83,11 @@ class UsersController < ActionController::Base
redirect_back_or_to params[:key], allow_other_host: false
end
# GOOD
def route15
redirect_to cookies[:foo]
end
private
def filter_params(input_params)