Slide 1

Slide 1 text

Justin Collins @presidentbeef Justin Collins @presidentbeef RailsConf 2015 The World of Ruby on Rails Security The World of Ruby on Rails Security

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

@presidentbeef Agenda What Rails Provides What Rails Doesn’t Provide What to Do About It

Slide 4

Slide 4 text

@presidentbeef What Rails Provides

Slide 5

Slide 5 text

@presidentbeef Rails 2 Need to use h() everywhere Rails 3/4 Escape template output by default Cross Site Scripting Protection

Slide 6

Slide 6 text

@presidentbeef Rails 3/4 Examples Escaped <%= params[:q] %> Not escaped <%= raw params[:q] %> Also not <%= params[:q].html_safe %>

Slide 7

Slide 7 text

@presidentbeef Cross Site Scripting

Slide 8

Slide 8 text

@presidentbeef Lots of Safe(ish) Helpers audio_tag image_tag button_tag form_for radio_button_tag text_area_tag tag …

Slide 9

Slide 9 text

@presidentbeef Cross Site Request Forgery (CSRF) http://bank.com/transfer?amount=100000&to=attacker1337

Slide 10

Slide 10 text

@presidentbeef CSRF Protection “Synchronizer Token Pattern” Save a CSRF token to the session Insert the CSRF token in forms Match tokens on POSTs

Slide 11

Slide 11 text

@presidentbeef CSRF Protection

Slide 12

Slide 12 text

@presidentbeef Mass Assignment User.create(params[:user]).save! /user/new/?user[admin]=true

Slide 13

Slide 13 text

@presidentbeef Mass Assignment Protection Rails 2 Optional white/black list in models Rails 3.1 Option to require whitelist in models Rails 3.2.3 Whitelist is default in new apps Rails 4 Whitelist on assignment instead

Slide 14

Slide 14 text

@presidentbeef Strong Parameters input = params.require(:name).permit(:email) User.create(input).save!

Slide 15

Slide 15 text

@presidentbeef Cookie Session Stores Rails 2/3 Signed session cookies Rails 4 Encrypted session cookies JSON, not Marshal

Slide 16

Slide 16 text

@presidentbeef SQL Injection Protection Rails 2/3 Parameterized queries Rails 4 Also Arel

Slide 17

Slide 17 text

@presidentbeef Security Headers Defaults (Rails 4) X-Content-Type-Options: nosniff X-Frame-Options: SAMEORIGIN X-Xss-Protection: 1; mode=block config.force_ssl = true Strict-Transport-Security: max_age=31536000

Slide 18

Slide 18 text

@presidentbeef What Rails Doesn’t Provide (Not an exhaustive list)

Slide 19

Slide 19 text

@presidentbeef Back to Cross Site Scripting .html_safe does not make strings safe .html_safe does not make strings safe .html_safe does not make strings safe .html_safe does not make strings safe .html_safe does not make strings safe

Slide 20

Slide 20 text

@presidentbeef JSON Encoding in Rails 3.2 Loading development environment (Rails 3.2.21) 2.1.5 :001 > {"" => ""}.to_json => "{\"\":\"\"}"

Slide 21

Slide 21 text

@presidentbeef Loading development environment (Rails 4.2.1) 2.1.5 :001 > {"" => ""}.to_json => "{\"\":\"\\u003c/script\\u003e\"} JSON Encoding in Rails 4

Slide 22

Slide 22 text

@presidentbeef How About Contextual Encoding? h j CGI.escape CGI.escapeHTML escape_once escape_javascript html_escape html_escape_once json_escape sanitize sanitize_css

Slide 23

Slide 23 text

@presidentbeef Not Great CSRF Protection Doesn’t apply to GET Route must disallow GET Must use form helpers for CSRF tokens CSRF tokens persist per session

Slide 24

Slide 24 text

@presidentbeef CSRF Token Failures Rails 2 - 3.0.3 Raise an exception Rails 3.0.4 - 3.2.21 Call handle_unverified_request Reset session (default) Rails 4 Raise an exception (default)

Slide 25

Slide 25 text

@presidentbeef def transfer transfer_monies params[:from], params[:to], params[:amount] end https://bounty.github.com/researchers/LukasReschke.html https://blog.nvisium.com/2014/09/understanding-protectfromforgery.html Why Care?

Slide 26

Slide 26 text

@presidentbeef Server-Side Sessions Not Default But sqlite is required by default?!

Slide 27

Slide 27 text

@presidentbeef So What? Rails session cookies are forever Impossible to manage server-side Pre-Rails 4 cookies are simple to decode

Slide 28

Slide 28 text

@presidentbeef Decoding Cookies require 'base64' Marshal.load(Base64.decode64(cookie.split('--')[0])) { "session_id"=>"87918133699858fa3f23542affcc7862", "sensitive_stuff"=>"OOPS DON'T LOOK HERE!", "password"=>"password123", "_csrf_token"=>"ciWkmnuFQZB7EcipKlX+BMYnze6KzAyw2r3aqWql3fU=" }

Slide 29

Slide 29 text

@presidentbeef No Account/Session Management has_secure_password?

Slide 30

Slide 30 text

@presidentbeef No Authorization Framework before_filter?

Slide 31

Slide 31 text

@presidentbeef No Directory Traversal Protection ?view=../admin/index render params[:view] ?file=/etc/password send_file params[:file]

Slide 32

Slide 32 text

@presidentbeef Not Enough SQL Injection Protection calculate exists? having order pluck … rails-sqli.org

Slide 33

Slide 33 text

@presidentbeef Rails-SQLi.org github.com/presidentbeef/inject-some-sql

Slide 34

Slide 34 text

@presidentbeef Rails-SQLi.org github.com/presidentbeef/inject-some-sql

Slide 35

Slide 35 text

@presidentbeef class User < ActiveRecord::Base def related_users(name) q = "last_name = #{name}" User.where(q) end end Sanitizing SQL

Slide 36

Slide 36 text

@presidentbeef Manual SQL Escaping Maybe in here? Yes…?

Slide 37

Slide 37 text

@presidentbeef Sanitizing SQL? class User < ActiveRecord::Base def related_users(name) q = "last_name = #{sanitize_sql name}" User.where(q) end end NoMethodError: undefined method `sanitize_sql' for #

Slide 38

Slide 38 text

@presidentbeef Sanitizing SQL?? self.class.sanitize_sql name NoMethodError: protected method `sanitize_sql' called for #

Slide 39

Slide 39 text

No content

Slide 40

Slide 40 text

@presidentbeef self.class.__send__(:sanitize_sql, name) Sanitizing SQL???

Slide 41

Slide 41 text

@presidentbeef name = "') or 1=1 --" self.class.__send__(:sanitize_sql, name) Sanitizing SQL???? "') or 1=1 --"

Slide 42

Slide 42 text

@presidentbeef name = "') or 1=1 --" self.class.__send__(:sanitize_sql, ["?", name]) Sanitizing SQL "''') or 1=1 --'"

Slide 43

Slide 43 text

@presidentbeef name = "') or 1=1 --" self.class.__send__(:sanitize_sql, last_name: name) Sanitizing SQL "\"users\".\"last_name\" = ''') or 1=1 --'"

Slide 44

Slide 44 text

@presidentbeef No Rate Limiting

Slide 45

Slide 45 text

@presidentbeef No Open Redirect Protection Open Redirect redirect_to params[:n] Safe-ish Redirect redirect_to URI.parse(params[:n]).path

Slide 46

Slide 46 text

@presidentbeef Open Redirect redirect_to params[:n] Safe-ish Redirect begin redirect_to URI.parse(params[:n]).path rescue URI::InvalidURIError #... end No Open Redirect Protection

Slide 47

Slide 47 text

@presidentbeef No Protocol Filtering for Links link_to "My home page", user.home_url My home page

Slide 48

Slide 48 text

@presidentbeef Even More Missing Security Features Code Climate Blog: Rails Insecure Defaults blog.codeclimate.com/blog/2013/03/27/rails-insecure-defaults/

Slide 49

Slide 49 text

@presidentbeef @MakotoTheCat

Slide 50

Slide 50 text

@presidentbeef What To Do About It

Slide 51

Slide 51 text

@presidentbeef Learn About Security

Slide 52

Slide 52 text

@presidentbeef Fix All The Rails Things?

Slide 53

Slide 53 text

@presidentbeef Use Security Libraries Rate Limiting and Blocking rack-attack Moar Headers secure_headers Access Control pundit cancan/cancancan Authentication omniauth User Management devise

Slide 54

Slide 54 text

@presidentbeef Use Static Analysis Tools Brakeman Check for potential vulnerabilities bundler-audit Check for vulnerable dependencies

Slide 55

Slide 55 text

@presidentbeef Cost of Fixing Defects

Slide 56

Slide 56 text

@presidentbeef Use static analysis Scan all the code all the time Don’t fix vulnerabilities, prevent them The Plan

Slide 57

Slide 57 text

@presidentbeef Some Options File system monitoring (using Guard?) Integration into commit tools Continuous integration (with Jenkins?) Integration into release process

Slide 58

Slide 58 text

@presidentbeef More Info “Using Brakeman and Security Automation in Practice in the SDLC and Stuff” youtu.be/kda8RZ5NIlM “Putting Your Robots to Work” vimeo.com/54250716

Slide 59

Slide 59 text

@presidentbeef Be Safe! @presidentbeef / presidentbeef.com @brakeman / brakemanscanner.org @brakemanpro / brakemanpro.com