Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Log for which keys values were set to nil in deep_munge #13813

Merged
merged 1 commit into from

5 participants

@lukesarnacki

I think we all want deep_munge to be gone soon, but I am afraid that we will have to wait little bit longer. There are many developers which are not aware of this behaviour so I thought that it would be nice of RoR if there was some kind of hint of what actually happened, so I added log message when value is set to nil in deep_munge.

I hope that with #13420 we will quickly make code from this PR go away, but in case it will take bit longer...

Any suggestions for better log message would be awesome.

actionpack/CHANGELOG.md
@@ -1,3 +1,11 @@
+* Log which keys were affected by deep munge
@rafaelfranca Owner

.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
actionpack/CHANGELOG.md
@@ -1,3 +1,11 @@
+* Log which keys were affected by deep munge
+
+ Deep munge solves CVE-2013-0155 security vulnerability, but its
+ behaviour is definately confuisng, so now at least information
@rafaelfranca Owner

confuisng => confusing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
actionpack/CHANGELOG.md
@@ -1,3 +1,11 @@
+* Log which keys were affected by deep munge
+
+ Deep munge solves CVE-2013-0155 security vulnerability, but its
+ behaviour is definately confuisng, so now at least information
+ about for which keys values were set to nil is visible in logs.
+
+ Lukasz Sarnacki
@rafaelfranca Owner

*Lukasz Sarnacki*

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
actionpack/lib/action_dispatch/request/utils.rb
@@ -15,7 +15,11 @@ def deep_munge(hash)
when Array
v.grep(Hash) { |x| deep_munge(x) }
v.compact!
- hash[k] = nil if v.empty?
+ if v.empty?
+ hash[k] = nil
+ name = "deep_munge.action_controller"
@rafaelfranca Owner

I think we can avoid this local variable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
actionpack/lib/action_controller/log_subscriber.rb
@@ -53,6 +53,10 @@ def unpermitted_parameters(event)
debug("Unpermitted parameters: #{unpermitted_keys.join(", ")}")
end
+ def deep_munge(event)
+ debug("Value for key :#{event.payload[:key]} in params was set to nil, because it was one of [], [null] or [null, null, ...]. ")
@rafaelfranca Owner

When we say params are we talking about the method or the parameters in general sense?

@chancancode Owner

Would it be too verbose if we (very briefly) what actions to take if you don't want this? And/or (very briefly) explain why we do this?

I'm just thinking it might be even more confusing when I see this because you didn't tell me what I can do about it.

At the very least, maybe we can say "Refer to the documentation of ActionDispatch::Request#deep_munge for details." And update that piece of documentation to include the details. Or perhaps put that in a guide.

@rafaelfranca Owner

Linking to documentation seems a good plan

Actually that is second problem with deep_munge - the only resources are discussions in issues, I will fix those typos and will add mention in documentation. Thanks for quick reply! :)

+1, or at least prefix message with deep_munge: so it's easier to trace

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@rafaelfranca

Seems a good plan to me.

@chancancode
Owner

:+1:

@lukesarnacki

@rafaelfranca @chancancode I fixed typos and made logs a little bit smarter, so i.e. params[:article][:tags] is printed instead of just :tags. I will add mention about deep_munge to guides and will link to it in log message later today.

@lukesarnacki

@rafaelfranca @chancancode I added deep_munge description in guides. One mention is in action controller overview in "Hash and array parameters" section, second one is in security guide as "Unsafe query generation" chapter. I think it covers this well, I am not sure if this is in proper place when it comes to security guide.

Output of command will look like:

Value for params[:article][:tags] was set to nil, because it was one of [], [null] or [null, null, ...]. \
Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation for more information.

(new line here is made for better readibility)

guides/source/action_controller_overview.md
@@ -112,6 +112,8 @@ NOTE: The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&id
The value of `params[:ids]` will now be `["1", "2", "3"]`. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.
+NOTE: Since `3.2.8` version of rails, values such as `[]`, `[nil]` or `[nil, nil, ...]` in params are replaced with `nil` for security reasons by default. See [Security Guide](security.html#unsafe-query-generation) for more information.
@rafaelfranca Owner

Should be "in `params`" since we are talking about the method. If we are talking about the parameters, it should be "in parameters"

@robin850 Collaborator

There is an extra space between the penultimate period and "See". Could you also wrap new additions around 80 chars please ? :smiley:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
guides/source/security.md
@@ -915,6 +915,37 @@ Content-Type: text/html
Under certain circumstances this would present the malicious HTML to the victim. However, this only seems to work with Keep-Alive connections (and many browsers are using one-time connections). But you can't rely on this. _In any case this is a serious bug, and you should update your Rails to version 2.0.5 or 2.1.2 to eliminate Header Injection (and thus response splitting) risks._
+Unsafe Query Generation
+-----------------------
+
+Due to the way `ActiveRecord` interprets parameters in combination with the way that Rack parses query parameters it was possible to issue unexpected database queries with `IS NULL` where clauses. As a response to that security issue ([CVE-2012-2660](https://groups.google.com/forum/#!searchin/rubyonrails-security/deep_munge/rubyonrails-security/8SA-M3as7A8/Mr9fi9X4kNgJ), [CVE-2012-2694](https://groups.google.com/forum/#!searchin/rubyonrails-security/deep_munge/rubyonrails-security/jILZ34tAHF4/7x0hLH-o0-IJ) and [CVE-2013-0155](https://groups.google.com/forum/#!searchin/rubyonrails-security/CVE-2012-2660/rubyonrails-security/c7jT-EeN9eI/L0u4e87zYGMJ)) `deep_munge` method was introduced as a solution to keep Rails secure by default.
@rafaelfranca Owner

It should be "Due to the way Active Record" since we are talking about the framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
guides/source/security.md
((15 lines not shown))
+end
+```
+
+When `params[:token]` is one of: `[]`, `[nil]`, `[nil, nil, ...]` or `['foo', nil]` it will bypass the test for `nil`, but `IS NULL` or `IN ('foo', NULL)` where clauses still will be added to the SQL query.
+
+To keep rails secure by default, `deep_munge` replaces some of the values with `nil`. Below table shows what the parameters look like based on `JSON` sent in request:
+
+| JSON | Parameters |
+|-----------------------------------|--------------------------|
+| `{ "person": null }` | `{ :person => nil }` |
+| `{ "person": [] }` | `{ :person => nil }` |
+| `{ "person": [null] }` | `{ :person => nil }` |
+| `{ "person": [null, null, ...] }` | `{ :person => nil }` |
+| `{ "person": ["foo", null] }` | `{ :person => ["foo"] }` |
+
+It is possible to return to old behaviour and disable `deep_munge` in config if you are aware of the risk and know how to handle it:
@rafaelfranca Owner

Maybe:

It is possible to return to old behaviour and disable `deep_munge` configuring your application if you are aware of the risk and know how to handle it:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
guides/source/security.md
((18 lines not shown))
+When `params[:token]` is one of: `[]`, `[nil]`, `[nil, nil, ...]` or `['foo', nil]` it will bypass the test for `nil`, but `IS NULL` or `IN ('foo', NULL)` where clauses still will be added to the SQL query.
+
+To keep rails secure by default, `deep_munge` replaces some of the values with `nil`. Below table shows what the parameters look like based on `JSON` sent in request:
+
+| JSON | Parameters |
+|-----------------------------------|--------------------------|
+| `{ "person": null }` | `{ :person => nil }` |
+| `{ "person": [] }` | `{ :person => nil }` |
+| `{ "person": [null] }` | `{ :person => nil }` |
+| `{ "person": [null, null, ...] }` | `{ :person => nil }` |
+| `{ "person": ["foo", null] }` | `{ :person => ["foo"] }` |
+
+It is possible to return to old behaviour and disable `deep_munge` in config if you are aware of the risk and know how to handle it:
+
+```ruby
+config.perform_deep_munge = false
@rafaelfranca Owner

We need to put this config in the configuration.md too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
actionpack/lib/action_controller/log_subscriber.rb
@@ -53,6 +53,10 @@ def unpermitted_parameters(event)
debug("Unpermitted parameters: #{unpermitted_keys.join(", ")}")
end
+ def deep_munge(event)
+ debug("Value for params[:#{event.payload[:keys].join('][:')}] was set to nil, because it was one of [], [null] or [null, null, ...]. Go to http://guides.rubyonrails.org/security.html#unsafe-query-generation for more information.")
@robin850 Collaborator

What do you think about using heredoc here or simply move the message to a variable and call debug(message) ? I find files hard to read when you have to scroll but this is just a proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@lukesarnacki

@rafaelfranca I corrected mistakes you pointed out and added mention in configuration guide.

@robin850 Yeah, that line started to be very long ;) I changed it to multiline string.

guides/source/action_controller_overview.md
@@ -112,6 +112,8 @@ NOTE: The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&id
The value of `params[:ids]` will now be `["1", "2", "3"]`. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.
+NOTE: Values such as `[]`, `[nil]` or `[nil, nil, ...]` in `params` are replaced with `nil` for security reasons by default. See [Security Guide](security.html#unsafe-query-generation) for more information.
@robin850 Collaborator

Could you wrap your additions around 80 chars please ? The other guides aren't wrapped too. :smile:

Also, this will need to be rebased. Thanks for the great work here so far! :+1:

Hey, thanks for heads up, is it ok now? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@lukesarnacki lukesarnacki Log which keys were set to nil in deep_munge
deep_munge solves CVE-2013-0155 security vulnerability, but its
behaviour is definately confuisng. This commit adds logging to deep_munge.
It logs keys for which values were set to nil.

Also mentions in guides were added.
69ab91a
@rafaelfranca rafaelfranca merged commit 0fcbc65 into rails:master
@rafaelfranca

Thank @lukesarnacki. Very good PR as always :heart:

@benja83 benja83 referenced this pull request from a commit in benja83/toyotakataboard-relational
@benja83 benja83