rails 4.1.6 → 4.2.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +12 -10
  3. data/guides/CHANGELOG.md +64 -17
  4. data/guides/Rakefile +21 -6
  5. data/guides/assets/images/getting_started/article_with_comments.png +0 -0
  6. data/guides/assets/javascripts/guides.js +6 -0
  7. data/guides/assets/stylesheets/main.css +4 -1
  8. data/guides/bug_report_templates/action_controller_gem.rb +3 -3
  9. data/guides/bug_report_templates/action_controller_master.rb +3 -2
  10. data/guides/bug_report_templates/active_record_gem.rb +1 -1
  11. data/guides/bug_report_templates/generic_gem.rb +15 -0
  12. data/guides/bug_report_templates/generic_master.rb +26 -0
  13. data/guides/rails_guides/helpers.rb +1 -1
  14. data/guides/rails_guides/levenshtein.rb +27 -21
  15. data/guides/rails_guides/markdown/renderer.rb +1 -1
  16. data/guides/rails_guides/markdown.rb +11 -7
  17. data/guides/rails_guides.rb +2 -2
  18. data/guides/source/2_2_release_notes.md +1 -1
  19. data/guides/source/2_3_release_notes.md +4 -4
  20. data/guides/source/3_0_release_notes.md +8 -8
  21. data/guides/source/3_1_release_notes.md +6 -3
  22. data/guides/source/3_2_release_notes.md +6 -3
  23. data/guides/source/4_0_release_notes.md +6 -3
  24. data/guides/source/4_1_release_notes.md +9 -10
  25. data/guides/source/4_2_release_notes.md +877 -0
  26. data/guides/source/_license.html.erb +1 -1
  27. data/guides/source/_welcome.html.erb +6 -8
  28. data/guides/source/action_controller_overview.md +25 -8
  29. data/guides/source/action_mailer_basics.md +97 -29
  30. data/guides/source/action_view_overview.md +142 -191
  31. data/guides/source/active_job_basics.md +339 -0
  32. data/guides/source/active_model_basics.md +371 -17
  33. data/guides/source/active_record_basics.md +25 -24
  34. data/guides/source/active_record_callbacks.md +12 -9
  35. data/guides/source/{migrations.md → active_record_migrations.md} +95 -220
  36. data/guides/source/active_record_postgresql.md +433 -0
  37. data/guides/source/active_record_querying.md +264 -268
  38. data/guides/source/active_record_validations.md +23 -13
  39. data/guides/source/active_support_core_extensions.md +115 -123
  40. data/guides/source/active_support_instrumentation.md +10 -18
  41. data/guides/source/api_documentation_guidelines.md +63 -17
  42. data/guides/source/asset_pipeline.md +259 -120
  43. data/guides/source/association_basics.md +96 -80
  44. data/guides/source/autoloading_and_reloading_constants.md +1311 -0
  45. data/guides/source/caching_with_rails.md +32 -7
  46. data/guides/source/command_line.md +52 -30
  47. data/guides/source/configuring.md +161 -33
  48. data/guides/source/contributing_to_ruby_on_rails.md +198 -114
  49. data/guides/source/credits.html.erb +2 -2
  50. data/guides/source/debugging_rails_applications.md +440 -286
  51. data/guides/source/development_dependencies_install.md +47 -36
  52. data/guides/source/documents.yaml +19 -7
  53. data/guides/source/engines.md +217 -196
  54. data/guides/source/form_helpers.md +79 -56
  55. data/guides/source/generators.md +24 -11
  56. data/guides/source/getting_started.md +359 -219
  57. data/guides/source/i18n.md +110 -66
  58. data/guides/source/index.html.erb +1 -0
  59. data/guides/source/initialization.md +109 -62
  60. data/guides/source/layout.html.erb +5 -11
  61. data/guides/source/layouts_and_rendering.md +26 -26
  62. data/guides/source/maintenance_policy.md +6 -3
  63. data/guides/source/nested_model_forms.md +7 -4
  64. data/guides/source/plugins.md +27 -27
  65. data/guides/source/rails_application_templates.md +21 -3
  66. data/guides/source/rails_on_rack.md +8 -5
  67. data/guides/source/routing.md +113 -73
  68. data/guides/source/ruby_on_rails_guides_guidelines.md +11 -12
  69. data/guides/source/security.md +40 -34
  70. data/guides/source/testing.md +199 -119
  71. data/guides/source/upgrading_ruby_on_rails.md +289 -31
  72. data/guides/source/working_with_javascript_in_rails.md +19 -17
  73. data/guides/w3c_validator.rb +2 -0
  74. metadata +42 -95
  75. data/guides/code/getting_started/Gemfile +0 -40
  76. data/guides/code/getting_started/Gemfile.lock +0 -125
  77. data/guides/code/getting_started/README.rdoc +0 -28
  78. data/guides/code/getting_started/Rakefile +0 -6
  79. data/guides/code/getting_started/app/assets/javascripts/application.js +0 -15
  80. data/guides/code/getting_started/app/assets/javascripts/comments.js.coffee +0 -3
  81. data/guides/code/getting_started/app/assets/javascripts/posts.js.coffee +0 -3
  82. data/guides/code/getting_started/app/assets/javascripts/welcome.js.coffee +0 -3
  83. data/guides/code/getting_started/app/assets/stylesheets/application.css +0 -13
  84. data/guides/code/getting_started/app/assets/stylesheets/comments.css.scss +0 -3
  85. data/guides/code/getting_started/app/assets/stylesheets/posts.css.scss +0 -3
  86. data/guides/code/getting_started/app/assets/stylesheets/welcome.css.scss +0 -3
  87. data/guides/code/getting_started/app/controllers/application_controller.rb +0 -5
  88. data/guides/code/getting_started/app/controllers/comments_controller.rb +0 -23
  89. data/guides/code/getting_started/app/controllers/posts_controller.rb +0 -53
  90. data/guides/code/getting_started/app/controllers/welcome_controller.rb +0 -4
  91. data/guides/code/getting_started/app/helpers/application_helper.rb +0 -2
  92. data/guides/code/getting_started/app/helpers/comments_helper.rb +0 -2
  93. data/guides/code/getting_started/app/helpers/posts_helper.rb +0 -2
  94. data/guides/code/getting_started/app/helpers/welcome_helper.rb +0 -2
  95. data/guides/code/getting_started/app/models/comment.rb +0 -3
  96. data/guides/code/getting_started/app/models/post.rb +0 -7
  97. data/guides/code/getting_started/app/views/comments/_comment.html.erb +0 -15
  98. data/guides/code/getting_started/app/views/comments/_form.html.erb +0 -13
  99. data/guides/code/getting_started/app/views/layouts/application.html.erb +0 -14
  100. data/guides/code/getting_started/app/views/posts/_form.html.erb +0 -27
  101. data/guides/code/getting_started/app/views/posts/edit.html.erb +0 -5
  102. data/guides/code/getting_started/app/views/posts/index.html.erb +0 -21
  103. data/guides/code/getting_started/app/views/posts/new.html.erb +0 -5
  104. data/guides/code/getting_started/app/views/posts/show.html.erb +0 -18
  105. data/guides/code/getting_started/app/views/welcome/index.html.erb +0 -4
  106. data/guides/code/getting_started/bin/bundle +0 -4
  107. data/guides/code/getting_started/bin/rails +0 -4
  108. data/guides/code/getting_started/bin/rake +0 -4
  109. data/guides/code/getting_started/config/application.rb +0 -18
  110. data/guides/code/getting_started/config/boot.rb +0 -4
  111. data/guides/code/getting_started/config/database.yml +0 -25
  112. data/guides/code/getting_started/config/environment.rb +0 -5
  113. data/guides/code/getting_started/config/environments/development.rb +0 -30
  114. data/guides/code/getting_started/config/environments/production.rb +0 -80
  115. data/guides/code/getting_started/config/environments/test.rb +0 -36
  116. data/guides/code/getting_started/config/initializers/backtrace_silencers.rb +0 -7
  117. data/guides/code/getting_started/config/initializers/filter_parameter_logging.rb +0 -4
  118. data/guides/code/getting_started/config/initializers/inflections.rb +0 -16
  119. data/guides/code/getting_started/config/initializers/locale.rb +0 -9
  120. data/guides/code/getting_started/config/initializers/mime_types.rb +0 -5
  121. data/guides/code/getting_started/config/initializers/secret_token.rb +0 -12
  122. data/guides/code/getting_started/config/initializers/session_store.rb +0 -3
  123. data/guides/code/getting_started/config/initializers/wrap_parameters.rb +0 -14
  124. data/guides/code/getting_started/config/locales/en.yml +0 -23
  125. data/guides/code/getting_started/config/routes.rb +0 -7
  126. data/guides/code/getting_started/config.ru +0 -4
  127. data/guides/code/getting_started/db/migrate/20130122042648_create_posts.rb +0 -10
  128. data/guides/code/getting_started/db/migrate/20130122045842_create_comments.rb +0 -11
  129. data/guides/code/getting_started/db/schema.rb +0 -33
  130. data/guides/code/getting_started/db/seeds.rb +0 -7
  131. data/guides/code/getting_started/public/404.html +0 -60
  132. data/guides/code/getting_started/public/422.html +0 -60
  133. data/guides/code/getting_started/public/500.html +0 -59
  134. data/guides/code/getting_started/public/favicon.ico +0 -0
  135. data/guides/code/getting_started/public/robots.txt +0 -5
  136. data/guides/code/getting_started/test/controllers/comments_controller_test.rb +0 -7
  137. data/guides/code/getting_started/test/controllers/posts_controller_test.rb +0 -7
  138. data/guides/code/getting_started/test/controllers/welcome_controller_test.rb +0 -9
  139. data/guides/code/getting_started/test/fixtures/comments.yml +0 -11
  140. data/guides/code/getting_started/test/fixtures/posts.yml +0 -9
  141. data/guides/code/getting_started/test/helpers/comments_helper_test.rb +0 -4
  142. data/guides/code/getting_started/test/helpers/posts_helper_test.rb +0 -4
  143. data/guides/code/getting_started/test/helpers/welcome_helper_test.rb +0 -4
  144. data/guides/code/getting_started/test/models/comment_test.rb +0 -7
  145. data/guides/code/getting_started/test/models/post_test.rb +0 -7
  146. data/guides/code/getting_started/test/test_helper.rb +0 -12
@@ -13,17 +13,17 @@ After reading this guide, you will know:
13
13
  Markdown
14
14
  -------
15
15
 
16
- Guides are written in [GitHub Flavored Markdown](http://github.github.com/github-flavored-markdown/). There is comprehensive [documentation for Markdown](http://daringfireball.net/projects/markdown/syntax), a [cheatsheet](http://daringfireball.net/projects/markdown/basics), and [additional documentation](http://github.github.com/github-flavored-markdown/) on the differences from traditional Markdown.
16
+ Guides are written in [GitHub Flavored Markdown](https://help.github.com/articles/github-flavored-markdown). There is comprehensive [documentation for Markdown](http://daringfireball.net/projects/markdown/syntax), as well as a [cheatsheet](http://daringfireball.net/projects/markdown/basics).
17
17
 
18
18
  Prologue
19
19
  --------
20
20
 
21
- Each guide should start with motivational text at the top (that's the little introduction in the blue area). The prologue should tell the reader what the guide is about, and what they will learn. See for example the [Routing Guide](routing.html).
21
+ Each guide should start with motivational text at the top (that's the little introduction in the blue area). The prologue should tell the reader what the guide is about, and what they will learn. As an example, see the [Routing Guide](routing.html).
22
22
 
23
- Titles
23
+ Headings
24
24
  ------
25
25
 
26
- The title of every guide uses `h1`; guide sections use `h2`; subsections `h3`; etc. However, the generated HTML output will have the heading tag starting from `<h2>`.
26
+ The title of every guide uses an `h1` heading; guide sections use `h2` headings; subsections use `h3` headings; etc. Note that the generated HTML output will use heading tags starting with `<h2>`.
27
27
 
28
28
  ```
29
29
  Guide Title
@@ -35,14 +35,14 @@ Section
35
35
  ### Sub Section
36
36
  ```
37
37
 
38
- Capitalize all words except for internal articles, prepositions, conjunctions, and forms of the verb to be:
38
+ When writing headings, capitalize all words except for prepositions, conjunctions, internal articles, and forms of the verb "to be":
39
39
 
40
40
  ```
41
41
  #### Middleware Stack is an Array
42
42
  #### When are Objects Saved?
43
43
  ```
44
44
 
45
- Use the same typography as in regular text:
45
+ Use the same inline formatting as regular text:
46
46
 
47
47
  ```
48
48
  ##### The `:content_type` Option
@@ -51,25 +51,24 @@ Use the same typography as in regular text:
51
51
  API Documentation Guidelines
52
52
  ----------------------------
53
53
 
54
- The guides and the API should be coherent and consistent where appropriate. Please have a look at these particular sections of the [API Documentation Guidelines](api_documentation_guidelines.html):
54
+ The guides and the API should be coherent and consistent where appropriate. In particular, these sections of the [API Documentation Guidelines](api_documentation_guidelines.html) also apply to the guides:
55
55
 
56
56
  * [Wording](api_documentation_guidelines.html#wording)
57
+ * [English](api_documentation_guidelines.html#english)
57
58
  * [Example Code](api_documentation_guidelines.html#example-code)
58
- * [Filenames](api_documentation_guidelines.html#filenames)
59
+ * [Filenames](api_documentation_guidelines.html#file-names)
59
60
  * [Fonts](api_documentation_guidelines.html#fonts)
60
61
 
61
- Those guidelines apply also to guides.
62
-
63
62
  HTML Guides
64
63
  -----------
65
64
 
66
65
  Before generating the guides, make sure that you have the latest version of Bundler installed on your system. As of this writing, you must install Bundler 1.3.5 on your device.
67
66
 
68
- To install the latest version of Bundler, simply run the `gem install bundler` command
67
+ To install the latest version of Bundler, run `gem install bundler`.
69
68
 
70
69
  ### Generation
71
70
 
72
- To generate all the guides, just `cd` into the `guides` directory, run `bundle install` and execute:
71
+ To generate all the guides, just `cd` into the `guides` directory, run `bundle install`, and execute:
73
72
 
74
73
  ```
75
74
  bundle exec rake guides:generate
@@ -17,7 +17,7 @@ After reading this guide, you will know:
17
17
  Introduction
18
18
  ------------
19
19
 
20
- Web application frameworks are made to help developers build web applications. Some of them also help you with securing the web application. In fact one framework is not more secure than another: If you use it correctly, you will be able to build secure apps with many frameworks. Ruby on Rails has some clever helper methods, for example against SQL injection, so that this is hardly a problem. It's nice to see that all of the Rails applications I audited had a good level of security.
20
+ Web application frameworks are made to help developers build web applications. Some of them also help you with securing the web application. In fact one framework is not more secure than another: If you use it correctly, you will be able to build secure apps with many frameworks. Ruby on Rails has some clever helper methods, for example against SQL injection, so that this is hardly a problem.
21
21
 
22
22
  In general there is no such thing as plug-n-play security. Security depends on the people using the framework, and sometimes on the development method. And it depends on all layers of a web application environment: The back-end storage, the web server and the web application itself (and possibly other layers or applications).
23
23
 
@@ -25,7 +25,7 @@ The Gartner Group however estimates that 75% of attacks are at the web applicati
25
25
 
26
26
  The threats against web applications include user account hijacking, bypass of access control, reading or modifying sensitive data, or presenting fraudulent content. Or an attacker might be able to install a Trojan horse program or unsolicited e-mail sending software, aim at financial enrichment or cause brand name damage by modifying company resources. In order to prevent attacks, minimize their impact and remove points of attack, first of all, you have to fully understand the attack methods in order to find the correct countermeasures. That is what this guide aims at.
27
27
 
28
- In order to develop secure web applications you have to keep up to date on all layers and know your enemies. To keep up to date subscribe to security mailing lists, read security blogs and make updating and security checks a habit (check the <a href="#additional-resources">Additional Resources</a> chapter). I do it manually because that's how you find the nasty logical security problems.
28
+ In order to develop secure web applications you have to keep up to date on all layers and know your enemies. To keep up to date subscribe to security mailing lists, read security blogs and make updating and security checks a habit (check the [Additional Resources](#additional-resources) chapter). It is done manually because that's how you find the nasty logical security problems.
29
29
 
30
30
  Sessions
31
31
  --------
@@ -60,7 +60,7 @@ Many web applications have an authentication system: a user provides a user name
60
60
 
61
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
- * 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:
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. 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
 
65
65
  ```ruby
66
66
  config.force_ssl = true
@@ -68,7 +68,7 @@ Hence, the cookie serves as temporary authentication for the web application. An
68
68
 
69
69
  * Most people don't clear out the cookies after working at a public terminal. So if the last user didn't log out of a web application, you would be able to use it as this user. Provide the user with a _log-out button_ in the web application, and _make it prominent_.
70
70
 
71
- * Many cross-site scripting (XSS) exploits aim at obtaining the user's cookie. You'll read <a href="#cross-site-scripting-xss">more about XSS</a> later.
71
+ * Many cross-site scripting (XSS) exploits aim at obtaining the user's cookie. You'll read [more about XSS](#cross-site-scripting-xss) later.
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
 
@@ -95,9 +95,16 @@ Rails 2 introduced a new default session storage, CookieStore. CookieStore saves
95
95
 
96
96
  That means the security of this storage depends on this secret (and on the digest algorithm, which defaults to SHA1, for compatibility). So _don't use a trivial secret, i.e. a word from a dictionary, or one which is shorter than 30 characters_.
97
97
 
98
- `config.secret_key_base` is used for specifying a key which allows sessions for the application to be verified against a known secure key to prevent tampering. Applications get `config.secret_key_base` initialized to a random key in `config/initializers/secret_token.rb`, e.g.:
98
+ `secrets.secret_key_base` is used for specifying a key which allows sessions for the application to be verified against a known secure key to prevent tampering. Applications get `secrets.secret_key_base` initialized to a random key present in `config/secrets.yml`, e.g.:
99
99
 
100
- YourApp::Application.config.secret_key_base = '49d3f3de9ed86c74b94ad6bd0...'
100
+ development:
101
+ secret_key_base: a75d...
102
+
103
+ test:
104
+ secret_key_base: 492f...
105
+
106
+ production:
107
+ secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
101
108
 
102
109
  Older versions of Rails use CookieStore, which uses `secret_token` instead of `secret_key_base` that is used by EncryptedCookieStore. Read the upgrade documentation for more information.
103
110
 
@@ -111,9 +118,9 @@ It works like this:
111
118
 
112
119
  * A user receives credits, the amount is stored in a session (which is a bad idea anyway, but we'll do this for demonstration purposes).
113
120
  * The user buys something.
114
- * Their new, lower credit will be stored in the session.
115
- * The dark side of the user forces them to take the cookie from the first step (which they copied) and replace the current cookie in the browser.
116
- * The user has their credit back.
121
+ * The new adjusted credit value is stored in the session.
122
+ * The user takes the cookie from the first step (which they previously copied) and replaces the current cookie in the browser.
123
+ * The user has their original credit back.
117
124
 
118
125
  Including a nonce (a random value) in the session solves replay attacks. A nonce is valid only once, and the server has to keep track of all the valid nonces. It gets even more complicated if you have several application servers (mongrels). Storing nonces in a database table would defeat the entire purpose of CookieStore (avoiding accessing the database).
119
126
 
@@ -128,8 +135,8 @@ NOTE: _Apart from stealing a user's session id, the attacker may fix a session i
128
135
  This attack focuses on fixing a user's session id known to the attacker, and forcing the user's browser into using this id. It is therefore not necessary for the attacker to steal the session id afterwards. Here is how this attack works:
129
136
 
130
137
  * The attacker creates a valid session id: They load the login page of the web application where they want to fix the session, and take the session id in the cookie from the response (see number 1 and 2 in the image).
131
- * They possibly maintains the session. Expiring sessions, for example every 20 minutes, greatly reduces the time-frame for attack. Therefore they access the web application from time to time in order to keep the session alive.
132
- * Now the attacker will force the user's browser into using this session id (see number 3 in the image). As you may not change a cookie of another domain (because of the same origin policy), the attacker has to run a JavaScript from the domain of the target web application. Injecting the JavaScript code into the application by XSS accomplishes this attack. Here is an example: `<script>document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";</script>`. Read more about XSS and injection later on.
138
+ * They maintain the session by accessing the web application periodically in order to keep an expiring session alive.
139
+ * The attacker forces the user's browser into using this session id (see number 3 in the image). As you may not change a cookie of another domain (because of the same origin policy), the attacker has to run a JavaScript from the domain of the target web application. Injecting the JavaScript code into the application by XSS accomplishes this attack. Here is an example: `<script>document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";</script>`. Read more about XSS and injection later on.
133
140
  * The attacker lures the victim to the infected page with the JavaScript code. By viewing the page, the victim's browser will change the session id to the trap session id.
134
141
  * As the new trap session is unused, the web application will require the user to authenticate.
135
142
  * 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.
@@ -144,7 +151,7 @@ The most effective countermeasure is to _issue a new session identifier_ and dec
144
151
  reset_session
145
152
  ```
146
153
 
147
- If you use the popular RestfulAuthentication plugin for user management, add reset\_session to the SessionsController#create action. Note that this removes any value from the session, _you have to transfer them to the new session_.
154
+ If you use the popular RestfulAuthentication plugin for user management, add reset_session to the SessionsController#create action. Note that this removes any value from the session, _you have to transfer them to the new session_.
148
155
 
149
156
  Another countermeasure is to _save user-specific properties in the session_, verify them every time a request comes in, and deny access, if the information does not match. Such properties could be the remote IP address or the user agent (the web browser name), though the latter is less user-specific. When saving the IP address, you have to bear in mind that there are Internet service providers or large organizations that put their users behind proxies. _These might change over the course of a session_, so these users will not be able to use your application, or only in a limited way.
150
157
 
@@ -180,7 +187,7 @@ This attack method works by including malicious code or a link in a page that ac
180
187
 
181
188
  ![](images/csrf.png)
182
189
 
183
- In the <a href="#sessions">session chapter</a> you have learned that most Rails applications use cookie-based sessions. Either they store the session id in the cookie and have a server-side session hash, or the entire session hash is on the client-side. In either case the browser will automatically send along the cookie on every request to a domain, if it can find a cookie for that domain. The controversial point is, that it will also send the cookie, if the request comes from a site of a different domain. Let's start with an example:
190
+ In the [session chapter](#sessions) you have learned that most Rails applications use cookie-based sessions. Either they store the session id in the cookie and have a server-side session hash, or the entire session hash is on the client-side. In either case the browser will automatically send along the cookie on every request to a domain, if it can find a cookie for that domain. The controversial point is, that it will also send the cookie, if the request comes from a site of a different domain. Let's start with an example:
184
191
 
185
192
  * Bob browses a message board and views a post from a hacker where there is a crafted HTML image element. The element references a command in Bob's project management application, rather than an image file.
186
193
  * `<img src="http://www.webapp.com/project/1/destroy">`
@@ -191,7 +198,7 @@ In the <a href="#sessions">session chapter</a> you have learned that most Rails
191
198
 
192
199
  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
200
 
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_.
201
+ 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 many security contract works - _CSRF is an important security issue_.
195
202
 
196
203
  ### CSRF Countermeasures
197
204
 
@@ -232,26 +239,25 @@ Or the attacker places the code into the onmouseover event handler of an image:
232
239
 
233
240
  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
241
 
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:
242
+ 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, and is the default for newly created rails applications:
236
243
 
237
244
  ```ruby
238
- protect_from_forgery
245
+ protect_from_forgery with: :exception
239
246
  ```
240
247
 
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.
248
+ 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, an exception will be thrown.
242
249
 
243
250
  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:
244
251
 
245
252
  ```ruby
246
- def handle_unverified_request
247
- super
248
- sign_out_user # Example method that will destroy the user cookies.
253
+ rescue_from ActionController::InvalidAuthenticityToken do |exception|
254
+ sign_out_user # Example method that will destroy the user cookies
249
255
  end
250
256
  ```
251
257
 
252
- The above method can be placed in the `ApplicationController` and will be called when a CSRF token is not present on a non-GET request.
258
+ The above method can be placed in the `ApplicationController` and will be called when a CSRF token is not present or is incorrect on a non-GET request.
253
259
 
254
- Note that _cross-site scripting (XSS) vulnerabilities bypass all CSRF protections_. XSS gives the attacker access to all elements on a page, so they can read the CSRF security token from a form or directly submit the form. Read <a href="#cross-site-scripting-xss">more about XSS</a> later.
260
+ Note that _cross-site scripting (XSS) vulnerabilities bypass all CSRF protections_. XSS gives the attacker access to all elements on a page, so they can read the CSRF security token from a form or directly submit the form. Read [more about XSS](#cross-site-scripting-xss) later.
255
261
 
256
262
  Redirection and Files
257
263
  ---------------------
@@ -307,7 +313,7 @@ def sanitize_filename(filename)
307
313
  end
308
314
  ```
309
315
 
310
- A significant disadvantage of synchronous processing of file uploads (as the attachment\_fu plugin may do with images), is its _vulnerability to denial-of-service attacks_. An attacker can synchronously start image file uploads from many computers which increases the server load and may eventually crash or stall the server.
316
+ A significant disadvantage of synchronous processing of file uploads (as the attachment_fu plugin may do with images), is its _vulnerability to denial-of-service attacks_. An attacker can synchronously start image file uploads from many computers which increases the server load and may eventually crash or stall the server.
311
317
 
312
318
  The solution to this is best to _process media files asynchronously_: Save the media file and schedule a processing request in the database. A second process will handle the processing of the file in the background.
313
319
 
@@ -356,7 +362,7 @@ Refer to the Injection section for countermeasures against XSS. It is _recommend
356
362
 
357
363
  **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.
358
364
 
359
- 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.
365
+ 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.
360
366
 
361
367
  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.

362
368
 
@@ -368,7 +374,7 @@ For _countermeasures against CSRF in administration interfaces and Intranet appl
368
374
 
369
375
  The common admin interface works like this: it's located at www.example.com/admin, may be accessed only if the admin flag is set in the User model, re-displays user input and allows the admin to delete/add/edit whatever data desired. Here are some thoughts about this:
370
376
 
371
- * It is very important to _think about the worst case_: What if someone really got hold of my cookie or user credentials. You could _introduce roles_ for the admin interface to limit the possibilities of the attacker. Or how about _special login credentials_ for the admin interface, other than the ones used for the public part of the application. Or a _special password for very serious actions_?
377
+ * It is very important to _think about the worst case_: What if someone really got hold of your cookies or user credentials. You could _introduce roles_ for the admin interface to limit the possibilities of the attacker. Or how about _special login credentials_ for the admin interface, other than the ones used for the public part of the application. Or a _special password for very serious actions_?
372
378
 
373
379
  * Does the admin really have to access the interface from everywhere in the world? Think about _limiting the login to a bunch of source IP addresses_. Examine request.remote_ip to find out about the user's IP address. This is not bullet-proof, but a great barrier. Remember that there might be a proxy in use, though.
374
380
 
@@ -400,7 +406,7 @@ If the parameter was nil, the resulting SQL query will be
400
406
  SELECT * FROM users WHERE (users.activation_code IS NULL) LIMIT 1
401
407
  ```
402
408
 
403
- And thus it found the first user in the database, returned it and logged them in. You can find out more about it in [my blog post](http://www.rorsecurity.info/2007/10/28/restful_authentication-login-security/). _It is advisable to update your plug-ins from time to time_. Moreover, you can review your application to find more flaws like this.
409
+ And thus it found the first user in the database, returned it and logged them in. You can find out more about it in [this blog post](http://www.rorsecurity.info/2007/10/28/restful_authentication-login-security/). _It is advisable to update your plug-ins from time to time_. Moreover, you can review your application to find more flaws like this.
404
410
 
405
411
  ### Brute-Forcing Accounts
406
412
 
@@ -471,7 +477,7 @@ config.filter_parameters << :password
471
477
 
472
478
  INFO: _Do you find it hard to remember all your passwords? Don't write them down, but use the initial letters of each word in an easy to remember sentence._
473
479
 
474
- Bruce Schneier, a security technologist, [has analyzed](http://www.schneier.com/blog/archives/2006/12/realworld_passw.html) 34,000 real-world user names and passwords from the MySpace phishing attack mentioned <a href="#examples-from-the-underground">below</a>. It turns out that most of the passwords are quite easy to crack. The 20 most common passwords are:
480
+ Bruce Schneier, a security technologist, [has analyzed](http://www.schneier.com/blog/archives/2006/12/realworld_passw.html) 34,000 real-world user names and passwords from the MySpace phishing attack mentioned [below](#examples-from-the-underground). It turns out that most of the passwords are quite easy to crack. The 20 most common passwords are:
475
481
 
476
482
  password1, abc123, myspace1, password, blink182, qwerty1, ****you, 123abc, baseball1, football1, 123456, soccer, monkey1, liverpool1, princess1, jordan23, slipknot1, superman1, iloveyou1, and monkey.
477
483
 
@@ -624,7 +630,7 @@ Also, the second query renames some columns with the AS statement so that the we
624
630
 
625
631
  #### Countermeasures
626
632
 
627
- Ruby on Rails has a built-in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. <em class="highlight">Using `Model.find(id)` or `Model.find_by_some thing(something)` automatically applies this countermeasure</em>. But in SQL fragments, especially <em class="highlight">in conditions fragments (`where("...")`), the `connection.execute()` or `Model.find_by_sql()` methods, it has to be applied manually</em>.
633
+ Ruby on Rails has a built-in filter for special SQL characters, which will escape ' , " , NULL character and line breaks. *Using `Model.find(id)` or `Model.find_by_some thing(something)` automatically applies this countermeasure*. But in SQL fragments, especially *in conditions fragments (`where("...")`), the `connection.execute()` or `Model.find_by_sql()` methods, it has to be applied manually*.
628
634
 
629
635
  Instead of passing a string to the conditions option, you can pass an array to sanitize tainted strings like this:
630
636
 
@@ -693,7 +699,7 @@ The log files on www.attacker.com will read like this:
693
699
  GET http://www.attacker.com/_app_session=836c1c25278e5b321d6bea4f19cb57e2
694
700
  ```
695
701
 
696
- You can mitigate these attacks (in the obvious way) by adding the [httpOnly](http://dev.rubyonrails.org/ticket/8895) flag to cookies, so that document.cookie may not be read by JavaScript. Http only cookies can be used from IE v6.SP1, Firefox v2.0.0.5 and Opera 9.5. Safari is still considering, it ignores the option. But other, older browsers (such as WebTV and IE 5.5 on Mac) can actually cause the page to fail to load. Be warned that cookies [will still be visible using Ajax](http://ha.ckers.org/blog/20070719/firefox-implements-httponly-and-is-vulnerable-to-xmlhttprequest/), though.
702
+ You can mitigate these attacks (in the obvious way) by adding the **httpOnly** flag to cookies, so that document.cookie may not be read by JavaScript. Http only cookies can be used from IE v6.SP1, Firefox v2.0.0.5 and Opera 9.5. Safari is still considering, it ignores the option. But other, older browsers (such as WebTV and IE 5.5 on Mac) can actually cause the page to fail to load. Be warned that cookies [will still be visible using Ajax](https://www.owasp.org/index.php/HTTPOnly#Browsers_Supporting_HttpOnly), though.
697
703
 
698
704
  ##### Defacement
699
705
 
@@ -726,7 +732,7 @@ Imagine a blacklist deletes "script" from the user input. Now the attacker injec
726
732
  strip_tags("some<<b>script>alert('hello')<</b>/script>")
727
733
  ```
728
734
 
729
- This returned "some&lt;script&gt;alert('hello')&lt;/script&gt;", which makes an attack work. That's why I vote for a whitelist approach, using the updated Rails 2 method sanitize():
735
+ This returned "some&lt;script&gt;alert('hello')&lt;/script&gt;", which makes an attack work. That's why a whitelist approach is better, using the updated Rails 2 method sanitize():
730
736
 
731
737
  ```ruby
732
738
  tags = %w(a acronym b strong i em li ul ol h1 h2 h3 h4 h5 h6 blockquote br cite sub sup ins p)
@@ -735,7 +741,7 @@ s = sanitize(user_input, tags: tags, attributes: %w(href title))
735
741
 
736
742
  This allows only the given tags and does a good job, even against all kinds of tricks and malformed tags.
737
743
 
738
- As a second step, _it is good practice to escape all output of the application_, especially when re-displaying user input, which hasn't been input-filtered (as in the search form example earlier on). _Use `escapeHTML()` (or its alias `h()`) method_ to replace the HTML input characters &amp;, &quot;, &lt;, &gt; by their uninterpreted representations in HTML (`&amp;`, `&quot;`, `&lt`;, and `&gt;`). However, it can easily happen that the programmer forgets to use it, so _it is recommended to use the [SafeErb](http://safe-erb.rubyforge.org/svn/plugins/safe_erb/) plugin_. SafeErb reminds you to escape strings from external sources.
744
+ As a second step, _it is good practice to escape all output of the application_, especially when re-displaying user input, which hasn't been input-filtered (as in the search form example earlier on). _Use `escapeHTML()` (or its alias `h()`) method_ to replace the HTML input characters &amp;, &quot;, &lt;, &gt; by their uninterpreted representations in HTML (`&amp;`, `&quot;`, `&lt`;, and `&gt;`). However, it can easily happen that the programmer forgets to use it, so _it is recommended to use the SafeErb gem. SafeErb reminds you to escape strings from external sources.
739
745
 
740
746
  ##### Obfuscation and Encoding Injection
741
747
 
@@ -806,7 +812,7 @@ The [moz-binding](http://www.securiteam.com/securitynews/5LP051FHPE.html) CSS pr
806
812
 
807
813
  #### Countermeasures
808
814
 
809
- This example, again, showed that a blacklist filter is never complete. However, as custom CSS in web applications is a quite rare feature, I am not aware of a whitelist CSS filter. _If you want to allow custom colors or images, you can allow the user to choose them and build the CSS in the web application_. Use Rails' `sanitize()` method as a model for a whitelist CSS filter, if you really need one.
815
+ This example, again, showed that a blacklist filter is never complete. However, as custom CSS in web applications is a quite rare feature, it may be hard to find a good whitelist CSS filter. _If you want to allow custom colors or images, you can allow the user to choose them and build the CSS in the web application_. Use Rails' `sanitize()` method as a model for a whitelist CSS filter, if you really need one.
810
816
 
811
817
  ### Textile Injection
812
818
 
@@ -996,7 +1002,7 @@ _'1; mode=block' in Rails by default_ - use XSS Auditor and block page if XSS at
996
1002
  * X-Content-Type-Options
997
1003
  _'nosniff' in Rails by default_ - stops the browser from guessing the MIME type of a file.
998
1004
  * X-Content-Security-Policy
999
- [A powerful mechanism for controlling which sites certain content types can be loaded from](http://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html)
1005
+ [A powerful mechanism for controlling which sites certain content types can be loaded from](http://w3c.github.io/webappsec/specs/content-security-policy/csp-specification.dev.html)
1000
1006
  * Access-Control-Allow-Origin
1001
1007
  Used to control which sites are allowed to bypass same origin policies and send cross-origin requests.
1002
1008
  * Strict-Transport-Security
@@ -1005,7 +1011,7 @@ Used to control which sites are allowed to bypass same origin policies and send
1005
1011
  Environmental Security
1006
1012
  ----------------------
1007
1013
 
1008
- It is beyond the scope of this guide to inform you on how to secure your application code and environments. However, please secure your database configuration, e.g. `config/database.yml`, and your server-side secret, e.g. stored in `config/initializers/secret_token.rb`. You may want to further restrict access, using environment-specific versions of these files and any others that may contain sensitive information.
1014
+ It is beyond the scope of this guide to inform you on how to secure your application code and environments. However, please secure your database configuration, e.g. `config/database.yml`, and your server-side secret, e.g. stored in `config/secrets.yml`. You may want to further restrict access, using environment-specific versions of these files and any others that may contain sensitive information.
1009
1015
 
1010
1016
  Additional Resources
1011
1017
  --------------------