rails 4.0.13 → 4.1.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +22 -17
  3. data/guides/CHANGELOG.md +68 -34
  4. data/guides/assets/images/edge_badge.png +0 -0
  5. data/guides/assets/images/feature_tile.gif +0 -0
  6. data/guides/assets/images/footer_tile.gif +0 -0
  7. data/guides/assets/images/fxn.png +0 -0
  8. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  9. data/guides/assets/images/getting_started/challenge.png +0 -0
  10. data/guides/assets/images/getting_started/confirm_dialog.png +0 -0
  11. data/guides/assets/images/getting_started/forbidden_attributes_for_new_article.png +0 -0
  12. data/guides/assets/images/getting_started/form_with_errors.png +0 -0
  13. data/guides/assets/images/getting_started/index_action_with_edit_link.png +0 -0
  14. data/guides/assets/images/getting_started/new_article.png +0 -0
  15. data/guides/assets/images/getting_started/rails_welcome.png +0 -0
  16. data/guides/assets/images/getting_started/routing_error_no_controller.png +0 -0
  17. data/guides/assets/images/getting_started/routing_error_no_route_matches.png +0 -0
  18. data/guides/assets/images/getting_started/show_action_for_articles.png +0 -0
  19. data/guides/assets/images/getting_started/template_is_missing_articles_new.png +0 -0
  20. data/guides/assets/images/getting_started/unknown_action_create_for_articles.png +0 -0
  21. data/guides/assets/images/getting_started/unknown_action_new_for_articles.png +0 -0
  22. data/guides/assets/images/header_tile.gif +0 -0
  23. data/guides/assets/images/icons/README +1 -1
  24. data/guides/assets/images/icons/callouts/11.png +0 -0
  25. data/guides/assets/images/icons/callouts/12.png +0 -0
  26. data/guides/assets/images/icons/callouts/13.png +0 -0
  27. data/guides/assets/images/icons/callouts/15.png +0 -0
  28. data/guides/assets/images/icons/caution.png +0 -0
  29. data/guides/assets/images/icons/example.png +0 -0
  30. data/guides/assets/images/radar.png +0 -0
  31. data/guides/assets/images/rails4_features.png +0 -0
  32. data/guides/assets/images/rails_guides_kindle_cover.jpg +0 -0
  33. data/guides/assets/images/vijaydev.jpg +0 -0
  34. data/guides/assets/javascripts/guides.js +30 -34
  35. data/guides/assets/stylesheets/main.css +2 -1
  36. data/guides/assets/stylesheets/print.css +1 -1
  37. data/guides/bug_report_templates/action_controller_gem.rb +9 -4
  38. data/guides/bug_report_templates/action_controller_master.rb +4 -2
  39. data/guides/bug_report_templates/active_record_gem.rb +5 -2
  40. data/guides/bug_report_templates/active_record_master.rb +2 -1
  41. data/guides/bug_report_templates/generic_gem.rb +15 -0
  42. data/guides/bug_report_templates/generic_master.rb +26 -0
  43. data/guides/code/getting_started/Gemfile +21 -24
  44. data/guides/code/getting_started/Gemfile.lock +78 -73
  45. data/guides/code/getting_started/Rakefile +1 -1
  46. data/guides/code/getting_started/app/assets/javascripts/application.js +1 -2
  47. data/guides/code/getting_started/app/views/layouts/application.html.erb +2 -2
  48. data/guides/code/getting_started/config/environment.rb +1 -1
  49. data/guides/code/getting_started/config/environments/development.rb +2 -2
  50. data/guides/code/getting_started/config/environments/production.rb +3 -3
  51. data/guides/code/getting_started/config/environments/test.rb +2 -2
  52. data/guides/code/getting_started/config/initializers/secret_token.rb +1 -1
  53. data/guides/code/getting_started/config/initializers/session_store.rb +1 -1
  54. data/guides/code/getting_started/config/routes.rb +1 -1
  55. data/guides/code/getting_started/config.ru +1 -1
  56. data/guides/code/getting_started/public/404.html +2 -0
  57. data/guides/code/getting_started/public/422.html +2 -0
  58. data/guides/code/getting_started/public/500.html +2 -0
  59. data/guides/code/getting_started/test/test_helper.rb +0 -3
  60. data/guides/rails_guides/helpers.rb +3 -1
  61. data/guides/source/2_2_release_notes.md +2 -2
  62. data/guides/source/2_3_release_notes.md +8 -8
  63. data/guides/source/3_0_release_notes.md +2 -3
  64. data/guides/source/3_1_release_notes.md +2 -2
  65. data/guides/source/3_2_release_notes.md +12 -12
  66. data/guides/source/4_0_release_notes.md +79 -46
  67. data/guides/source/4_1_release_notes.md +731 -0
  68. data/guides/source/_welcome.html.erb +5 -2
  69. data/guides/source/action_controller_overview.md +189 -40
  70. data/guides/source/action_mailer_basics.md +27 -27
  71. data/guides/source/action_view_overview.md +131 -20
  72. data/guides/source/active_model_basics.md +6 -6
  73. data/guides/source/active_record_basics.md +15 -15
  74. data/guides/source/active_record_callbacks.md +18 -16
  75. data/guides/source/active_record_querying.md +93 -51
  76. data/guides/source/active_record_validations.md +26 -24
  77. data/guides/source/active_support_core_extensions.md +72 -118
  78. data/guides/source/active_support_instrumentation.md +13 -4
  79. data/guides/source/api_documentation_guidelines.md +104 -6
  80. data/guides/source/asset_pipeline.md +573 -244
  81. data/guides/source/association_basics.md +94 -22
  82. data/guides/source/caching_with_rails.md +15 -6
  83. data/guides/source/command_line.md +55 -46
  84. data/guides/source/configuring.md +248 -52
  85. data/guides/source/contributing_to_ruby_on_rails.md +18 -17
  86. data/guides/source/credits.html.erb +2 -2
  87. data/guides/source/debugging_rails_applications.md +39 -8
  88. data/guides/source/development_dependencies_install.md +91 -8
  89. data/guides/source/documents.yaml +4 -0
  90. data/guides/source/engines.md +678 -232
  91. data/guides/source/form_helpers.md +53 -35
  92. data/guides/source/generators.md +19 -15
  93. data/guides/source/getting_started.md +758 -497
  94. data/guides/source/i18n.md +64 -28
  95. data/guides/source/index.html.erb +1 -1
  96. data/guides/source/initialization.md +155 -58
  97. data/guides/source/kindle/toc.html.erb +1 -1
  98. data/guides/source/layout.html.erb +2 -2
  99. data/guides/source/layouts_and_rendering.md +59 -26
  100. data/guides/source/maintenance_policy.md +3 -3
  101. data/guides/source/migrations.md +101 -62
  102. data/guides/source/nested_model_forms.md +3 -3
  103. data/guides/source/plugins.md +34 -31
  104. data/guides/source/rails_application_templates.md +27 -8
  105. data/guides/source/rails_on_rack.md +41 -58
  106. data/guides/source/routing.md +115 -104
  107. data/guides/source/ruby_on_rails_guides_guidelines.md +2 -2
  108. data/guides/source/security.md +81 -36
  109. data/guides/source/testing.md +56 -79
  110. data/guides/source/upgrading_ruby_on_rails.md +531 -21
  111. data/guides/source/working_with_javascript_in_rails.md +19 -11
  112. metadata +51 -23
  113. data/guides/assets/images/getting_started/forbidden_attributes_for_new_post.png +0 -0
  114. data/guides/assets/images/getting_started/new_post.png +0 -0
  115. data/guides/assets/images/getting_started/post_with_comments.png +0 -0
  116. data/guides/assets/images/getting_started/show_action_for_posts.png +0 -0
  117. data/guides/assets/images/getting_started/template_is_missing_posts_new.png +0 -0
  118. data/guides/assets/images/getting_started/undefined_method_post_path.png +0 -0
  119. data/guides/assets/images/getting_started/unknown_action_create_for_posts.png +0 -0
  120. data/guides/assets/images/getting_started/unknown_action_new_for_posts.png +0 -0
  121. data/guides/assets/images/jaimeiniesta.jpg +0 -0
  122. data/guides/source/kindle/KINDLE.md +0 -26
@@ -58,7 +58,7 @@ WARNING: _Stealing a user's session id lets an attacker use the web application
58
58
 
59
59
  Many web applications have an authentication system: a user provides a user name and password, the web application checks them and stores the corresponding user id in the session hash. From now on, the session is valid. On every request the application will load the user, identified by the user id in the session, without the need for new authentication. The session id in the cookie identifies the session.
60
60
 
61
- Hence, the cookie serves as temporary authentication for the web application. Everyone who seizes a cookie from someone else, may use the web application as this user with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures:
61
+ Hence, the cookie serves as temporary authentication for the web application. Anyone who seizes a cookie from someone else, may use the web application as this user - with possibly severe consequences. Here are some ways to hijack a session, and their countermeasures:
62
62
 
63
63
  * Sniff the cookie in an insecure network. A wireless LAN can be an example of such a network. In an unencrypted wireless LAN it is especially easy to listen to the traffic of all connected clients. This is one more reason not to work from a coffee shop. For the web application builder this means to _provide a secure connection over SSL_. In Rails 3.1 and later, this could be accomplished by always forcing SSL connection in your application config file:
64
64
 
@@ -72,7 +72,7 @@ Hence, the cookie serves as temporary authentication for the web application. Ev
72
72
 
73
73
  * Instead of stealing a cookie unknown to the attacker, they fix a user's session identifier (in the cookie) known to them. Read more about this so-called session fixation later.
74
74
 
75
- The main objective of most attackers is to make money. The underground prices for stolen bank login accounts range from $10–$1000 (depending on the available amount of funds), $0.40–$20 for credit card numbers, $1–$8 for online auction site accounts and $4–$30 for email passwords, according to the [Symantec Global Internet Security Threat Report](http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf).
75
+ The main objective of most attackers is to make money. The underground prices for stolen bank login accounts range from $10-$1000 (depending on the available amount of funds), $0.40-$20 for credit card numbers, $1-$8 for online auction site accounts and $4-$30 for email passwords, according to the [Symantec Global Internet Security Threat Report](http://eval.symantec.com/mktginfo/enterprise/white_papers/b-whitepaper_internet_security_threat_report_xiii_04-2008.en-us.pdf).
76
76
 
77
77
  ### Session Guidelines
78
78
 
@@ -81,7 +81,7 @@ Here are some general guidelines on sessions.
81
81
  * _Do not store large objects in a session_. Instead you should store them in the database and save their id in the session. This will eliminate synchronization headaches and it won't fill up your session storage space (depending on what session storage you chose, see below).
82
82
  This will also be a good idea, if you modify the structure of an object and old versions of it are still in some user's cookies. With server-side session storages you can clear out the sessions, but with client-side storages, this is hard to mitigate.
83
83
 
84
- * _Critical data should not be stored in session_. If the user clears his cookies or closes the browser, they will be lost. And with a client-side session storage, the user can read the data.
84
+ * _Critical data should not be stored in session_. If the user clears their cookies or closes the browser, they will be lost. And with a client-side session storage, the user can read the data.
85
85
 
86
86
  ### Session Storage
87
87
 
@@ -134,7 +134,7 @@ This attack focuses on fixing a user's session id known to the attacker, and for
134
134
  * As the new trap session is unused, the web application will require the user to authenticate.
135
135
  * From now on, the victim and the attacker will co-use the web application with the same session: The session became valid and the victim didn't notice the attack.
136
136
 
137
- ### Session Fixation Countermeasures
137
+ ### Session Fixation - Countermeasures
138
138
 
139
139
  TIP: _One line of code will protect you from session fixation._
140
140
 
@@ -150,7 +150,7 @@ Another countermeasure is to _save user-specific properties in the session_, ver
150
150
 
151
151
  ### Session Expiry
152
152
 
153
- NOTE: _Sessions that never expire extend the time-frame for attacks such as cross-site reference forgery (CSRF), session hijacking and session fixation._
153
+ NOTE: _Sessions that never expire extend the time-frame for attacks such as cross-site request forgery (CSRF), session hijacking and session fixation._
154
154
 
155
155
  One possibility is to set the expiry time-stamp of the cookie with the session id. However the client can edit cookies that are stored in the web browser so expiring sessions on the server is safer. Here is an example of how to _expire sessions in a database table_. Call `Session.sweep("20 minutes")` to expire sessions that were used longer than 20 minutes ago.
156
156
 
@@ -187,11 +187,11 @@ In the <a href="#sessions">session chapter</a> you have learned that most Rails
187
187
  * Bob's session at www.webapp.com is still alive, because he didn't log out a few minutes ago.
188
188
  * By viewing the post, the browser finds an image tag. It tries to load the suspected image from www.webapp.com. As explained before, it will also send along the cookie with the valid session id.
189
189
  * The web application at www.webapp.com verifies the user information in the corresponding session hash and destroys the project with the ID 1. It then returns a result page which is an unexpected result for the browser, so it will not display the image.
190
- * Bob doesn't notice the attack but a few days later he finds out that project number one is gone.
190
+ * Bob doesn't notice the attack - but a few days later he finds out that project number one is gone.
191
191
 
192
- It is important to notice that the actual crafted image or link doesn't necessarily have to be situated in the web application's domain, it can be anywhere in a forum, blog post or email.
192
+ It is important to notice that the actual crafted image or link doesn't necessarily have to be situated in the web application's domain, it can be anywhere - in a forum, blog post or email.
193
193
 
194
- CSRF appears very rarely in CVE (Common Vulnerabilities and Exposures) less than 0.1% in 2006 but it really is a 'sleeping giant' [Grossman]. This is in stark contrast to the results in my (and others) security contract work _CSRF is an important security issue_.
194
+ CSRF appears very rarely in CVE (Common Vulnerabilities and Exposures) - less than 0.1% in 2006 - but it really is a 'sleeping giant' [Grossman]. This is in stark contrast to the results in my (and others) security contract work - _CSRF is an important security issue_.
195
195
 
196
196
  ### CSRF Countermeasures
197
197
 
@@ -230,13 +230,15 @@ Or the attacker places the code into the onmouseover event handler of an image:
230
230
  <img src="http://www.harmless.com/img" width="400" height="400" onmouseover="..." />
231
231
  ```
232
232
 
233
- There are many other possibilities, including Ajax to attack the victim in the background.The _solution to this is including a security token in non-GET requests_ which check on the server-side. In Rails 2 or higher, this is a one-liner in the application controller:
233
+ There are many other possibilities, like using a `<script>` tag to make a cross-site request to a URL with a JSONP or JavaScript response. The response is executable code that the attacker can find a way to run, possibly extracting sensitive data. To protect against this data leakage, we disallow cross-site `<script>` tags. Only Ajax requests may have JavaScript responses since XmlHttpRequest is subject to the browser Same-Origin policy - meaning only your site can initiate the request.
234
+
235
+ To protect against all other forged requests, we introduce a _required security token_ that our site knows but other sites don't know. We include the security token in requests and verify it on the server. This is a one-liner in your application controller:
234
236
 
235
237
  ```ruby
236
- protect_from_forgery secret: "123456789012345678901234567890..."
238
+ protect_from_forgery
237
239
  ```
238
240
 
239
- This will automatically include a security token, calculated from the current session and the server-side secret, in all forms and Ajax requests generated by Rails. You won't need the secret, if you use CookieStorage as session storage. If the security token doesn't match what was expected, the session will be reset. **Note:** In Rails versions prior to 3.0.4, this raised an `ActionController::InvalidAuthenticityToken` error.
241
+ This will automatically include a security token in all forms and Ajax requests generated by Rails. If the security token doesn't match what was expected, the session will be reset.
240
242
 
241
243
  It is common to use persistent cookies to store user information, with `cookies.permanent` for example. In this case, the cookies will not be cleared and the out of the box CSRF protection will not be effective. If you are using a different cookie store than the session for this information, you must handle what to do with it yourself:
242
244
 
@@ -288,9 +290,9 @@ This example is a Base64 encoded JavaScript which displays a simple message box.
288
290
 
289
291
  NOTE: _Make sure file uploads don't overwrite important files, and process media files asynchronously._
290
292
 
291
- Many web applications allow users to upload files. _File names, which the user may choose (partly), should always be filtered_ as an attacker could use a malicious file name to overwrite any file on the server. If you store file uploads at /var/www/uploads, and the user enters a file name like “../../../etc/passwd”, it may overwrite an important file. Of course, the Ruby interpreter would need the appropriate permissions to do so one more reason to run web servers, database servers and other programs as a less privileged Unix user.
293
+ Many web applications allow users to upload files. _File names, which the user may choose (partly), should always be filtered_ as an attacker could use a malicious file name to overwrite any file on the server. If you store file uploads at /var/www/uploads, and the user enters a file name like "../../../etc/passwd", it may overwrite an important file. Of course, the Ruby interpreter would need the appropriate permissions to do so - one more reason to run web servers, database servers and other programs as a less privileged Unix user.
292
294
 
293
- When filtering user input file names, _don't try to remove malicious parts_. Think of a situation where the web application removes all “../” in a file name and an attacker uses a string such as “....//” - the result will be “../”. It is best to use a whitelist approach, which _checks for the validity of a file name with a set of accepted characters_. This is opposed to a blacklist approach which attempts to remove not allowed characters. In case it isn't a valid file name, reject it (or replace not accepted characters), but don't remove them. Here is the file name sanitizer from the [attachment_fu plugin](https://github.com/technoweenie/attachment_fu/tree/master:)
295
+ When filtering user input file names, _don't try to remove malicious parts_. Think of a situation where the web application removes all "../" in a file name and an attacker uses a string such as "....//" - the result will be "../". It is best to use a whitelist approach, which _checks for the validity of a file name with a set of accepted characters_. This is opposed to a blacklist approach which attempts to remove not allowed characters. In case it isn't a valid file name, reject it (or replace not accepted characters), but don't remove them. Here is the file name sanitizer from the [attachment_fu plugin](https://github.com/technoweenie/attachment_fu/tree/master):
294
296
 
295
297
  ```ruby
296
298
  def sanitize_filename(filename)
@@ -313,7 +315,7 @@ The solution to this is best to _process media files asynchronously_: Save the m
313
315
 
314
316
  WARNING: _Source code in uploaded files may be executed when placed in specific directories. Do not place file uploads in Rails' /public directory if it is Apache's home directory._
315
317
 
316
- The popular Apache web server has an option called DocumentRoot. This is the home directory of the web site, everything in this directory tree will be served by the web server. If there are files with a certain file name extension, the code in it will be executed when requested (might require some options to be set). Examples for this are PHP and CGI files. Now think of a situation where an attacker uploads a file file.cgi with code in it, which will be executed when someone downloads the file.
318
+ The popular Apache web server has an option called DocumentRoot. This is the home directory of the web site, everything in this directory tree will be served by the web server. If there are files with a certain file name extension, the code in it will be executed when requested (might require some options to be set). Examples for this are PHP and CGI files. Now think of a situation where an attacker uploads a file "file.cgi" with code in it, which will be executed when someone downloads the file.
317
319
 
318
320
  _If your Apache DocumentRoot points to Rails' /public directory, do not put file uploads in it_, store files at least one level downwards.
319
321
 
@@ -327,7 +329,7 @@ Just as you have to filter file names for uploads, you have to do so for downloa
327
329
  send_file('/var/www/uploads/' + params[:filename])
328
330
  ```
329
331
 
330
- Simply pass a file name like “../../../etc/passwd to download the server's login information. A simple solution against this, is to _check that the requested file is in the expected directory_:
332
+ Simply pass a file name like "../../../etc/passwd" to download the server's login information. A simple solution against this, is to _check that the requested file is in the expected directory_:
331
333
 
332
334
  ```ruby
333
335
  basename = File.expand_path(File.join(File.dirname(__FILE__), '../../files'))
@@ -346,15 +348,15 @@ Intranet and administration interfaces are popular attack targets, because they
346
348
 
347
349
  In 2007 there was the first tailor-made trojan which stole information from an Intranet, namely the "Monster for employers" web site of Monster.com, an online recruitment web application. Tailor-made Trojans are very rare, so far, and the risk is quite low, but it is certainly a possibility and an example of how the security of the client host is important, too. However, the highest threat to Intranet and Admin applications are XSS and CSRF.

348
350
 
349
- **XSS** If your application re-displays malicious user input from the extranet, the application will be vulnerable to XSS. User names, comments, spam reports, order addresses are just a few uncommon examples, where there can be XSS.
351
+ **XSS** If your application re-displays malicious user input from the extranet, the application will be vulnerable to XSS. User names, comments, spam reports, order addresses are just a few uncommon examples, where there can be XSS.
350
352
 
351
353
  Having one single place in the admin interface or Intranet, where the input has not been sanitized, makes the entire application vulnerable. Possible exploits include stealing the privileged administrator's cookie, injecting an iframe to steal the administrator's password or installing malicious software through browser security holes to take over the administrator's computer.
352
354
 
353
355
  Refer to the Injection section for countermeasures against XSS. It is _recommended to use the SafeErb plugin_ also in an Intranet or administration interface.
354
356
 
355
- **CSRF** Cross-Site Reference Forgery (CSRF) is a gigantic attack method, it allows the attacker to do everything the administrator or Intranet user may do. As you have already seen above how CSRF works, here are a few examples of what attackers can do in the Intranet or admin interface.
357
+ **CSRF** Cross-Site Request Forgery (CSRF), also known as Cross-Site Reference Forgery (XSRF), is a gigantic attack method, it allows the attacker to do everything the administrator or Intranet user may do. As you have already seen above how CSRF works, here are a few examples of what attackers can do in the Intranet or admin interface.
356
358
 
357
- A real-world example is a [router reconfiguration by CSRF](http://www.h-online.com/security/Symantec-reports-first-active-attack-on-a-DSL-router--/news/102352). The attackers sent a malicious e-mail, with CSRF in it, to Mexican users. The e-mail claimed there was an e-card waiting for them, but it also contained an image tag that resulted in a HTTP-GET request to reconfigure the user's router (which is a popular model in Mexico). The request changed the DNS-settings so that requests to a Mexico-based banking site would be mapped to the attacker's site. Everyone who accessed the banking site through that router saw the attacker's fake web site and had their credentials stolen.
359
+ A real-world example is a [router reconfiguration by CSRF](http://www.h-online.com/security/news/item/Symantec-reports-first-active-attack-on-a-DSL-router-735883.html). The attackers sent a malicious e-mail, with CSRF in it, to Mexican users. The e-mail claimed there was an e-card waiting for them, but it also contained an image tag that resulted in a HTTP-GET request to reconfigure the user's router (which is a popular model in Mexico). The request changed the DNS-settings so that requests to a Mexico-based banking site would be mapped to the attacker's site. Everyone who accessed the banking site through that router saw the attacker's fake web site and had their credentials stolen.
358
360
 
359
361
  Another example changed Google Adsense's e-mail address and password by. If the victim was logged into Google Adsense, the administration interface for Google advertisements campaigns, an attacker could change their credentials.

360
362
 
@@ -406,7 +408,7 @@ NOTE: _Brute-force attacks on accounts are trial and error attacks on the login
406
408
 
407
409
  A list of user names for your web application may be misused to brute-force the corresponding passwords, because most people don't use sophisticated passwords. Most passwords are a combination of dictionary words and possibly numbers. So armed with a list of user names and a dictionary, an automatic program may find the correct password in a matter of minutes.
408
410
 
409
- Because of this, most web applications will display a generic error message user name or password not correct”, if one of these are not correct. If it said the user name you entered has not been found”, an attacker could automatically compile a list of user names.
411
+ Because of this, most web applications will display a generic error message "user name or password not correct", if one of these are not correct. If it said "the user name you entered has not been found", an attacker could automatically compile a list of user names.
410
412
 
411
413
  However, what most web application designers neglect, are the forgot-password pages. These pages often admit that the entered user name or e-mail address has (not) been found. This allows an attacker to compile a list of user names and brute-force the accounts.
412
414
 
@@ -447,7 +449,7 @@ Here are some ideas how to hide honeypot fields by JavaScript and/or CSS:
447
449
 
448
450
  The most simple negative CAPTCHA is one hidden honeypot field. On the server side, you will check the value of the field: If it contains any text, it must be a bot. Then, you can either ignore the post or return a positive result, but not saving the post to the database. This way the bot will be satisfied and moves on. You can do this with annoying users, too.
449
451
 
450
- You can find more sophisticated negative CAPTCHAs in Ned Batchelder's [blog post](http://nedbatchelder.com/text/stopbots.html:)
452
+ You can find more sophisticated negative CAPTCHAs in Ned Batchelder's [blog post](http://nedbatchelder.com/text/stopbots.html):
451
453
 
452
454
  * Include a field with the current UTC time-stamp in it and check it on the server. If it is too far in the past, or if it is in the future, the form is invalid.
453
455
  * Randomize the field names
@@ -481,7 +483,7 @@ A good password is a long alphanumeric combination of mixed cases. As this is qu
481
483
 
482
484
  INFO: _A common pitfall in Ruby's regular expressions is to match the string's beginning and end by ^ and $, instead of \A and \z._
483
485
 
484
- Ruby uses a slightly different approach than many other languages to match the end and the beginning of a string. That is why even many Ruby and Rails books make this wrong. So how is this a security threat? Say you wanted to loosely validate a URL field and you used a simple regular expression like this:
486
+ Ruby uses a slightly different approach than many other languages to match the end and the beginning of a string. That is why even many Ruby and Rails books get this wrong. So how is this a security threat? Say you wanted to loosely validate a URL field and you used a simple regular expression like this:
485
487
 
486
488
  ```ruby
487
489
  /^https?:\/\/[^\n]+$/i
@@ -495,7 +497,7 @@ http://hi.com
495
497
  */
496
498
  ```
497
499
 
498
- This URL passes the filter because the regular expression matches the second line, the rest does not matter. Now imagine we had a view that showed the URL like this:
500
+ This URL passes the filter because the regular expression matches - the second line, the rest does not matter. Now imagine we had a view that showed the URL like this:
499
501
 
500
502
  ```ruby
501
503
  link_to "Homepage", @user.homepage
@@ -547,7 +549,7 @@ Injection is very tricky, because the same code or parameter can be malicious in
547
549
 
548
550
  ### Whitelists versus Blacklists
549
551
 
550
- NOTE: _When sanitizing, protecting or verifying something, whitelists over blacklists._
552
+ NOTE: _When sanitizing, protecting or verifying something, prefer whitelists over blacklists._
551
553
 
552
554
  A blacklist can be a list of bad e-mail addresses, non-public actions or bad HTML tags. This is opposed to a whitelist which lists the good e-mail addresses, public actions, good HTML tags and so on. Although sometimes it is not possible to create a whitelist (in a SPAM filter, for example), _prefer to use whitelist approaches_:
553
555
 
@@ -646,7 +648,7 @@ INFO: _The most widespread, and one of the most devastating security vulnerabili
646
648
 
647
649
  An entry point is a vulnerable URL and its parameters where an attacker can start an attack.
648
650
 
649
- The most common entry points are message posts, user comments, and guest books, but project titles, document names and search result pages have also been vulnerable - just about everywhere where the user can input data. But the input does not necessarily have to come from input boxes on web sites, it can be in any URL parameter obvious, hidden or internal. Remember that the user may intercept any traffic. Applications, such as the [Live HTTP Headers Firefox plugin](http://livehttpheaders.mozdev.org/), or client-site proxies make it easy to change requests.
651
+ The most common entry points are message posts, user comments, and guest books, but project titles, document names and search result pages have also been vulnerable - just about everywhere where the user can input data. But the input does not necessarily have to come from input boxes on web sites, it can be in any URL parameter - obvious, hidden or internal. Remember that the user may intercept any traffic. Applications, such as the [Live HTTP Headers Firefox plugin](http://livehttpheaders.mozdev.org/), or client-site proxies make it easy to change requests.
650
652
 
651
653
  XSS attacks work like this: An attacker injects some code, the web application saves it and displays it on a page, later presented to a victim. Most XSS examples simply display an alert box, but it is more powerful than that. XSS can steal the cookie, hijack the session, redirect the victim to a fake website, display advertisements for the benefit of the attacker, change elements on the web site to get confidential information or install malicious software through security holes in the web browser.
652
654
 
@@ -698,10 +700,10 @@ You can mitigate these attacks (in the obvious way) by adding the [httpOnly](htt
698
700
  With web page defacement an attacker can do a lot of things, for example, present false information or lure the victim on the attackers web site to steal the cookie, login credentials or other sensitive data. The most popular way is to include code from external sources by iframes:
699
701
 
700
702
  ```html
701
- <iframe name=”StatPage src="http://58.xx.xxx.xxx" width=5 height=5 style=”display:none”></iframe>
703
+ <iframe name="StatPage" src="http://58.xx.xxx.xxx" width=5 height=5 style="display:none"></iframe>
702
704
  ```
703
705
 
704
- This loads arbitrary HTML and/or JavaScript from an external source and embeds it as part of the site. This iframe is taken from an actual attack on legitimate Italian sites using the [Mpack attack framework](http://isc.sans.org/diary.html?storyid=3015). Mpack tries to install malicious software through security holes in the web browser very successfully, 50% of the attacks succeed.
706
+ This loads arbitrary HTML and/or JavaScript from an external source and embeds it as part of the site. This iframe is taken from an actual attack on legitimate Italian sites using the [Mpack attack framework](http://isc.sans.org/diary.html?storyid=3015). Mpack tries to install malicious software through security holes in the web browser - very successfully, 50% of the attacks succeed.
705
707
 
706
708
  A more specialized attack could overlap the entire web site or display a login form, which looks the same as the site's original, but transmits the user name and password to the attacker's site. Or it could use CSS and/or JavaScript to hide a legitimate link in the web application, and display another one at its place which redirects to a fake web site.
707
709
 
@@ -718,7 +720,7 @@ _It is very important to filter malicious input, but it is also important to esc
718
720
 
719
721
  Especially for XSS, it is important to do _whitelist input filtering instead of blacklist_. Whitelist filtering states the values allowed as opposed to the values not allowed. Blacklists are never complete.
720
722
 
721
- Imagine a blacklist deletes script from the user input. Now the attacker injects “&lt;scrscriptipt&gt;”, and after the filter, “&lt;script&gt;” remains. Earlier versions of Rails used a blacklist approach for the strip_tags(), strip_links() and sanitize() method. So this kind of injection was possible:
723
+ Imagine a blacklist deletes "script" from the user input. Now the attacker injects "&lt;scrscriptipt&gt;", and after the filter, "&lt;script&gt;" remains. Earlier versions of Rails used a blacklist approach for the strip_tags(), strip_links() and sanitize() method. So this kind of injection was possible:
722
724
 
723
725
  ```ruby
724
726
  strip_tags("some<<b>script>alert('hello')<</b>/script>")
@@ -744,7 +746,7 @@ Network traffic is mostly based on the limited Western alphabet, so new characte
744
746
  &#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>
745
747
  ```
746
748
 
747
- This example pops up a message box. It will be recognized by the above sanitize() filter, though. A great tool to obfuscate and encode strings, and thus get to know your enemy”, is the [Hackvertor](https://hackvertor.co.uk/public). Rails' sanitize() method does a good job to fend off encoding attacks.
749
+ This example pops up a message box. It will be recognized by the above sanitize() filter, though. A great tool to obfuscate and encode strings, and thus "get to know your enemy", is the [Hackvertor](https://hackvertor.co.uk/public). Rails' sanitize() method does a good job to fend off encoding attacks.
748
750
 
749
751
  #### Examples from the Underground
750
752
 
@@ -760,9 +762,9 @@ The following is an excerpt from the [Js.Yamanner@m](http://www.symantec.com/sec
760
762
 
761
763
  The worms exploits a hole in Yahoo's HTML/JavaScript filter, which usually filters all target and onload attributes from tags (because there can be JavaScript). The filter is applied only once, however, so the onload attribute with the worm code stays in place. This is a good example why blacklist filters are never complete and why it is hard to allow HTML/JavaScript in a web application.
762
764
 
763
- Another proof-of-concept webmail worm is Nduja, a cross-domain worm for four Italian webmail services. Find more details on [Rosario Valotta's paper](http://www.xssed.com/article/9/Paper_A_PoC_of_a_cross_webmail_worm_XWW_called_Njuda_connection/). Both webmail worms have the goal to harvest email addresses, something a criminal hacker could make money with.
765
+ Another proof-of-concept webmail worm is Nduja, a cross-domain worm for four Italian webmail services. Find more details on [Rosario Valotta's paper](http://www.xssed.com/news/37/Nduja_Connection_A_cross_webmail_worm_XWW/). Both webmail worms have the goal to harvest email addresses, something a criminal hacker could make money with.
764
766
 
765
- In December 2006, 34,000 actual user names and passwords were stolen in a [MySpace phishing attack](http://news.netcraft.com/archives/2006/10/27/myspace_accounts_compromised_by_phishers.html). The idea of the attack was to create a profile page named login_home_index_html”, so the URL looked very convincing. Specially-crafted HTML and CSS was used to hide the genuine MySpace content from the page and instead display its own login form.
767
+ In December 2006, 34,000 actual user names and passwords were stolen in a [MySpace phishing attack](http://news.netcraft.com/archives/2006/10/27/myspace_accounts_compromised_by_phishers.html). The idea of the attack was to create a profile page named "login_home_index_html", so the URL looked very convincing. Specially-crafted HTML and CSS was used to hide the genuine MySpace content from the page and instead display its own login form.
766
768
 
767
769
  The MySpace Samy worm will be discussed in the CSS Injection section.
768
770
 
@@ -784,13 +786,13 @@ So the payload is in the style attribute. But there are no quotes allowed in the
784
786
  <div id="mycode" expr="alert('hah!')" style="background:url('javascript:eval(document.all.mycode.expr)')">
785
787
  ```
786
788
 
787
- The eval() function is a nightmare for blacklist input filters, as it allows the style attribute to hide the word innerHTML”:
789
+ The eval() function is a nightmare for blacklist input filters, as it allows the style attribute to hide the word "innerHTML":
788
790
 
789
791
  ```
790
792
  alert(eval('document.body.inne' + 'rHTML'));
791
793
  ```
792
794
 
793
- The next problem was MySpace filtering the word javascript”, so the author used java&lt;NEWLINE&gt;script" to get around this:
795
+ The next problem was MySpace filtering the word "javascript", so the author used "java&lt;NEWLINE&gt;script" to get around this:
794
796
 
795
797
  ```html
796
798
  <div id="mycode" expr="alert('hah!')" style="background:url('java↵
script:eval(document.all.mycode.expr)')">
@@ -837,9 +839,9 @@ It is recommended to _use RedCloth in combination with a whitelist input filter_
837
839
 
838
840
  ### Ajax Injection
839
841
 
840
- NOTE: _The same security precautions have to be taken for Ajax actions as for normal ones. There is at least one exception, however: The output has to be escaped in the controller already, if the action doesn't render a view._
842
+ NOTE: _The same security precautions have to be taken for Ajax actions as for "normal" ones. There is at least one exception, however: The output has to be escaped in the controller already, if the action doesn't render a view._
841
843
 
842
- If you use the [in_place_editor plugin](http://dev.rubyonrails.org/browser/plugins/in_place_editing), or actions that return a string, rather than rendering a view, _you have to escape the return value in the action_. Otherwise, if the return value contains a XSS string, the malicious code will be executed upon return to the browser. Escape any input value using the h() method.
844
+ If you use the [in_place_editor plugin](https://rubygems.org/gems/in_place_editing), or actions that return a string, rather than rendering a view, _you have to escape the return value in the action_. Otherwise, if the return value contains a XSS string, the malicious code will be executed upon return to the browser. Escape any input value using the h() method.
843
845
 
844
846
  ### Command Line Injection
845
847
 
@@ -861,7 +863,7 @@ WARNING: _HTTP headers are dynamically generated and under certain circumstances
861
863
 
862
864
  HTTP request headers have a Referer, User-Agent (client software), and Cookie field, among others. Response headers for example have a status code, Cookie and Location (redirection target URL) field. All of them are user-supplied and may be manipulated with more or less effort. _Remember to escape these header fields, too._ For example when you display the user agent in an administration area.
863
865
 
864
- Besides that, it is _important to know what you are doing when building response headers partly based on user input._ For example you want to redirect the user back to a specific page. To do that you introduced a referer field in a form to redirect to the given address:
866
+ Besides that, it is _important to know what you are doing when building response headers partly based on user input._ For example you want to redirect the user back to a specific page. To do that you introduced a "referer" field in a form to redirect to the given address:
865
867
 
866
868
  ```ruby
867
869
  redirect_to params[:referer]
@@ -913,6 +915,49 @@ Content-Type: text/html
913
915
 
914
916
  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._
915
917
 
918
+ Unsafe Query Generation
919
+ -----------------------
920
+
921
+ Due to the way Active Record interprets parameters in combination with the way
922
+ that Rack parses query parameters it was possible to issue unexpected database
923
+ queries with `IS NULL` where clauses. As a response to that security issue
924
+ ([CVE-2012-2660](https://groups.google.com/forum/#!searchin/rubyonrails-security/deep_munge/rubyonrails-security/8SA-M3as7A8/Mr9fi9X4kNgJ),
925
+ [CVE-2012-2694](https://groups.google.com/forum/#!searchin/rubyonrails-security/deep_munge/rubyonrails-security/jILZ34tAHF4/7x0hLH-o0-IJ)
926
+ and [CVE-2013-0155](https://groups.google.com/forum/#!searchin/rubyonrails-security/CVE-2012-2660/rubyonrails-security/c7jT-EeN9eI/L0u4e87zYGMJ))
927
+ `deep_munge` method was introduced as a solution to keep Rails secure by default.
928
+
929
+ Example of vulnerable code that could be used by attacker, if `deep_munge`
930
+ wasn't performed is:
931
+
932
+ ```ruby
933
+ unless params[:token].nil?
934
+ user = User.find_by_token(params[:token])
935
+ user.reset_password!
936
+ end
937
+ ```
938
+
939
+ When `params[:token]` is one of: `[]`, `[nil]`, `[nil, nil, ...]` or
940
+ `['foo', nil]` it will bypass the test for `nil`, but `IS NULL` or
941
+ `IN ('foo', NULL)` where clauses still will be added to the SQL query.
942
+
943
+ To keep rails secure by default, `deep_munge` replaces some of the values with
944
+ `nil`. Below table shows what the parameters look like based on `JSON` sent in
945
+ request:
946
+
947
+ | JSON | Parameters |
948
+ |-----------------------------------|--------------------------|
949
+ | `{ "person": null }` | `{ :person => nil }` |
950
+ | `{ "person": [] }` | `{ :person => nil }` |
951
+ | `{ "person": [null] }` | `{ :person => nil }` |
952
+ | `{ "person": [null, null, ...] }` | `{ :person => nil }` |
953
+ | `{ "person": ["foo", null] }` | `{ :person => ["foo"] }` |
954
+
955
+ It is possible to return to old behaviour and disable `deep_munge` configuring
956
+ your application if you are aware of the risk and know how to handle it:
957
+
958
+ ```ruby
959
+ config.action_dispatch.perform_deep_munge = false
960
+ ```
916
961
 
917
962
  Default Headers
918
963
  ---------------
@@ -942,7 +987,7 @@ Or you can remove them.
942
987
  config.action_dispatch.default_headers.clear
943
988
  ```
944
989
 
945
- Here is the list of common headers:
990
+ Here is a list of common headers:
946
991
 
947
992
  * X-Frame-Options
948
993
  _'SAMEORIGIN' in Rails by default_ - allow framing on same domain. Set it to 'DENY' to deny framing at all or 'ALLOWALL' if you want to allow framing for all website.