From 570eafa01b6b4313d4224607e3bd5ee21cabd6a7 Mon Sep 17 00:00:00 2001 From: Ken Johnson Date: Sun, 2 Jun 2013 20:19:31 -0400 Subject: [PATCH] this closes issue #9 --- app/controllers/tutorials_controller.rb | 4 + app/views/layouts/tutorial/_sidebar.html.erb | 7 +- .../_admin_mass_assign.html.erb | 150 ++++++++++++++++++ app/views/tutorials/guard.html.erb | 1 + app/views/tutorials/info_disclosure.html.erb | 1 + app/views/tutorials/mass_assignment.html.erb | 18 +++ config/routes.rb | 1 + 7 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 app/views/layouts/tutorial/mass_assignment/_admin_mass_assign.html.erb create mode 100644 app/views/tutorials/mass_assignment.html.erb diff --git a/app/controllers/tutorials_controller.rb b/app/controllers/tutorials_controller.rb index 7bc3459..976ede8 100755 --- a/app/controllers/tutorials_controller.rb +++ b/app/controllers/tutorials_controller.rb @@ -102,4 +102,8 @@ class TutorialsController < ApplicationController @good_code_2 = %q{<%= @user.work_info.last_four %>} end + def mass_assignment + + end + end diff --git a/app/views/layouts/tutorial/_sidebar.html.erb b/app/views/layouts/tutorial/_sidebar.html.erb index 7aa9ae8..c246448 100755 --- a/app/views/layouts/tutorial/_sidebar.html.erb +++ b/app/views/layouts/tutorial/_sidebar.html.erb @@ -99,11 +99,14 @@
  • <%= link_to "Guard", guard_tutorials_path %>
  • -
  • +
  • Session Secret
  • -
  • +
  • <%= link_to "Info Dislosure", info_disclosure_tutorials_path %> +
  • +
  • + <%= link_to "Mass Assignment", mass_assignment_tutorials_path %>
  • DB Sessions diff --git a/app/views/layouts/tutorial/mass_assignment/_admin_mass_assign.html.erb b/app/views/layouts/tutorial/mass_assignment/_admin_mass_assign.html.erb new file mode 100644 index 0000000..e9f8e18 --- /dev/null +++ b/app/views/layouts/tutorial/mass_assignment/_admin_mass_assign.html.erb @@ -0,0 +1,150 @@ +
    +
    +
    + Mass Assignment (Admin role) +
    +
    +
    +
    +
    + +
    +
    +

    + The application allows the admin attribute of a User model to be set through a mass assignment call. This vulnerability exists because a developer has indicated it is acceptable to set or change the admin value through the use of the attr_accessible setting. Any action that uses mass assignment to create a user or modify a user's settings is susceptible to this attack which would allow vertical privilege escalation. +

    +
    +
    +
    +
    + +
    +
    +

    + The bug is introduced within app/models/user.rb, seen on line 3 (:admin): +

    +

    +

    +						<%= %q{
    +						class User < ActiveRecord::Base
    +						  attr_accessible :email, :password, :admin, :password_confirmation, :first_name, :last_name
    +						} %>
    +				 	
    +

    +

    + Any attribute added to the attr_accessible setting can be used during a mass assignment call. What this means is that conceptually, the following is allowed: +

    +
    +					# Note the string "true"/"false" or 1/0, etc. can be added to specify the boolean attribute...
    +					# is true or false thanks to ActiveRecord
    +					User.new(:email => "email@email.com", 
    +					:admin => "true", 
    +					:password => "h4xx0r", 
    +					:first_name => "Captain", 
    +					:last_name => "Crunch"
    +					)
    +				
    +
    +
    +
    +
    + +
    +
    +

    Mass Assignment ATTACK:

    +

    + Through the use of an intercepting proxy, we are able to capture our form submission after entering our information on the sign up page. The request looks like this... +

    +
    		  
    +			POST /users HTTP/1.1
    +			Host: railsgoat.dev
    +			User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:19.0) Gecko/20100101 Firefox/19.0
    +			Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    +			Accept-Language: en-US,en;q=0.5
    +			Accept-Encoding: gzip, deflate
    +			Referer: http://railsgoat.dev/signup
    +			Cookie: _railsgoat_session=[redacted]
    +			Connection: keep-alive
    +			Content-Type: application/x-www-form-urlencoded
    +			Content-Length: 248
    +
    +			utf8=✓&authenticity_token=GXhLKKhfBXdFx5i6iqHEd5E32Kebn1+G35eA87RW1tU=&user[email]=test@test.com&user[first_name]=test&user[last_name]=test&user[password]=testtest&user[password_confirmation]=testtest&commit=Submit
    +			 
    +

    + ...and the attack is quite simple. Append a parameter to the body of this POST request that specifies the admin value is true. +

    +
    	utf8=✓&authenticity_token=GXhLKKhfBXdFx5i6iqHEd5E32Kebn1+G35eA87RW1tU=&user[email]=test@test.com&user[first_name]=test&user[last_name]=test&user[password]=testtest&user[password_confirmation]=testtest&commit=Submit&user[admin]=true
    +			 
    +

    + So when the request is received by the create method within the user controller (code shown below), the admin attribute is set to true upon user creation. +

    +
    +				 def create
    +				    user = User.new(params[:user])
    +				    user.build_retirement(POPULATE_RETIREMENTS.shuffle.first)
    +				    user.build_paid_time_off(POPULATE_PAID_TIME_OFF.shuffle.first).schedule.build(POPULATE_SCHEDULE.shuffle.first)
    +				    user.build_work_info(POPULATE_WORK_INFO.shuffle.first)
    +				    user.performance.build(POPULATE_PERFORMANCE.shuffle.first)
    +				    if user.save
    +				      session[:user_id] = user.user_id
    +				      redirect_to home_dashboard_index_path
    +				    else
    +				      @user = user
    +				      render :new
    +				    end
    +				  end
    +			 
    +

    + The last thing to mention here is that this can be done either through the signup page or when you edit your account settings. +

    +

    Mass Assignment SOLUTION:

    +

    + The solution is fairly simple, remove the admin attribute from the attr_accessible method. The following code shows what we mean: +

    +
    +				        # Note that the admin attr has been removed 
    +						<%= %q{	
    +						class User < ActiveRecord::Base
    +						  attr_accessible :email, :password, :password_confirmation, :first_name, :last_name
    +						} %>
    +			 
    +
    +
    +
    +
    + +
    +
    +

    + Did you register your account correctly? How about when you updated your settings? +

    +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/app/views/tutorials/guard.html.erb b/app/views/tutorials/guard.html.erb index fd9cd5b..a657301 100755 --- a/app/views/tutorials/guard.html.erb +++ b/app/views/tutorials/guard.html.erb @@ -22,6 +22,7 @@ function openSub(){ $('li[id="submenu"]').addClass('open'); + $('li[id="submenu"]').addClass('active open'); }; $(document).ready(openSub); diff --git a/app/views/tutorials/info_disclosure.html.erb b/app/views/tutorials/info_disclosure.html.erb index 660fb97..b482a01 100644 --- a/app/views/tutorials/info_disclosure.html.erb +++ b/app/views/tutorials/info_disclosure.html.erb @@ -11,6 +11,7 @@ \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 6a8217d..9e7ff80 100755 --- a/config/routes.rb +++ b/config/routes.rb @@ -40,6 +40,7 @@ resources :tutorials do get "redirects" get "guard" get "info_disclosure" + get "mass_assignment" end end