Slide 1

Slide 1 text

Ruby on Rails 4 Application Security Anthony Lewis

Slide 2

Slide 2 text

Overview • Authorization Attacks • Injection Attacks • SQL Injection • Cross-Site Scripting • Cross-Site Request Forgery Attacks • Mass Assignment Attacks

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

Authorization Attacks Authentication is not authorization

Slide 5

Slide 5 text

Definitions • Authentication identifies a user • Authorization specifies what a logged-in user can access within your application

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

Example # This method lets any logged-in # user update any post. def update @post = Post.find(params[:id]) # ... end

Slide 8

Slide 8 text

Example # This method ensures that a user # can only update their own post def update @post = current_user.posts.find(params[:id]) # ... end

Slide 9

Slide 9 text

Injection Attacks Never trust the user

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

SQL Injection The most common attack

Slide 12

Slide 12 text

SQL Injection # Never trust user input class User def self.authenticate(username, password) where("username = '#{username}'" + " AND password = '#{password}'").first end end

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

So Far, So Good User.authenticate("tony", "wrong") SELECT * FROM users WHERE (username = 'tony' AND password = 'wrong') LIMIT 1 => nil

Slide 15

Slide 15 text

Magic Words • Attackers know a magic phrase for exploiting SQL Injection vulnerabilities. • What if we enter this for the password? ' OR '1' = '1

Slide 16

Slide 16 text

Uh Oh User.authenticate("tony", "' OR '1' = '1") SELECT * FROM users WHERE (username = 'tony' AND password = '' OR '1' = '1') LIMIT 1 => #

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

Solution # Switch to hash conditions class User def self.authenticate(username, password) where(username: username, password: password).first end end

Slide 19

Slide 19 text

Solution • Rails automatically SQL escapes strings in hash conditions • If you see string interpolation inside a where method, assume it is dangerous

Slide 20

Slide 20 text

Cross-Site Scripting Also known as XSS

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

Safe By Default • Thankfully, Rails HTML escapes all output by default • Symbols such as < are replaced with character entities such as < • But what if your application needs to show HTML output?

Slide 23

Slide 23 text

Example # Create a new post with # JavaScript in the body Post.create( title: "XSS Test", body: "alert('XSS');" )

Slide 24

Slide 24 text

Example # This view code... <%= @post.body %> # Becomes this HTML... <script>alert('XSS');</script> # This will not execute

Slide 25

Slide 25 text

Safe By Default • But what if your application needs to show HTML output? • Users want to use HTML to format their posts

Slide 26

Slide 26 text

Example # This view code... <%= raw @post.body %> # Becomes this HTML... alert('XSS'); # This WILL execute

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

Example # Use helper.sanitize in a console helper.sanitize "

Hello

" => "

Hello

" # pass a list of allowed tags tags = ['em', 'strong'] helper.sanitize "

Hello

", tags: tags => "Hello"

Slide 29

Slide 29 text

Example # This view code... <%= sanitize @post.body %> # Becomes an empty string... # Obviously, this will not execute

Slide 30

Slide 30 text

Cross-Site Request Forgery Also known as CSRF

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

Example

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

CSRF Prevention # Your application layout includes # a per-user token by default... <%= csrf_meta_tags %> # That renders this HTML

Slide 38

Slide 38 text

CSRF Prevention # Your application controller raises # an exception if the token is not # included with a POST request... protect_from_forgery with: :exception

Slide 39

Slide 39 text

Mass Assignment Attacks Protect your attributes

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

Example # The params variable in your # controller now looks like this: params = { user: { name: "Tony", admin: true } }

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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)

Slide 46

Slide 46 text

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

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

Thank you!