Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The Evolution of Rails Security

The Evolution of Rails Security

Rails has a reputation for being secure by default, but how deserved is that reputation? Let’s take a look back at some of the low points in Rails security history: from the first Rails CVE, to the controversial GitHub mass assignment, the 2013 Rails apocalypse, and more recent remote code execution issues. Then we’ll cheer ourselves up with the many cool security features Rails has added over the years! We’ll cover auto-escaping, strong parameters, default security headers, secret storage, and less well-known features like per-form CSRF tokens and upcoming Content Security Policy support.

Justin Collins

April 18, 2018
Tweet

More Decks by Justin Collins

Other Decks in Programming

Transcript

  1. @presidentbeef
    The Evolution
    of
    Rails Security
    Justin Collins
    @presidentbeef
    RailsConf 2018

    View full-size slide

  2. @presidentbeef
    Ugh, About Me
    8 years of application security
    (AT&T Interactive, Twitter, SurveyMonkey)
    8 years working on Brakeman OSS
    (Static analysis security tool for Rails)
    4 years working on
    (More pro static analysis security tool for Rails)

    View full-size slide

  3. @presidentbeef
    July 2004
    Rails Released to the World
    http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/107370

    View full-size slide

  4. @presidentbeef

    View full-size slide

  5. @presidentbeef
    December 2005
    Rails 1.0
    http://weblog.rubyonrails.org/2005/12/13/rails-1-0-party-like-its-one-oh-oh/

    View full-size slide

  6. @presidentbeef

    View full-size slide

  7. @presidentbeef
    August 2006
    CVE-2006-4111
    CVE-2006-4112

    View full-size slide

  8. @presidentbeef

    View full-size slide

  9. @presidentbeef
    Common
    Vulnerabilities
    and
    Exposures

    View full-size slide

  10. @presidentbeef
    Common
    Vulnerabilities
    and
    Exposures®

    View full-size slide

  11. @presidentbeef
    https://cve.mitre.org/

    View full-size slide

  12. @presidentbeef
    CVE-2006-4111 & CVE-2006-4112

    View full-size slide

  13. @presidentbeef
    Panic!
    http://weblog.rubyonrails.org/2006/8/9/rails-1-1-5-mandatory-security-patch-and-other-tidbits/

    View full-size slide

  14. @presidentbeef
    Panic!
    http://weblog.rubyonrails.org/2006/8/10/security-update-rails-1-0-not-affected/

    View full-size slide

  15. @presidentbeef
    Panic!
    http://weblog.rubyonrails.org/2006/8/10/rails-1-1-6-backports-and-full-disclosure/

    View full-size slide

  16. @presidentbeef

    View full-size slide

  17. @presidentbeef
    https://blog.evanweaver.com/2006/08/12/anatomy-of-an-attack-against-1-1-4/

    View full-size slide

  18. @presidentbeef
    Remote
    Code
    Execution

    View full-size slide

  19. @presidentbeef
    October 2007
    CVE-2007-5380
    http://weblog.rubyonrails.org/2007/10/5/rails-1-2-4-maintenance-release/

    View full-size slide

  20. @presidentbeef
    example.com/home/?_session_id=...

    View full-size slide

  21. @presidentbeef
    If you’re using RESTful routing, pay special attention to the changes to route generation and
    recognition. The previous use of the semicolon in URLs has been replaced with a
    regular /. For instance /person/1;edit has become /person/1/edit. This change was
    made as several libraries, including mongrel, mistakenly treated semi-colons as query string
    seperators[sic] and some browsers and http libraries misbehaved.

    View full-size slide

  22. @presidentbeef
    February 2011
    CVE-2011-0447
    http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails/

    View full-size slide

  23. @presidentbeef
    Cross-Site Request Forgery
    https://bank.com/transfer?amount=100000&to=attacker1337

    View full-size slide

  24. @presidentbeef
    Cross-Site Request Forgery Protection
    “Synchronizer Token Pattern”
    1. Save a CSRF token to the session
    2. Insert the CSRF token in forms
    3. Match tokens on POST/DELETE/PATCH

    View full-size slide

  25. @presidentbeef
    CSRF Token in Form


    View full-size slide

  26. @presidentbeef
    What about XHR?
    It’s cool, an attacker can’t make an XHR request

    View full-size slide

  27. @presidentbeef
    http://lists.webappsec.org/pipermail/websecurity_lists.webappsec.org/2011-February/007533.html

    View full-size slide

  28. @presidentbeef
    Better Cross-Site Request Forgery Protection
    1. Save a CSRF token to the session
    2. Add meta-tags for JavaScript to read tokens
    3. Insert the CSRF token in forms
    4. Send token with XHR requests
    5. Match tokens on POST/DELETE/PATCH/XHR

    View full-size slide

  29. @presidentbeef
    CSRF Meta Tags


    View full-size slide

  30. @presidentbeef
    March 2012
    Mass Assignment,
    GitHub,
    and
    Homakov
    https://blog.github.com/2012-03-04-public-key-security-vulnerability-and-mitigation/

    View full-size slide

  31. @presidentbeef
    Mass Assignment
    @user = User.find(params[:id])
    @user.update_attributes(params[:user])

    View full-size slide

  32. @presidentbeef
    Mass Assignment
    @user = User.find(params[:id])
    @user.update_attributes(params[:user])
    PUT example.com/users/1?user[admin]=true

    View full-size slide

  33. @presidentbeef
    https://github.com/rails/rails/issues/5228

    View full-size slide

  34. @presidentbeef

    View full-size slide

  35. @presidentbeef
    https://github.com/rails/rails/commit/b83965785db1eec019edf1fc272b1aa393e6dc57

    View full-size slide

  36. @presidentbeef
    Speculated GitHub Code
    class PublicKeyController < ApplicationController
    before_filter :authorize_user
    def update
    @current_key = PublicKey.find_by_id params[:public_key][:id]
    @current_key.update_attributes(params[:public_key])
    end
    end
    https://gist.github.com/peternixey/1978249

    View full-size slide

  37. @presidentbeef
    More Speculation

    View full-size slide

  38. @presidentbeef
    More Speculation


    View full-size slide

  39. @presidentbeef
    Mass Assignment Over Time
    Rails 2
    Optional white/black list in models
    Rails 3.1
    Option to require whitelist in models
    Rails 3.2.3
    Whitelist is default in new apps
    Rails 4
    Strong Parameters

    View full-size slide

  40. @presidentbeef
    January 2013
    CVE-2013-0156
    YAML -> RCE
    https://groups.google.com/d/msg/rubyonrails-security/61bkgvnSGTQ/nehwjA8tQ8EJ

    View full-size slide

  41. @presidentbeef
    YAML Can Serialize Arbitrary Ruby Objects
    2.5.0 :001 > require 'yaml'
    => true
    2.5.0 :002 > YAML.dump(Object.new)
    => "--- !ruby/object {}\n"
    2.5.0 :003 > YAML.load(_)
    => #

    View full-size slide

  42. @presidentbeef
    Deserialization Can Execute Code
    https://github.com/charliesome/charlie.bz/blob/master/posts/rails-3.2.10-remote-code-execution.md

    View full-size slide

  43. @presidentbeef
    Put the YAML in the XML

    --- !ruby/object {}

    View full-size slide

  44. @presidentbeef
    January 2013
    YAML -> RCE
    Part 2

    View full-size slide

  45. @presidentbeef
    Rails Parsed JSON as YAML

    View full-size slide

  46. @presidentbeef
    CVE-2014-0130
    CVE-2016-0752
    RCE via Render
    http://matasano.com/research/AnatomyOfRailsVuln-CVE-2014-0130.pdf
    https://nvisium.com/resources/blog/2016/01/26/rails-dynamic-render-to-rce-cve-2016-0752.html

    View full-size slide

  47. @presidentbeef
    Directory Traversal
    render "custom/#{params[:template]}"

    View full-size slide

  48. @presidentbeef
    Directory Traversal
    render "custom/#{params[:template]}"
    ?template=../../../../Gemfile

    View full-size slide

  49. @presidentbeef
    Render Defaulted to ERB
    render "blah.txt"

    View full-size slide

  50. @presidentbeef
    Log a Payload
    example.com/users/?x=<%25%3D+%60ls%60+%25>

    View full-size slide

  51. @presidentbeef
    Log a Payload
    example.com/users/?x=<%25%3D+%60ls%60+%25>
    Started GET "/users/?x=%3C%25%3D+%60ls%60+%25%3E" for 127.0.0.1 at
    2018-04-17 23:37:52 -0700
    Processing by UsersController#index as HTML
    Parameters: {"x"=>"<%= `ls` %>"}
    Rendered users/index within layouts/application (0.6ms)
    Completed 200 OK in 16.9ms (Views: 16.4ms | ActiveRecord: 0.0ms)

    View full-size slide

  52. @presidentbeef
    Render Log
    render "custom/#{params[:template]}"
    ?template=../../../../log/production.log

    View full-size slide

  53. @presidentbeef
    No CVEs in 2017
    ?!

    View full-size slide

  54. @presidentbeef
    Sanitizing vs. Escaping
    sanitize "prompt(1)> input"
    => "> input"
    h "prompt(1)> input"
    => "<Some <script>prompt(1)</script>> input"

    View full-size slide

  55. @presidentbeef
    CVEs Related to Sanitizing Methods
    ● November 2009 - No CVE
    ● CVE-2011-2931
    ● CVE-2012-3465
    ● CVE-2013-1855
    ● CVE-2013-1857
    ● CVE-2015-7579
    ● CVE-2015-7580
    ● CVE-2018-8048
    ● CVE-2018-3741

    View full-size slide

  56. @presidentbeef
    Avoid!
    sanitize()
    sanitize_css()
    strip_tags()
    strip_links()

    View full-size slide

  57. @presidentbeef
    Rails Security Features!

    View full-size slide

  58. @presidentbeef
    January 2007
    Rails 1.2

    View full-size slide

  59. @presidentbeef
    Rails 1.2: Parameter Log Filtering
    class ApplicationController < ActionController::Base
    filter_parameter_logging :password, :cc_number
    end

    View full-size slide

  60. @presidentbeef
    Parameter Log Filtering
    Started GET "/?password=[FILTERED]" for 127.0.0.1 at 2018-04-15 11:12:36 -0700
    Processing by HomeController#index as HTML
    Parameters: {"password"=>"[FILTERED]"}
    Rendered home/index.html.erb within layouts/application (0.0ms)
    Completed 200 OK in 4.2ms (Views: 4.1ms | ActiveRecord: 0.0ms)

    View full-size slide

  61. @presidentbeef
    Rails 4: Parameter Log Filtering
    Rails.application.config.filter_parameters += [:password]
    Default config/initializers/filter_parameter_logging.rb

    View full-size slide

  62. @presidentbeef
    August 2010
    Brakeman 0.0.1!

    View full-size slide

  63. @presidentbeef
    gem install brakeman
    brakeman your/app

    View full-size slide

  64. @presidentbeef
    August 2010
    Rails 3.0!

    View full-size slide

  65. @presidentbeef
    Rails 3.0: Auto-escaping HTML
    Rails 2:
    <%= h params[:query] %>
    Rails 3:
    <%= params[:query] %>

    View full-size slide

  66. @presidentbeef
    August 2011
    Rails 3.1

    View full-size slide

  67. @presidentbeef
    Rails 3.1: has_secure_password
    class User < ActiveRecord::Model
    has_secure_password
    end

    View full-size slide

  68. @presidentbeef
    Rails 3.1: config.force_ssl
    In Rails 3.1, this just redirected requests to HTTPS
    As of Rails 5.2, this setting:
    ● Redirects requests to HTTPS
    ● Sets secure flag on all cookies
    ● Sends the Strict-Transport-Security header

    View full-size slide

  69. @presidentbeef
    June 2013
    Rails 4.0!

    View full-size slide

  70. @presidentbeef
    Rails 4.0: Strong Parameters
    Rails 3:
    params.class => ActiveSupport::HashWithIndifferentAccess
    Rails 4:
    params.class => ActionController::Parameters

    View full-size slide

  71. @presidentbeef
    Rails 4.0: Encrypted Session Cookies
    Rails 3:
    Session cookie is marshalled and signed
    Rails 4:
    Session cookie is JSON, signed, and encrypted

    View full-size slide

  72. @presidentbeef
    Rails 4.0: Default Headers
    config.action_dispatch.default_headers = {
    'X-Frame-Options' => 'SAMEORIGIN',
    'X-XSS-Protection' => '1; mode=block',
    'X-Content-Type-Options' => 'nosniff'
    }

    View full-size slide

  73. @presidentbeef
    Rails 5.0: Per-form CSRF Tokens
    Rails.configuration.action_controller.per_form_csrf_tokens = true
    https://medium.com/rubyinside/a-deep-dive-into-csrf-protection-in-rails-19fa0a42c0ef

    View full-size slide

  74. @presidentbeef
    Rails 5.1: Encrypted Secrets
    rails secrets:setup
    rails secrets:edit
    https://www.engineyard.com/blog/encrypted-rails-secrets-on-rails-5.1

    View full-size slide

  75. @presidentbeef
    Rails 5.2: Encrypted Credentials
    rails credentials:edit
    https://www.engineyard.com/blog/rails-encrypted-credentials-on-rails-5.2

    View full-size slide

  76. @presidentbeef
    Rails 5.2: Default Headers
    config.action_dispatch.default_headers = {
    'X-Frame-Options' => 'SAMEORIGIN',
    'X-XSS-Protection' => '1; mode=block',
    'X-Content-Type-Options' => 'nosniff',
    'X-Download-Options' => 'noopen',
    'X-Permitted-Cross-Domain-Policies' => 'none',
    'Referrer-Policy' => 'strict-origin-when-cross-origin'
    }

    View full-size slide

  77. @presidentbeef
    Rails 5.2: Content-Security-Policy
    # config/initializers/content_security_policy.rb
    Rails.application.config.content_security_policy do |policy|
    policy.default_src :self, :https
    policy.font_src :self, :https, :data
    policy.img_src :self, :https, :data
    policy.object_src :none
    policy.script_src :self, :https
    policy.style_src :self, :https
    # Specify URI for violation reports
    policy.report_uri "/csp-violation-report-endpoint"
    end

    View full-size slide

  78. @presidentbeef
    Content Security Policy
    https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
    https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy

    View full-size slide

  79. @presidentbeef
    More Information
    http://guides.rubyonrails.org/security.html

    View full-size slide

  80. @presidentbeef
    Thank You
    @presidentbeef presidentbeef.com
    @brakemanpro brakemanpro.com
    @brakeman brakeman.org

    View full-size slide