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/spec/features/broken_auth_spec.rb b/spec/features/broken_auth_spec.rb index d1f7e6e..4c83de0 100644 --- a/spec/features/broken_auth_spec.rb +++ b/spec/features/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 'TMI during login - username' 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 'TMI during login - password' 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/features/command_injection_spec.rb index e1ef311..468e92d 100644 --- a/spec/features/command_injection_spec.rb +++ b/spec/features/command_injection_spec.rb @@ -8,7 +8,7 @@ feature 'command injection' do end scenario 'injection attack on file upload', :js => true do - login(@normal_user) + 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/features/csrf_spec.rb b/spec/features/csrf_spec.rb new file mode 100644 index 0000000..b3e56fb --- /dev/null +++ b/spec/features/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 'csrf attack to pto', :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/features/info_disclosure_spec.rb b/spec/features/info_disclosure_spec.rb new file mode 100644 index 0000000..cc93282 --- /dev/null +++ b/spec/features/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 'full ssn returned to view' 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/features/insecure_dor_spec.rb index b0ac570..ce089e2 100644 --- a/spec/features/insecure_dor_spec.rb +++ b/spec/features/insecure_dor_spec.rb @@ -13,9 +13,11 @@ feature 'insecure direct object reference' do 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 @@ -24,6 +26,6 @@ feature 'insecure direct object reference' do @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/features/mass_assignment_spec.rb b/spec/features/mass_assignment_spec.rb new file mode 100644 index 0000000..0e89b65 --- /dev/null +++ b/spec/features/mass_assignment_spec.rb @@ -0,0 +1,37 @@ +require 'spec_helper' + +feature 'sql injection' do + before do + UserFixture.reset_all_users + @normal_user = UserFixture.normal_user + end + + scenario 'mass assignment attack update account_settings' 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 'mass assignment attack create new account' 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/features/sql_injection_spec.rb b/spec/features/sql_injection_spec.rb index 9553fc4..45a2800 100644 --- a/spec/features/sql_injection_spec.rb +++ b/spec/features/sql_injection_spec.rb @@ -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/features/unvalidated_redirects_spec.rb b/spec/features/unvalidated_redirects_spec.rb new file mode 100644 index 0000000..8db28e8 --- /dev/null +++ b/spec/features/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 'login redirects to anywhere', :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/features/url_access_spec.rb b/spec/features/url_access_spec.rb new file mode 100644 index 0000000..f33f858 --- /dev/null +++ b/spec/features/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 'admin route not protected', :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/features/xss_spec.rb index a5bea9f..264eaaf 100644 --- a/spec/features/xss_spec.rb +++ b/spec/features/xss_spec.rb @@ -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. 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..55cd9d3 100644 --- a/spec/support/capybara_shared.rb +++ b/spec/support/capybara_shared.rb @@ -1,3 +1,14 @@ +# 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. +def verifying_fixed? + !ENV['RAILSGOAT_MAINTAINER'] +end + def login(user) visit '/' within('.signup') do