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

Rails 4 Application Security

Rails 4 Application Security

Slides from my O'Reilly Webcast.

http://www.oreilly.com/pub/e/3247

Anthony Lewis

November 12, 2014
Tweet

More Decks by Anthony Lewis

Other Decks in Programming

Transcript

  1. Overview • Authorization Attacks • Injection Attacks • SQL Injection

    • Cross-Site Scripting • Cross-Site Request Forgery Attacks • Mass Assignment Attacks
  2. Examples • The examples in this presentation are based on

    a simple social network application • Users sign up for accounts and create posts • Assume User and Post models • A user has many posts • A post belongs to a user
  3. Authorization Attack • This attack is sometimes called an Insecure

    Direct Object Reference • In other words, a user might change the URL from posts/1 to posts/2 and try to edit another user’s post
  4. Example # This method lets any logged-in # user update

    any post. def update @post = Post.find(params[:id]) # ... end
  5. Example # This method ensures that a user # can

    only update their own post def update @post = current_user.posts.find(params[:id]) # ... end
  6. Injection Attacks • An injection attack occurs when user input

    is executed as part of the application • Injection attacks are extremely common, especially in older applications • The first rule of avoiding injection attacks is never trust input from the user
  7. SQL Injection # Never trust user input class User def

    self.authenticate(username, password) where("username = '#{username}'" + " AND password = '#{password}'").first end end
  8. So Far, So Good User.authenticate("tony", "secret") SELECT * FROM users

    WHERE (username = 'tony' AND password = 'secret') LIMIT 1 => #<User id: 1, username: ...>
  9. So Far, So Good User.authenticate("tony", "wrong") SELECT * FROM users

    WHERE (username = 'tony' AND password = 'wrong') LIMIT 1 => nil
  10. Magic Words • Attackers know a magic phrase for exploiting

    SQL Injection vulnerabilities. • What if we enter this for the password? ' OR '1' = '1
  11. Uh Oh User.authenticate("tony", "' OR '1' = '1") SELECT *

    FROM users WHERE (username = 'tony' AND password = '' OR '1' = '1') LIMIT 1 => #<User id: 1, username: ...>
  12. What Happened? • My password isn’t an empty string, but

    the addition of OR '1' = '1' made the expression true • The attacker is now logged in as me
  13. Solution # Switch to hash conditions class User def self.authenticate(username,

    password) where(username: username, password: password).first end end
  14. Solution • Rails automatically SQL escapes strings in hash conditions

    • If you see string interpolation inside a where method, assume it is dangerous
  15. Cross-Site Scripting • A vulnerability that allows attackers to inject

    client- side JavaScript into web pages viewed by others • When another user views the page, the JavaScript is executed as if it were part of your application
  16. Safe By Default • Thankfully, Rails HTML escapes all output

    by default • Symbols such as < are replaced with character entities such as &lt; • But what if your application needs to show HTML output?
  17. Example # Create a new post with # JavaScript in

    the body Post.create( title: "XSS Test", body: "<script>alert('XSS');</script>" )
  18. Example # This view code... <%= @post.body %> # Becomes

    this HTML... &lt;script&gt;alert('XSS');&lt;/script&gt; # This will not execute
  19. Safe By Default • But what if your application needs

    to show HTML output? • Users want to use HTML to format their posts
  20. Example # This view code... <%= raw @post.body %> #

    Becomes this HTML... <script>alert('XSS');</script> # This WILL execute
  21. Remove Unsafe Tags • Rails includes the sanitize method to

    automatically remove unsafe HTML tags • The sanitize method uses a whitelist of allowed tags to clean up potentially unsafe strings • In Rails 4.2, sanitize is based on the Loofah gem
  22. Example # Use helper.sanitize in a console helper.sanitize "<p>Hello</p>" =>

    "<p>Hello</p>" # pass a list of allowed tags tags = ['em', 'strong'] helper.sanitize "<p>Hello</p>", tags: tags => "Hello"
  23. Example # This view code... <%= sanitize @post.body %> #

    Becomes an empty string... # Obviously, this will not execute
  24. CSRF Attacks • Occurs when one of your application’s users

    visits another site that has been modified by an attacker to target your site • The attacker must trick your application’s users into visiting the malicious page and activating the link • The malicious page uses your application’s trust in this user to accept requests
  25. Example • Imagine you are building an online payment application

    • Your application includes a transfer action that accepts amount and to parameters that specify how much money to transfer to another user • An attacker studies the requests generated by your site and attempts to replicate those requests on his own site
  26. Example <!-- an image tag on the attacker’s site causes

    a GET request --> <img src="http://yoursite.com/transfer? amount=100&to=attacker">
  27. Example • If one of your users visits this site,

    and your site is vulnerable to CSRF attacks, $100 is transferred from their account to the attackers account • This could also be done with a script on the attacker’s site that issues requests
  28. CSRF Prevention • Never use a GET request to change

    state • Use a POST request to update data • Include a user-specific token with all requests that change state in your application • Ignore requests that do not include this token
  29. CSRF Prevention • Rails includes helper methods for generating a

    user-specific token automatically • Rails calls this an authenticity_token • The token is stored in a meta tag on each page • The token is also included in a hidden field on every form
  30. CSRF Prevention # Your application layout includes # a per-user

    token by default... <%= csrf_meta_tags %> # That renders this HTML <meta content="authenticity_token" name="csrf-param" /> <meta content="KA1Q/JoVfI+aV6/L4..." name="csrf-token" />
  31. CSRF Prevention # Your application controller raises # an exception

    if the token is not # included with a POST request... protect_from_forgery with: :exception
  32. Mass Assignment • Model methods such as update_attributes and new

    accept a hash of attributes and update or set all attributes by default • Older Rails versions used the attr_accessible model method to define attributes that could be mass assigned • Rails 4 uses the Strong Parameters gem to move this responsibility to the controller
  33. Example • An attacker can modify your application’s forms or

    use a tool such as cURL to send parameters you aren’t expecting • For example, the attacker might try sending admin=true to your user signup form
  34. Example # The params variable in your # controller now

    looks like this: params = { user: { name: "Tony", admin: true } }
  35. Example # In older Rails versions this assigns # all

    attributes unless attr_accessible # is setup on the User model @user = User.new(params[:user]) # Assuming your User model has an admin # flag, the new user is now an admin
  36. Example # In Rails 4 this raises an exception #

    because it is a mass assignment # without a call to permit @user = User.new(params[:user]) # The new user is not created
  37. Example # The preferred pattern is to call # a

    private user_params method that # uses the permit and require methods # to setup allowed params @user = User.new(user_params)
  38. Example private def user_params params.require(:user).permit(:name, :email) end # this method

    returns this hash: # { name: "Tony" } # the admin flag is silently removed
  39. Summary • As your application gains popularity, the risk of

    attack rises • Rails provides the tools you need to protect your application and your users from attacks • Stay up-to-date on security issues
  40. Resources • The examples in this presentation are based on

    Chapter 11 of my book Rails Crash Course • The security vulnerabilities were taken from the OWASP Top 10 List • The Open Web App Security Project • www.owasp.org