ruby on rails security - jaoo.dkjaoo.dk › ... › slides ›...

29
Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers [email protected]

Upload: others

Post on 06-Jun-2020

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Ruby On Rails Security

RubyFools Copenhagen, 2008 1

Heiko [email protected]

Page 2: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Heiko Webers

Ruby On Rails Security Project: www.RoRsecurity.info

E-Book „Ruby On Rails Security“Ruby On Rails Security Audits

RubyFools Copenhagen, 2008 2

Software company

Page 3: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Attack trendsCracker‘s motivation: Make money, it’s amulti-billion dollar businessRecently: Attacks on trusted news or sports sites

Break into the server: Apache, cPanel, CMS

RubyFools Copenhagen, 2008 3

Break into the server: Apache, cPanel, CMS holesAdvertisement with malwareInject specific exploits or entire attackframeworks: MPack, 500-1,000$, available inthe Russian underground, guaranteed 40-50% success rate

Here: Security of the (upper) application

Page 4: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Injection

The wrong wayDirectly use external input

The right wayConsider external input malicious, until proven

RubyFools Copenhagen, 2008 4

Consider external input malicious, until provenotherwiseSanitize or (preferably) escape it according tothe context it‘s being used in

Page 5: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Injection - Contexts

SQL – remember SQLi in find_by_sql

SGML (HTML, XML, RSS…) – Escapeagainst XSS, SafeErb plug-inJavaScript – Escape possible code in a

RubyFools Copenhagen, 2008 5

JavaScript – Escape possible code in aRJS contextescape_javascript()

Page 6: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Injection - Contexts

CSS – This is how the Samy wormbrought down MySpace<div id=mycode style="BACKGROUND: url('javascript: eval(document.all.mycode.expr)')" expr="..." />

RubyFools Copenhagen, 2008 6

Command line parameter: No | or ;allowed, use system() instead of `command`

`ls #{dir}` # dir #= "whatever | rm *"

Page 7: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Injection - Contexts

Textile – Definitely sanitize the result withRails’ sanitize()

!bunny.gif(Bunny" onclick="alert(1))!

RubyFools Copenhagen, 2008 7

<p><img src="bunny.gif" title="Bunny" onclick=" alert(1) " alt="Bunny" onclick=" alert(1) " /></p>

Page 8: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Whitelists vs. Blacklists

Use before_filter :only instead of :except

Attr_accessible instead of attr_protected

Against XSS: Allow <b> instead of removing <script>

RubyFools Copenhagen, 2008 8

removing <script>

Don’t try to “correct” user input by blacklists:

"<sc <script> ript>".gsub("<script>", "")

But reject malformed input

Page 9: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Cross-Site Reference Forgery (CSRF)

Browser sends domain cookie for every request

© SecureNet

RubyFools Copenhagen, 2008 9

Browser sends domain cookie for every request to that domainClient is logged in, authentication information in the cookieVictim clicks a link or views a page with a special image:

<img src="http://www.example.com/project/1/destroy" />

He doesn‘t even notice the attack

Page 10: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

CSRF in Rails

The wrong wayGET /project/1/destroy

The right wayGET /project/1/show

POST /project/1/destroy

RubyFools Copenhagen, 2008 10

POST /project/1/destroy

verify :method => :post, :only => [:destroy]

Page 11: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

CSRF & POST<a href=" http://www.harmless.com/ " onclick="var f =

document.createElement (' form '); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = ' POST'; f.action = ' http://www.example.com/account/destroy '; f.submit();return false;"> To the survey </a>

RubyFools Copenhagen, 2008 11

<img src=" http://www.harmless.com/img " width="400" height="400" onmouseover="..." />

Page 12: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

CSRF in Rails

The right wayprotect_from_forgery :secret => "very_long_secret"

Includes a security token in non-GETrequests, automatically generated in

RubyFools Copenhagen, 2008 12

requests, automatically generated inform_for() and others

<input name="authenticity_token" type="hidden" value="3a1e11299eff1fa5cbc724ca32978448098af0" />

Page 13: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Administration Interface

The wrong wayVulnerable to XSS (steal a privileged cookie)Vulnerable to CSRF<img src="/admin/user/destroy/1" />

The same cookies used for the application

RubyFools Copenhagen, 2008 13

The same cookies used for the applicationand the admin interface

Page 14: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Administration Interface

The right wayTake security even more serious (especially XSS & CSRF)Take precautions for the worst case:Someone else takes control of the

RubyFools Copenhagen, 2008 14

Someone else takes control of theadministration interfaceRequire to log in to the interface despite of avalid session, might even be special adminlogin credentialsIntroduce user roles: Different permissions fordifferent admins

Page 15: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Administration Interface

The right wayPut it to admin.example.com instead ofwww.example.com/ admin: A (stolen admin)cookie from www.example.com doesn‘t workon admin.example.com

RubyFools Copenhagen, 2008 15

on admin.example.comCheck the remote IP: Administration allowedfrom a certain IP (check request.remote_ip )

Page 16: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Session Fixation

Instead of stealing a cookie, an attacker fixes a user‘ssession identifier known to him

RubyFools Copenhagen, 2008 16

©acros

Page 17: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Session Fixation

Change the victim‘s cookie, for example with HTML/JS: document.cookie="_session_id=16d5b78abb28e3d6206b60f22a03c8d9";

The wrong way

RubyFools Copenhagen, 2008 17

The wrong wayVulnerable to XSS (the most obvious way to fixate sessions)Allow users to log in with the same session ID for years

Page 18: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Session Fixation

The right wayIf the application is non-public: Turn offcookies for the public parts, so an attackermay not obtain a valid session IDIssue a new session ID after a succesful login

RubyFools Copenhagen, 2008 18

Issue a new session ID after a succesful loginclass SessionsController < ApplicationController

def create

reset_session

end

end

Page 19: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Session Fixation

The right wayExpire sessions, frequency based on howcritical the application isAn attacker may write an automated script tokeep a session alive: Check the session‘s

RubyFools Copenhagen, 2008 19

keep a session alive: Check the session‘screated_at, as well (for ActiveRecordStore)

Page 20: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Login

The wrong wayNot updating plug-ins (e.g. restful_authentication)

The right way

RubyFools Copenhagen, 2008 20

Check for updates: There was a security holein it, you could log in without login credentialsGET /activate?id=

User.find_by_activation_code(params[:id])SELECT * FROM users WHERE (users.`activation_code` IS NULL )LIMIT 1

See http://www.rorsecurity.info/2007/10/28/restful_authentication-login-security/

Page 21: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

User Management

The wrong wayMake changing password and e-mail address easy

The right way

RubyFools Copenhagen, 2008 21

Make it harder to seize an accountRequire to enter the old password when changingOr the answer to a security question

Page 22: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

User Management

The wrong waySpecific error messages enable usernameenumeration (for login and “send-forgotten-password” pages)

The right way

RubyFools Copenhagen, 2008 22

The right wayArmed with a list of usernames and adictionary for the passwords, a bot mightbrute-force accountsFirst step: Possibly disable an account orrequire to enter a CAPTCHA after a certainamount of failed logins

Page 23: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

CookieStore

What you store in the session can be seen by the client<base64 encoded session>-<digest>

The wrong wayStore secrets, more than 4K of data, entire

RubyFools Copenhagen, 2008 23

Store secrets, more than 4K of data, entire objectsUse a trivial secret

config.action_controller.session = {

:secret => ‘trivial’

}

Page 24: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

CookieStore

The right wayOk if you store a user_id and flash message onlyMake the secret at least 30 characters long

RubyFools Copenhagen, 2008 24

config.action_controller.session = {

:session_key => ‘_app_session’,

:secret => ‘0x0dkfj3927dkc7djdh36rkckdfzsg’

}

Page 25: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

CookieStore

Be aware of replay attacks1. User receives credits, stored in his session2. User buys something3. User gets his new, lower credits stored in his

RubyFools Copenhagen, 2008 25

session4. Cracker takes his saved cookie from step #1

and pastes it back in his browser’s cookie.Now he’s gotten his credits backNormally solved using a nonce, but that‘svery hard for multiple app servers(mongrels)

Page 26: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Files

The wrong waysend_file '/var/www/uploads/' + params[:filename]

GET /download?filename=../../../etc/passwd

PUT /upload?filename=../../../etc/passwd

The right way

RubyFools Copenhagen, 2008 26

The right wayStore filenames in the DB, name the files afterthe record ID, just as the attachment_fu plug-in doesVerify the downloaded file to be in the correctdirectoryraise if DOWNLOAD_DIR =!

File.dirname(filename)

Page 27: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Files

The wrong wayStore file uploads in Rails‘ public directoryUpload: /public/uploads/file.fcgi

The right way

RubyFools Copenhagen, 2008 27

The right wayDo not store it in Apache's DocumentRoot directory tree

Page 28: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Hate CAPTCHAS?

Say Hello to negative CAPTCHAsDon‘t ask the user to proof he‘s human, butreveal that the spam/login bot is a botInclude a honeypot field that is hidden fromthe user by CSS

RubyFools Copenhagen, 2008 28

the user by CSSIf this field contains any text, it must be a botOr make it more sophisticated

http://nedbatchelder.com/text/stopbots.html

Page 29: Ruby On Rails Security - jaoo.dkjaoo.dk › ... › slides › HeikoWebers_RubyOnRailsSecurity.pdf · Ruby On Rails Security RubyFools Copenhagen, 2008 1 Heiko Webers 42@rorsecurity.info

Thanks

RubyFools Copenhagen, 2008 29

Thanks