-Conversion to the OWASP Top 10, 2013 is under way.
+Start the WEBrick HTTP Server:
-You can view progress within the top-10-2013 branch.
+```
+$ rails server
+```
- git fetch origin
- git checkout top-10-2013
-Then proceed with browsing the site as normal :thumbsup:
-
+Open your favorite browser, navigate to `http://localhost:3000` and start hacking!
-### Build Info ###
+## Capybara Tests
-[](https://codeclimate.com/github/OWASP/railsgoat)
+RailsGoat now includes a set of failing Capybara RSpecs, each one indicating that a separate vulnerability exists in the application. To run them, you first need to install [PhantomJS](https://github.com/jonleighton/poltergeist#installing-phantomjs), which is required by the Poltergeist Capybara driver. Upon installation, simply run the following rake task:
-[](https://travis-ci.org/OWASP/railsgoat)
+```
+$ rake training
+```
-### License Stuff ###
+NOTE: As vulnerabilities are fixed in the application, these specs will not change to `passing`, but to `pending`.
+
+## Processing Email
+
+In order for RailsGoat to effectively process email, you will first need to run MailCatcher, an SMTP server that will intercept email messages and display them in a web interface.
+
+To start an instance of MailCatcher, simply run:
+
+```
+$ mailcatcher
+```
+
+If successful, you should see the following output:
+
+```
+Starting MailCatcher
+==> smtp://127.0.0.1:1025
+==> http://127.0.0.1:1080
+*** MailCatcher runs as a daemon by default. Go to the web interface to quit.
+```
+
+Alternatively, you can run MailCatcher in the foreground by running `mailcatcher -f` in your terminal.
+
+## Contributing
+
+As changes are made to the application, the Capybara RSpecs can be used to verify that 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 Ten 2013 completed in November, 2013.
+
+# License
The MIT License (MIT)
-Copyright (c) 2013 The Open Web Application Security Project
+Copyright (c) 2013 The Open Web Application Security Project
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-
-
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/README.rdoc b/README.rdoc
deleted file mode 100755
index 3e1c15c..0000000
--- a/README.rdoc
+++ /dev/null
@@ -1,261 +0,0 @@
-== Welcome to Rails
-
-Rails is a web-application framework that includes everything needed to create
-database-backed web applications according to the Model-View-Control pattern.
-
-This pattern splits the view (also called the presentation) into "dumb"
-templates that are primarily responsible for inserting pre-built data in between
-HTML tags. The model contains the "smart" domain objects (such as Account,
-Product, Person, Post) that holds all the business logic and knows how to
-persist themselves to a database. The controller handles the incoming requests
-(such as Save New Account, Update Product, Show Post) by manipulating the model
-and directing data to the view.
-
-In Rails, the model is handled by what's called an object-relational mapping
-layer entitled Active Record. This layer allows you to present the data from
-database rows as objects and embellish these data objects with business logic
-methods. You can read more about Active Record in
-link:files/vendor/rails/activerecord/README.html.
-
-The controller and view are handled by the Action Pack, which handles both
-layers by its two parts: Action View and Action Controller. These two layers
-are bundled in a single package due to their heavy interdependence. This is
-unlike the relationship between the Active Record and Action Pack that is much
-more separate. Each of these packages can be used independently outside of
-Rails. You can read more about Action Pack in
-link:files/vendor/rails/actionpack/README.html.
-
-
-== Getting Started
-
-1. At the command prompt, create a new Rails application:
- rails new myapp (where myapp is the application name)
-
-2. Change directory to myapp and start the web server:
- cd myapp; rails server (run with --help for options)
-
-3. Go to http://localhost:3000/ and you'll see:
- "Welcome aboard: You're riding Ruby on Rails!"
-
-4. Follow the guidelines to start developing your application. You can find
-the following resources handy:
-
-* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
-* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
-
-
-== Debugging Rails
-
-Sometimes your application goes wrong. Fortunately there are a lot of tools that
-will help you debug it and get it back on the rails.
-
-First area to check is the application log files. Have "tail -f" commands
-running on the server.log and development.log. Rails will automatically display
-debugging and runtime information to these files. Debugging info will also be
-shown in the browser on requests from 127.0.0.1.
-
-You can also log your own messages directly into the log file from your code
-using the Ruby logger class from inside your controllers. Example:
-
- class WeblogController < ActionController::Base
- def destroy
- @weblog = Weblog.find(params[:id])
- @weblog.destroy
- logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
- end
- end
-
-The result will be a message in your log file along the lines of:
-
- Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
-
-More information on how to use the logger is at http://www.ruby-doc.org/core/
-
-Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
-several books available online as well:
-
-* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
-* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
-
-These two books will bring you up to speed on the Ruby language and also on
-programming in general.
-
-
-== Debugger
-
-Debugger support is available through the debugger command when you start your
-Mongrel or WEBrick server with --debugger. This means that you can break out of
-execution at any point in the code, investigate and change the model, and then,
-resume execution! You need to install ruby-debug to run the server in debugging
-mode. With gems, use sudo gem install ruby-debug. Example:
-
- class WeblogController < ActionController::Base
- def index
- @posts = Post.all
- debugger
- end
- end
-
-So the controller will accept the action, run the first line, then present you
-with a IRB prompt in the server window. Here you can do things like:
-
- >> @posts.inspect
- => "[#nil, "body"=>nil, "id"=>"1"}>,
- #"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
- >> @posts.first.title = "hello from a debugger"
- => "hello from a debugger"
-
-...and even better, you can examine how your runtime objects actually work:
-
- >> f = @posts.first
- => #nil, "body"=>nil, "id"=>"1"}>
- >> f.
- Display all 152 possibilities? (y or n)
-
-Finally, when you're ready to resume execution, you can enter "cont".
-
-
-== Console
-
-The console is a Ruby shell, which allows you to interact with your
-application's domain model. Here you'll have all parts of the application
-configured, just like it is when the application is running. You can inspect
-domain models, change values, and save to the database. Starting the script
-without arguments will launch it in the development environment.
-
-To start the console, run rails console from the application
-directory.
-
-Options:
-
-* Passing the -s, --sandbox argument will rollback any modifications
- made to the database.
-* Passing an environment name as an argument will load the corresponding
- environment. Example: rails console production.
-
-To reload your controllers and models after launching the console run
-reload!
-
-More information about irb can be found at:
-link:http://www.rubycentral.org/pickaxe/irb.html
-
-
-== dbconsole
-
-You can go to the command line of your database directly through rails
-dbconsole. You would be connected to the database with the credentials
-defined in database.yml. Starting the script without arguments will connect you
-to the development database. Passing an argument will connect you to a different
-database, like rails dbconsole production. Currently works for MySQL,
-PostgreSQL and SQLite 3.
-
-== Description of Contents
-
-The default directory structure of a generated Ruby on Rails application:
-
- |-- app
- | |-- assets
- | | |-- images
- | | |-- javascripts
- | | `-- stylesheets
- | |-- controllers
- | |-- helpers
- | |-- mailers
- | |-- models
- | `-- views
- | `-- layouts
- |-- config
- | |-- environments
- | |-- initializers
- | `-- locales
- |-- db
- |-- doc
- |-- lib
- | |-- assets
- | `-- tasks
- |-- log
- |-- public
- |-- script
- |-- test
- | |-- fixtures
- | |-- functional
- | |-- integration
- | |-- performance
- | `-- unit
- |-- tmp
- | `-- cache
- | `-- assets
- `-- vendor
- |-- assets
- | |-- javascripts
- | `-- stylesheets
- `-- plugins
-
-app
- Holds all the code that's specific to this particular application.
-
-app/assets
- Contains subdirectories for images, stylesheets, and JavaScript files.
-
-app/controllers
- Holds controllers that should be named like weblogs_controller.rb for
- automated URL mapping. All controllers should descend from
- ApplicationController which itself descends from ActionController::Base.
-
-app/models
- Holds models that should be named like post.rb. Models descend from
- ActiveRecord::Base by default.
-
-app/views
- Holds the template files for the view that should be named like
- weblogs/index.html.erb for the WeblogsController#index action. All views use
- eRuby syntax by default.
-
-app/views/layouts
- Holds the template files for layouts to be used with views. This models the
- common header/footer method of wrapping views. In your views, define a layout
- using the layout :default and create a file named default.html.erb.
- Inside default.html.erb, call <% yield %> to render the view using this
- layout.
-
-app/helpers
- Holds view helpers that should be named like weblogs_helper.rb. These are
- generated for you automatically when using generators for controllers.
- Helpers can be used to wrap functionality for your views into methods.
-
-config
- Configuration files for the Rails environment, the routing map, the database,
- and other dependencies.
-
-db
- Contains the database schema in schema.rb. db/migrate contains all the
- sequence of Migrations for your schema.
-
-doc
- This directory is where your application documentation will be stored when
- generated using rake doc:app
-
-lib
- Application specific libraries. Basically, any kind of custom code that
- doesn't belong under controllers, models, or helpers. This directory is in
- the load path.
-
-public
- The directory available for the web server. Also contains the dispatchers and the
- default HTML files. This should be set as the DOCUMENT_ROOT of your web
- server.
-
-script
- Helper scripts for automation and generation.
-
-test
- Unit and functional tests along with fixtures. When using the rails generate
- command, template test files will be generated for you and placed in this
- directory.
-
-vendor
- External libraries that the application depends on. Also includes the plugins
- subdirectory. If the app has frozen rails, those gems also go here, under
- vendor/rails/. This directory is in the load path.
diff --git a/app/assets/javascripts/password_resets.js.coffee b/app/assets/javascripts/password_resets.js.coffee
new file mode 100644
index 0000000..7615679
--- /dev/null
+++ b/app/assets/javascripts/password_resets.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
diff --git a/app/assets/stylesheets/password_resets.css.scss b/app/assets/stylesheets/password_resets.css.scss
new file mode 100644
index 0000000..8160ad8
--- /dev/null
+++ b/app/assets/stylesheets/password_resets.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the password_resets controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/controllers/admin_controller.rb b/app/controllers/admin_controller.rb
index 5926b40..d7efbdb 100755
--- a/app/controllers/admin_controller.rb
+++ b/app/controllers/admin_controller.rb
@@ -1,6 +1,6 @@
class AdminController < ApplicationController
- # before_filter :administrative
+ before_filter :administrative, :if => :admin_param
skip_before_filter :has_info
def dashboard
@@ -44,5 +44,11 @@ class AdminController < ApplicationController
format.json { render :json => { :msg => message ? "success" : "failure"} }
end
end
+
+ private
+
+ def admin_param
+ params[:admin_id] != '1'
+ end
end
diff --git a/app/controllers/api/v1/users_controller.rb b/app/controllers/api/v1/users_controller.rb
new file mode 100644
index 0000000..6866774
--- /dev/null
+++ b/app/controllers/api/v1/users_controller.rb
@@ -0,0 +1,57 @@
+class Api::V1::UsersController < ApplicationController
+
+ skip_before_filter :authenticated
+ before_filter :valid_api_token
+ before_filter :extrapolate_user
+
+ respond_to :json
+
+ def index
+ # We removed the .as_json code from the model, just seemed like extra work.
+ # dunno, maybe useful at a later time?
+ #respond_with @user.admin ? User.all.as_json : @user.as_json
+
+ respond_with @user.admin ? User.all : @user
+ end
+
+ def show
+ respond_with @user.as_json
+ end
+
+private
+
+ def valid_api_token
+ authenticate_or_request_with_http_token do |token, options|
+ # TODO :add some functionality to check if the HTTP Header is valid
+ identify_user(token)
+ end
+ end
+
+ def identify_user(token="")
+ # We've had issues with URL encoding, etc. causing issues so just to be safe
+ # we will go ahead and unescape the user's token
+ unescape_token(token)
+ @clean_token =~ /(.*?)-(.*)/
+ id = $1
+ hash = $2
+ (id && hash) ? true : false
+ check_hash(id, hash) ? true : false
+ end
+
+ def check_hash(id, hash)
+ digest = OpenSSL::Digest::SHA1.hexdigest("#{ACCESS_TOKEN_SALT}:#{id}")
+ hash == digest
+ end
+
+ # We had some issues with the token and url encoding...
+ # this is an attempt to normalize the data.
+ def unescape_token(token="")
+ @clean_token = CGI::unescape(token)
+ end
+
+ # Added a method to make it easy to figure out who the user is.
+ def extrapolate_user
+ @user = User.find_by_id(@clean_token.split("-").first)
+ end
+
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index a0ef5cf..56ad260 100755
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -2,36 +2,39 @@ class ApplicationController < ActionController::Base
before_filter :authenticated, :has_info
helper_method :current_user, :is_admin?
-
+
# Our security guy keep talking about sea-surfing, cool story bro.
# protect_from_forgery
-
+
private
def current_user
- @current_user ||= User.find_by_user_id(session[:user_id].to_s)
+ @current_user ||= (
+ User.find_by_auth_token(cookies[:auth_token].to_s) ||
+ User.find_by_user_id(session[:user_id].to_s)
+ )
end
-
+
def authenticated
path = request.fullpath.present? ? root_url(:url => request.fullpath) : root_url
redirect_to path and reset_session if not current_user
end
def is_admin?
- current_user.admin if current_user
+ current_user.admin if current_user
end
def administrative
if not is_admin?
- reset_session
+ #reset_session
redirect_to root_url
end
end
-
+
def has_info
redirect = false
if current_user
- begin
+ begin
if !(current_user.retirement || current_user.paid_time_off.schedule || current_user.paid_time_off || current_user.work_info || current_user.performance)
redirect = true
end
@@ -41,5 +44,5 @@ class ApplicationController < ActionController::Base
end
redirect_to home_dashboard_index_path if redirect
end
-
+
end
diff --git a/app/controllers/password_resets_controller.rb b/app/controllers/password_resets_controller.rb
new file mode 100644
index 0000000..533643a
--- /dev/null
+++ b/app/controllers/password_resets_controller.rb
@@ -0,0 +1,63 @@
+class PasswordResetsController < ApplicationController
+ skip_before_filter :authenticated
+
+
+ def reset_password
+ user = Marshal.load(Base64.decode64(params[:user])) unless params[:user].nil?
+
+ if user && params[:password] && params[:confirm_password] && params[:password] == params[:confirm_password]
+ user.password = params[:password]
+ user.save!
+ flash[:success] = "Your password has been reset please login"
+ redirect_to :login
+ else
+ flash[:error] = "Error resetting your password. Please try again."
+ redirect_to :login
+ end
+ end
+
+ def confirm_token
+ if !params[:token].nil? && is_valid?(params[:token])
+ flash[:success] = "Password reset token confirmed! Please create a new password."
+ render :reset_password
+ else
+ flash[:error] = "Invalid password reset token. Please try again."
+ redirect_to :login
+ end
+ end
+
+ def forgot_password
+ @user = User.find_by_email(params[:email]) unless params[:email].nil?
+
+ if @user && password_reset_mailer(@user)
+ flash[:success] = "Password reset email sent to #{params[:email]}"
+ redirect_to :login
+ else
+ flash[:error] = "There was an issue sending password reset email to #{params[:email]}".html_safe unless params[:email].nil?
+ end
+ end
+
+ private
+
+ def password_reset_mailer(user)
+ token = generate_token(user.id, user.email)
+ UserMailer.forgot_password(user.email, token).deliver
+ end
+
+ def generate_token(id, email)
+ hash = Digest::MD5.hexdigest(email)
+ "#{id}-#{hash}"
+ end
+
+ def is_valid?(token)
+ if token =~ /(?\d+)-(?[A-Z0-9]{32})/i
+
+ # Fetch the user by their id, and hash their email address
+ @user = User.find_by_id($~[:user_id])
+ email = Digest::MD5.hexdigest(@user.email)
+
+ # Compare and validate our hashes
+ return true if email == $~[:email_hash]
+ end
+ end
+end
diff --git a/app/controllers/pay_controller.rb b/app/controllers/pay_controller.rb
new file mode 100644
index 0000000..6a71dc3
--- /dev/null
+++ b/app/controllers/pay_controller.rb
@@ -0,0 +1,43 @@
+class PayController < ApplicationController
+
+ def index
+ end
+
+ def update_dd_info
+ msg = false
+ pay = Pay.new(
+ :bank_account_num => params[:bank_account_num],
+ :bank_routing_num => params[:bank_routing_num],
+ :percent_of_deposit => params[:dd_percent]
+ )
+ pay.user_id = current_user.user_id
+ msg = true if pay.save!
+ respond_to do |format|
+ format.json {render :json => {:msg => msg } }
+ end
+ end
+
+ def show
+ respond_to do |format|
+ format.json { render :json => {:user => current_user.pay.as_json} }
+ end
+ end
+
+ def destroy
+ pay = Pay.find_by_id(params[:id])
+ if pay.present? and pay.destroy
+ flash[:success] = "Successfully Deleted Entry"
+ else
+ flash[:error] = "Unable to process that request at this time"
+ end
+ redirect_to user_pay_index_path
+ end
+
+ def decrypted_bank_acct_num
+ decrypted = Encryption.decrypt_sensitive_value(params[:value_to_decrypt])
+ respond_to do |format|
+ format.json {render :json => {:account_num => decrypted || "No Data" }}
+ end
+ end
+
+end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index 3f84173..a13bbc7 100755
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -8,7 +8,6 @@ class SessionsController < ApplicationController
redirect_to home_dashboard_index_path if current_user
end
-
def create
path = params[:url].present? ? params[:url] : home_dashboard_index_path
begin
@@ -19,7 +18,11 @@ class SessionsController < ApplicationController
end
if user
- session[:user_id] = user.user_id if User.where(:user_id => user.user_id).exists?
+ if params[:remember_me]
+ cookies.permanent[:auth_token] = user.auth_token if User.where(:user_id => user.user_id).exists?
+ else
+ session[:user_id] = user.user_id if User.where(:user_id => user.user_id).exists?
+ end
redirect_to path
else
# Removed this code, just doesn't seem specific enough!
@@ -30,6 +33,7 @@ class SessionsController < ApplicationController
end
def destroy
+ cookies.delete(:auth_token)
reset_session
redirect_to root_path
end
diff --git a/app/controllers/tutorials_controller.rb b/app/controllers/tutorials_controller.rb
index d27a0ca..69df74f 100755
--- a/app/controllers/tutorials_controller.rb
+++ b/app/controllers/tutorials_controller.rb
@@ -15,7 +15,6 @@ class TutorialsController < ApplicationController
end
def injection
-
end
def xss
@@ -62,6 +61,12 @@ class TutorialsController < ApplicationController
def misconfig
end
+
+ def insecure_components
+ end
+
+ def access_control
+ end
def crypto
end
@@ -78,55 +83,16 @@ class TutorialsController < ApplicationController
def guard
end
- def info_disclosure
- @bad_code_1 =
- %q{
-
-
-
-
Full Name
-
Income
-
Bonuses
-
Years w/ MetaCorp
-
SSN
-
DoB
-
-
-
-
-
-
<%= "#{@user.first_name} #{@user.last_name}" %>
-
<%= @user.work_info.income %>
-
<%= @user.work_info.bonuses %>
-
<%= @user.work_info.years_worked %>
-
<%= @user.work_info.SSN %>
-
<%= @user.work_info.DoB %>
-
-
-
-
- }
-
- @good_code_1 = %q{
- class WorkInfo < ActiveRecord::Base
- attr_accessible :DoB, :SSN, :bonuses, :income, :years_worked
- belongs_to :user
-
- # We should probably use this
- def last_four
- "***-**-" << self.SSN[-4,4]
- end
-
- end
- }
-
- @bad_code_2 = %q{
<%= @user.work_info.SSN %>
}
- @good_code_2 = %q{
<%= @user.work_info.last_four %>
}
+ def logic_flaws
end
def mass_assignment
end
+ def guantlt
+
+ end
+
def constantize
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index e7f1684..9a48c27 100755
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -3,6 +3,7 @@ class UsersController < ApplicationController
skip_before_filter :has_info
skip_before_filter :authenticated, :only => [:new, :create]
+
def new
@user = User.new
end
@@ -16,7 +17,7 @@ class UsersController < ApplicationController
else
@user = user
flash[:error] = user.errors.full_messages.to_sentence
- redirect_to :sign_up
+ redirect_to :signup
end
end
@@ -52,4 +53,4 @@ class UsersController < ApplicationController
end
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/api/v1/users_helper.rb b/app/helpers/api/v1/users_helper.rb
new file mode 100644
index 0000000..4d5288c
--- /dev/null
+++ b/app/helpers/api/v1/users_helper.rb
@@ -0,0 +1,2 @@
+module Api::V1::UsersHelper
+end
diff --git a/app/helpers/password_resets_helper.rb b/app/helpers/password_resets_helper.rb
new file mode 100644
index 0000000..0c9d96e
--- /dev/null
+++ b/app/helpers/password_resets_helper.rb
@@ -0,0 +1,2 @@
+module PasswordResetsHelper
+end
diff --git a/app/helpers/pay_helper.rb b/app/helpers/pay_helper.rb
new file mode 100644
index 0000000..0af6719
--- /dev/null
+++ b/app/helpers/pay_helper.rb
@@ -0,0 +1,2 @@
+module PayHelper
+end
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
new file mode 100644
index 0000000..209b839
--- /dev/null
+++ b/app/mailers/user_mailer.rb
@@ -0,0 +1,10 @@
+class UserMailer < ActionMailer::Base
+ default from: "noreply@railsgoat.dev"
+
+ def forgot_password(email, token)
+ @token = token
+ @url = url_for(controller: "password_resets", action: "reset_password", only_path: false) + "?token=#{token}"
+
+ mail(to: "#{email}", subject: "Reset your MetaCorp password")
+ end
+end
diff --git a/app/models/key_management.rb b/app/models/key_management.rb
new file mode 100644
index 0000000..174b80c
--- /dev/null
+++ b/app/models/key_management.rb
@@ -0,0 +1,6 @@
+class KeyManagement < ActiveRecord::Base
+ attr_accessible :iv, :user_id
+ belongs_to :work_info
+ belongs_to :user
+
+end
diff --git a/app/models/pay.rb b/app/models/pay.rb
new file mode 100644
index 0000000..78f0278
--- /dev/null
+++ b/app/models/pay.rb
@@ -0,0 +1,25 @@
+class Pay < ActiveRecord::Base
+
+ # mass-assignable attributes
+ attr_accessible :bank_account_num, :bank_routing_num, :percent_of_deposit
+
+ # Associations
+ belongs_to :user
+
+ # Validations
+ validates :bank_account_num, presence: true
+ validates :bank_routing_num, presence: true
+ validates :percent_of_deposit, presence: true
+
+ # callbacks
+ before_save :encrypt_bank_account_num
+
+ def as_json
+ super(only: [:bank_account_num, :bank_routing_num, :percent_of_deposit, :id])
+ end
+
+ def encrypt_bank_account_num
+ self.bank_account_num = Encryption.encrypt_sensitive_value(self.bank_account_num)
+ end
+
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 58e93b2..261703e 100755
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,11 +1,19 @@
+require 'encryption'
+
class User < ActiveRecord::Base
+
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,
- :if => :password#,
- #:format => {:with => /\A.*(?=.{10,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\@\#\$\%\^\&\+\=]).*\z/}
+ :if => :password
+=begin
+ validates :password, :presence => true,
+ :confirmation => true,
+ :if => :password,
+ :format => {:with => /\A.*(?=.{10,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[\@\#\$\%\^\&\+\=]).*\z/}
+=end
validates_presence_of :email
validates_uniqueness_of :email
validates_format_of :email, :with => /.+@.+\..+/i
@@ -18,36 +26,55 @@ class User < ActiveRecord::Base
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 :messages, :foreign_key => :receiver_id, :primary_key => :user_id, :dependent => :destroy
-
+ has_many :pay, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy
+ before_create { generate_token(:auth_token) }
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)
+ # Uncomment below line to use encrypted SSN(s)
+ #work_info.build_key_management(:iv => SecureRandom.hex(32))
performance.build(POPULATE_PERFORMANCE.shuffle.first)
end
def full_name
"#{self.first_name} #{self.last_name}"
end
+
+=begin
+ # Instead of the entire user object being returned, we can use this to filter.
+ def as_json
+ super(only: [:user_id, :email, :first_name, :last_name])
+ end
+=end
private
def self.authenticate(email, password)
auth = nil
user = find_by_email(email)
- if user
+ raise "#{email} doesn't exist!" if !(user)
if user.password == Digest::MD5.hexdigest(password)
auth = user
else
raise "Incorrect Password!"
end
- else
- raise "#{email} doesn't exist!"
- end
return auth
end
+=begin
+ # More secure version, still lacking a decent hashing routine, this is for timing attack prevention
+ def self.authenticate(email, password)
+ user = find_by_email(email) || User.new(:password => "")
+ if Rack::Utils.secure_compare(user.password, Digest::MD5.hexdigest(password))
+ return user
+ else
+ raise "Incorrect username or password"
+ end
+ end
+=end
+
def assign_user_id
unless @skip_user_id_assign.present? || self.user_id.present?
user = User.order("user_id").last
@@ -63,5 +90,11 @@ private
end
end
end
+
+ def generate_token(column)
+ begin
+ self[column] = Encryption.encrypt_sensitive_value(self.user_id)
+ end while User.exists?(column => self[column])
+ end
end
diff --git a/app/models/work_info.rb b/app/models/work_info.rb
index c3b70b6..c8e30d8 100644
--- a/app/models/work_info.rb
+++ b/app/models/work_info.rb
@@ -1,17 +1,44 @@
class WorkInfo < ActiveRecord::Base
attr_accessible :DoB, :SSN, :bonuses, :income, :years_worked
belongs_to :user
+ has_one :key_management, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy
#before_save :encrypt_ssn
+
# We should probably use this
def last_four
- "***-**-" << self.SSN[-4,4]
+ "***-**-" << self.decrypt_ssn[-4,4]
end
def encrypt_ssn
+ aes = OpenSSL::Cipher::Cipher.new(cipher_type)
+ aes.encrypt
+ aes.key = key
+ aes.iv = iv if iv != nil
+ self.encrypted_ssn = aes.update(self.SSN) + aes.final
+ self.SSN = nil
end
def decrypt_ssn
+ aes = OpenSSL::Cipher::Cipher.new(cipher_type)
+ aes.decrypt
+ aes.key = key
+ aes.iv = iv if iv != nil
+ aes.update(self.encrypted_ssn) + aes.final
+ end
+
+ def key
+ raise "Key Missing" if !(KEY)
+ KEY
+ end
+
+ def iv
+ raise "No IV for this User" if !(self.key_management.iv)
+ self.key_management.iv
+ end
+
+ def cipher_type
+ 'aes-256-cbc'
end
end
diff --git a/app/views/admin/dashboard.html.erb b/app/views/admin/dashboard.html.erb
index 3e1466c..da2c845 100755
--- a/app/views/admin/dashboard.html.erb
+++ b/app/views/admin/dashboard.html.erb
@@ -59,7 +59,7 @@ function makeActive(){
};
function loadTable(){
- $("#userDataTable").load("/admin/"+ <%=current_user.user_id %> + "/get_all_users")
+ $("#userDataTable").load("/admin/"+ <%= params[:admin_id] %> + "/get_all_users")
};
$(document).ready(
diff --git a/app/views/layouts/admin/_get_user.html.erb b/app/views/layouts/admin/_get_user.html.erb
index eda97d7..9557b7d 100755
--- a/app/views/layouts/admin/_get_user.html.erb
+++ b/app/views/layouts/admin/_get_user.html.erb
@@ -83,7 +83,7 @@ $('#delete_button').click(function() {
$("#editAcct").modal('hide');
$.ajax({
- url: "/admin/" + <%= @user.user_id %> + "/delete_user.json",
+ url: "/admin/" + <%= params[:admin_id] %> + "/delete_user.json",
type: "POST",
success: function(response) {
$('#success').show(500).delay(1500).fadeOut();
diff --git a/app/views/layouts/shared/_sidebar.html.erb b/app/views/layouts/shared/_sidebar.html.erb
index 1add2e3..7114b08 100755
--- a/app/views/layouts/shared/_sidebar.html.erb
+++ b/app/views/layouts/shared/_sidebar.html.erb
@@ -65,6 +65,14 @@
Messages
<% end %>
+
+
+ <%= link_to user_pay_index_path(:user_id => current_user.user_id) do %>
+
\ No newline at end of file
diff --git a/app/views/tutorials/info_disclosure.html.erb b/app/views/tutorials/access_control.html.erb
similarity index 61%
rename from app/views/tutorials/info_disclosure.html.erb
rename to app/views/tutorials/access_control.html.erb
index b482a01..6796302 100644
--- a/app/views/tutorials/info_disclosure.html.erb
+++ b/app/views/tutorials/access_control.html.erb
@@ -2,7 +2,7 @@
@@ -10,8 +10,7 @@
\ No newline at end of file
diff --git a/app/views/tutorials/insecure_components.html.erb b/app/views/tutorials/insecure_components.html.erb
new file mode 100644
index 0000000..271f7a9
--- /dev/null
+++ b/app/views/tutorials/insecure_components.html.erb
@@ -0,0 +1,17 @@
+
+
+
\ No newline at end of file
diff --git a/app/views/tutorials/logic_flaws.html.erb b/app/views/tutorials/logic_flaws.html.erb
new file mode 100644
index 0000000..ed83c4f
--- /dev/null
+++ b/app/views/tutorials/logic_flaws.html.erb
@@ -0,0 +1,24 @@
+
+ A password reset was requested for your user account.
+
+
+ To reset your MetaCorp password, simply click on the
+ following link and follow the instructions:
+
+
+ <%= link_to "Click here to reset your password", @url %>
+
+
+ If you don't want to change your password, you can ignore this email.
+
+
Thanks, and have a great day!
+
+
\ No newline at end of file
diff --git a/app/views/user_mailer/forgot_password.text.erb b/app/views/user_mailer/forgot_password.text.erb
new file mode 100644
index 0000000..92067db
--- /dev/null
+++ b/app/views/user_mailer/forgot_password.text.erb
@@ -0,0 +1,13 @@
+Need help logging in?
+==========================================================
+
+A password reset was requested for your user account.
+
+To reset your MetaCorp password, simply copy the
+following link and follow the instructions:
+
+<%= @url %>
+
+If you don't want to change your password, you can ignore this email.
+
+Thanks, and have a great day!
\ No newline at end of file
diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb
index 27f3738..cf03ae2 100755
--- a/app/views/users/new.html.erb
+++ b/app/views/users/new.html.erb
@@ -13,22 +13,17 @@
diff --git a/config/application.rb b/config/application.rb
index 4bac9da..1597890 100755
--- a/config/application.rb
+++ b/config/application.rb
@@ -40,7 +40,7 @@ module Railsgoat
config.filter_parameters += [:password]
# Enable escaping HTML in JSON.
- config.active_support.escape_html_entities_in_json = true
+ #config.active_support.escape_html_entities_in_json = false
# Use SQL instead of Active Record's schema dumper when creating the database.
# This is necessary if your schema can't be completely dumped by the schema dumper,
@@ -51,7 +51,7 @@ module Railsgoat
# This will create an empty whitelist of attributes available for mass-assignment for all models
# in your app. As such, your models will need to explicitly whitelist or blacklist accessible
# parameters by using an attr_accessible or attr_protected declaration.
- config.active_record.whitelist_attributes = true
+ config.active_record.whitelist_attributes = false
# Enable the asset pipeline
config.assets.enabled = true
@@ -61,5 +61,7 @@ module Railsgoat
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
+
+ I18n.config.enforce_available_locales = false
end
end
diff --git a/config/environments/development.rb b/config/environments/development.rb
index 9db258d..9ff11cf 100755
--- a/config/environments/development.rb
+++ b/config/environments/development.rb
@@ -28,13 +28,21 @@ Railsgoat::Application.configure do
# Log the query plan for queries taking more than this (works
# with SQLite, MySQL, and PostgreSQL)
config.active_record.auto_explain_threshold_in_seconds = 0.5
+
+ # Tired of caching causing issues
+ config.middleware.delete Rack::ETag
# Do not compress assets
config.assets.compress = false
# Expands the lines which load the assets
config.assets.debug = true
-
+
+ # ActionMailer settings for email support
+ config.action_mailer.delivery_method = :smtp
+ config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }
+ config.action_mailer.default_url_options = { :host => "localhost:3000" }
+
config.middleware.insert_before(
Rack::Lock, Rack::LiveReload,
:min_delay => 500,
diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb
new file mode 100644
index 0000000..086522f
--- /dev/null
+++ b/config/initializers/constants.rb
@@ -0,0 +1,3 @@
+ACCESS_TOKEN_SALT = "S4828341189aefiasd#ASDF"
+
+RG_IV = "PPKLKAJDKGHALDJL482823458028"
\ No newline at end of file
diff --git a/config/initializers/html_entities.rb b/config/initializers/html_entities.rb
new file mode 100644
index 0000000..4db1c30
--- /dev/null
+++ b/config/initializers/html_entities.rb
@@ -0,0 +1 @@
+ActiveSupport::JSON::Encoding::escape_html_entities_in_json = false
diff --git a/config/initializers/key.rb b/config/initializers/key.rb
new file mode 100644
index 0000000..89022ee
--- /dev/null
+++ b/config/initializers/key.rb
@@ -0,0 +1,5 @@
+if Rails.env.production?
+ # Specify env variable/location/etc. to retrieve key from
+else
+ KEY = "123456789101112123456789101112123456789101112"
+end
diff --git a/config/routes.rb b/config/routes.rb
index 5770161..9386fd0 100755
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,83 +1,102 @@
Railsgoat::Application.routes.draw do
-get "login" => "sessions#new"
-get "signup" => "users#new"
-get "logout" => "sessions#destroy"
+ get "login" => "sessions#new"
+ get "signup" => "users#new"
+ get "logout" => "sessions#destroy"
+ match "forgot_password" => "password_resets#forgot_password"
+ get "password_resets" => "password_resets#confirm_token"
+ post "password_resets" => "password_resets#reset_password"
-resources :sessions do
-end
+ resources :sessions do
+ end
-resources :users do
- get "account_settings"
-
- resources :retirement do
- end
-
- resources :paid_time_off do
- end
-
- resources :work_info do
- end
-
- resources :performance do
-
- end
-
- resources :benefit_forms do
+ resources :users do
+ get "account_settings"
+
+ resources :retirement do
+ end
+
+ resources :paid_time_off do
+ end
+
+ resources :work_info do
+ end
+
+ resources :performance do
+
+ end
+
+ resources :benefit_forms do
+
+ end
+
+ resources :messages do
+ end
+ resources :pay do
+ collection do
+ post "update_dd_info"
+ post "decrypted_bank_acct_num"
+ end
+ end
+
end
- resources :messages do
+ get "download" => "benefit_forms#download"
+ post "upload" => "benefit_forms#upload"
+
+ resources :tutorials do
+ collection do
+ get "credentials"
+ get "injection"
+ get "xss"
+ get "broken_auth"
+ get "insecure_dor"
+ get "csrf"
+ get "misconfig"
+ get "exposure"
+ get "url_access"
+ get "insecure_components"
+ get "access_control"
+ get "ssl_tls"
+ get "redirects"
+ get "guard"
+ get "mass_assignment"
+ get "constantize"
+ get "gauntlt"
+ get "logic_flaws"
+ end
+ end
+
+ resources :schedule do
+ collection do
+ get "get_pto_schedule"
+ end
+
+ end
+
+ resources :admin do
+ get "dashboard"
+ get "get_user"
+ post "delete_user"
+ put "update_user"
+ get "get_all_users"
+ end
+
+ resources :dashboard do
+ collection do
+ get "home"
+ end
end
-end
-
-get "download" => "benefit_forms#download"
-post "upload" => "benefit_forms#upload"
-
-resources :tutorials do
- collection do
- get "credentials"
- get "injection"
- get "xss"
- get "broken_auth"
- get "insecure_dor"
- get "csrf"
- get "misconfig"
- get "crypto"
- get "url_access"
- get "ssl_tls"
- get "redirects"
- get "guard"
- get "info_disclosure"
- get "mass_assignment"
- get "constantize"
- end
-end
-
-resources :schedule do
- collection do
- get "get_pto_schedule"
- end
-
-end
-
-resources :admin do
- get "dashboard"
- get "get_user"
- post "delete_user"
- put "update_user"
- get "get_all_users"
-end
-
-resources :dashboard do
- collection do
- get "home"
- end
-end
+ namespace :api, defaults: {format: 'json'} do
+ namespace :v1 do
+ resources :users
+ end
+ end
-root :to => "sessions#new"
+ root :to => "sessions#new"
end
diff --git a/db/migrate/20131112235256_add_encrypted_ssn_to_work_infos.rb b/db/migrate/20131112235256_add_encrypted_ssn_to_work_infos.rb
new file mode 100644
index 0000000..2c7935a
--- /dev/null
+++ b/db/migrate/20131112235256_add_encrypted_ssn_to_work_infos.rb
@@ -0,0 +1,5 @@
+class AddEncryptedSsnToWorkInfos < ActiveRecord::Migration
+ def change
+ add_column :work_infos, :encrypted_ssn, :binary
+ end
+end
diff --git a/db/migrate/20131113200708_create_key_managements.rb b/db/migrate/20131113200708_create_key_managements.rb
new file mode 100644
index 0000000..96ce247
--- /dev/null
+++ b/db/migrate/20131113200708_create_key_managements.rb
@@ -0,0 +1,10 @@
+class CreateKeyManagements < ActiveRecord::Migration
+ def change
+ create_table :key_managements do |t|
+ t.string :iv
+ t.integer :user_id
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20140312002642_add_auth_token_to_users.rb b/db/migrate/20140312002642_add_auth_token_to_users.rb
new file mode 100644
index 0000000..2c83ac1
--- /dev/null
+++ b/db/migrate/20140312002642_add_auth_token_to_users.rb
@@ -0,0 +1,5 @@
+class AddAuthTokenToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :auth_token, :string
+ end
+end
diff --git a/db/migrate/20140315002730_create_pays.rb b/db/migrate/20140315002730_create_pays.rb
new file mode 100644
index 0000000..78a9b37
--- /dev/null
+++ b/db/migrate/20140315002730_create_pays.rb
@@ -0,0 +1,12 @@
+class CreatePays < ActiveRecord::Migration
+ def change
+ create_table :pays do |t|
+ t.integer :user_id
+ t.string :bank_account_num
+ t.string :bank_routing_num
+ t.integer :percent_of_deposit
+
+ t.timestamps
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 2adcc14..a32189b 100755
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,13 +11,20 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20131011180207) do
+ActiveRecord::Schema.define(:version => 20140315002730) do
create_table "benefits", :force => true do |t|
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
+ create_table "key_managements", :force => true do |t|
+ t.string "iv"
+ t.integer "user_id"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "messages", :force => true do |t|
t.integer "creator_id"
t.integer "receiver_id"
@@ -37,6 +44,15 @@ ActiveRecord::Schema.define(:version => 20131011180207) do
t.datetime "updated_at", :null => false
end
+ create_table "pays", :force => true do |t|
+ t.integer "user_id"
+ t.string "bank_account_num"
+ t.string "bank_routing_num"
+ t.integer "percent_of_deposit"
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
create_table "performances", :force => true do |t|
t.integer "user_id"
t.date "date_submitted"
@@ -76,6 +92,7 @@ ActiveRecord::Schema.define(:version => 20131011180207) do
t.integer "user_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
+ t.string "auth_token"
end
create_table "work_infos", :force => true do |t|
@@ -85,8 +102,9 @@ ActiveRecord::Schema.define(:version => 20131011180207) do
t.integer "years_worked"
t.string "SSN"
t.date "DoB"
- t.datetime "created_at", :null => false
- t.datetime "updated_at", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ t.binary "encrypted_ssn"
end
end
diff --git a/db/seeds.rb b/db/seeds.rb
index 3533d20..9750f25 100755
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -33,8 +33,8 @@ users = [
{
:email => "mike@metacorp.com",
:admin => false,
- :password => "motorcross1445",
- :password_confirmation => "motorcross1445",
+ :password => "motocross1445",
+ :password_confirmation => "motocross1445",
:first_name => "Mike",
:last_name => "McCabe",
:user_id =>4
@@ -289,12 +289,6 @@ schedule.each do |event|
sched.save
end
-work_info.each do |wi|
- info = WorkInfo.new(wi.reject {|k| k == :user_id})
- info.user_id = wi[:user_id]
- info.save
-end
-
performance.each do |perf|
p = Performance.new(perf.reject {|k| k == :user_id})
p.user_id = perf[:user_id]
@@ -306,3 +300,21 @@ messages.each do |message|
m.creator_id = message[:creator_id]
m.save
end
+
+work_info.each do |wi|
+ info = WorkInfo.new(wi.reject {|k| k == :user_id } )
+ info.user_id = wi[:user_id]
+ info.save
+end
+
+
+=begin
+work_info.each do |wi|
+ list = [:user_id, :SSN]
+ info = WorkInfo.new(wi.reject {|k| list.include?(k)})
+ info.user_id = wi[:user_id]
+ info.build_key_management({:user_id => wi[:user_id], :iv => SecureRandom.hex(32) })
+ info.SSN = wi[:SSN]
+ info.save
+end
+=end
diff --git a/lib/encryption.rb b/lib/encryption.rb
new file mode 100644
index 0000000..defa525
--- /dev/null
+++ b/lib/encryption.rb
@@ -0,0 +1,36 @@
+module Encryption
+
+ # Added a re-usable encryption routine, shouldn't be an issue!
+ def self.encrypt_sensitive_value(val="")
+ aes = OpenSSL::Cipher::Cipher.new(cipher_type)
+ aes.encrypt
+ aes.key = key
+ aes.iv = iv if iv != nil
+ new_val = aes.update("#{val}") + aes.final
+ Base64.strict_encode64(new_val).encode('utf-8')
+ end
+
+ def self.decrypt_sensitive_value(val="")
+ aes = OpenSSL::Cipher::Cipher.new(cipher_type)
+ aes.decrypt
+ aes.key = key
+ aes.iv = iv if iv != nil
+ decoded = Base64.strict_decode64("#{val}")
+ aes.update("#{decoded}") + aes.final
+ end
+
+ # Should be able to just re-use the same key we already have!
+ def self.key
+ raise "Key Missing" if !(KEY)
+ KEY
+ end
+
+ def self.iv
+ RG_IV
+ end
+
+ def self.cipher_type
+ 'aes-256-cbc'
+ end
+
+end
\ No newline at end of file
diff --git a/spec/controllers/api/v1/users_controller_spec.rb b/spec/controllers/api/v1/users_controller_spec.rb
new file mode 100644
index 0000000..9b5309e
--- /dev/null
+++ b/spec/controllers/api/v1/users_controller_spec.rb
@@ -0,0 +1,6 @@
+=begin require 'spec_helper'
+
+describe Api::V1::UsersController do
+
+end
+=end
\ No newline at end of file
diff --git a/spec/controllers/messages_controller_spec.rb b/spec/controllers/messages_controller_spec.rb
index 503cc98..335cafc 100644
--- a/spec/controllers/messages_controller_spec.rb
+++ b/spec/controllers/messages_controller_spec.rb
@@ -1,5 +1 @@
-require 'spec_helper'
-
-describe MessagesController do
-
-end
+require 'spec_helper'
\ No newline at end of file
diff --git a/spec/controllers/password_resets_controller_spec.rb b/spec/controllers/password_resets_controller_spec.rb
new file mode 100644
index 0000000..335cafc
--- /dev/null
+++ b/spec/controllers/password_resets_controller_spec.rb
@@ -0,0 +1 @@
+require 'spec_helper'
\ No newline at end of file
diff --git a/spec/controllers/pay_controller_spec.rb b/spec/controllers/pay_controller_spec.rb
new file mode 100644
index 0000000..84b6475
--- /dev/null
+++ b/spec/controllers/pay_controller_spec.rb
@@ -0,0 +1,6 @@
+=begin require 'spec_helper'
+
+describe PayController do
+
+end
+=end
diff --git a/spec/helpers/api/v1/users_helper_spec.rb b/spec/helpers/api/v1/users_helper_spec.rb
new file mode 100644
index 0000000..9619df0
--- /dev/null
+++ b/spec/helpers/api/v1/users_helper_spec.rb
@@ -0,0 +1,16 @@
+=begin require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the Api::V1::UsersHelper. For example:
+#
+# describe Api::V1::UsersHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# expect(helper.concat_strings("this","that")).to eq("this that")
+# end
+# end
+# end
+describe Api::V1::UsersHelper do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
+=end
\ No newline at end of file
diff --git a/spec/helpers/messages_helper_spec.rb b/spec/helpers/messages_helper_spec.rb
index a29b665..f8ec369 100644
--- a/spec/helpers/messages_helper_spec.rb
+++ b/spec/helpers/messages_helper_spec.rb
@@ -1,15 +1 @@
require 'spec_helper'
-
-# Specs in this file have access to a helper object that includes
-# the MessagesHelper. For example:
-#
-# describe MessagesHelper do
-# describe "string concat" do
-# it "concats two strings with spaces" do
-# expect(helper.concat_strings("this","that")).to eq("this that")
-# end
-# end
-# end
-describe MessagesHelper do
- pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/helpers/password_resets_helper_spec.rb b/spec/helpers/password_resets_helper_spec.rb
new file mode 100644
index 0000000..b87346e
--- /dev/null
+++ b/spec/helpers/password_resets_helper_spec.rb
@@ -0,0 +1,16 @@
+=begin require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the PasswordResetsHelper. For example:
+#
+# describe PasswordResetsHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# expect(helper.concat_strings("this","that")).to eq("this that")
+# end
+# end
+# end
+describe PasswordResetsHelper do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
+=end
\ No newline at end of file
diff --git a/spec/helpers/pay_helper_spec.rb b/spec/helpers/pay_helper_spec.rb
new file mode 100644
index 0000000..408d779
--- /dev/null
+++ b/spec/helpers/pay_helper_spec.rb
@@ -0,0 +1,16 @@
+=begin require 'spec_helper'
+
+# Specs in this file have access to a helper object that includes
+# the PayHelper. For example:
+#
+# describe PayHelper do
+# describe "string concat" do
+# it "concats two strings with spaces" do
+# expect(helper.concat_strings("this","that")).to eq("this that")
+# end
+# end
+# end
+describe PayHelper do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
+=end
\ No newline at end of file
diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb
new file mode 100644
index 0000000..a79b75f
--- /dev/null
+++ b/spec/mailers/user_mailer_spec.rb
@@ -0,0 +1 @@
+require "spec_helper"
\ No newline at end of file
diff --git a/spec/models/key_management_spec.rb b/spec/models/key_management_spec.rb
new file mode 100644
index 0000000..335cafc
--- /dev/null
+++ b/spec/models/key_management_spec.rb
@@ -0,0 +1 @@
+require 'spec_helper'
\ No newline at end of file
diff --git a/spec/models/message_spec.rb b/spec/models/message_spec.rb
index a5f59dd..f8ec369 100644
--- a/spec/models/message_spec.rb
+++ b/spec/models/message_spec.rb
@@ -1,5 +1 @@
require 'spec_helper'
-
-describe Message do
- pending "add some examples to (or delete) #{__FILE__}"
-end
diff --git a/spec/models/pay_spec.rb b/spec/models/pay_spec.rb
new file mode 100644
index 0000000..1b4399c
--- /dev/null
+++ b/spec/models/pay_spec.rb
@@ -0,0 +1,6 @@
+=begin require 'spec_helper'
+
+describe Pay do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
+=end
\ No newline at end of file
diff --git a/spec/support/capybara_shared.rb b/spec/support/capybara_shared.rb
index 1b323ba..e140dd4 100644
--- a/spec/support/capybara_shared.rb
+++ b/spec/support/capybara_shared.rb
@@ -13,22 +13,21 @@ def verifying_fixed?
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.
+ ******************************************************************************
+ 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.
+ 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. When the vulnerabilities
+ are removed, the specs will not "pass," but rather go into a "pending" state.
+ ******************************************************************************
- **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
@@ -43,3 +42,41 @@ def login(user)
end
click_on 'Login'
end
+
+##Hack to fix PhantomJS errors on Mavericks - https://gist.github.com/ericboehs/7125105
+module Capybara::Poltergeist
+ class Client
+ private
+ def redirect_stdout
+ prev = STDOUT.dup
+ prev.autoclose = false
+ $stdout = @write_io
+ STDOUT.reopen(@write_io)
+
+ prev = STDERR.dup
+ prev.autoclose = false
+ $stderr = @write_io
+ STDERR.reopen(@write_io)
+ yield
+ ensure
+ STDOUT.reopen(prev)
+ $stdout = STDOUT
+ STDERR.reopen(prev)
+ $stderr = STDERR
+ end
+ end
+end
+
+class WarningSuppressor
+ class << self
+ def write(message)
+ if message =~ /QFont::setPixelSize: Pixel size <= 0/ || message =~/CoreText performance note:/ || message =~/Method userSpaceScaleFactor in class NSView/ then 0 else puts(message);1;end
+ end
+ end
+end
+
+Capybara.register_driver :poltergeist do |app|
+ Capybara::Poltergeist::Driver.new(app, phantomjs_logger: WarningSuppressor, timeout: 60)
+end
+
+Capybara.javascript_driver = :poltergeist
diff --git a/spec/views/password_resets/new.html.erb_spec.rb b/spec/views/password_resets/new.html.erb_spec.rb
new file mode 100644
index 0000000..fcb6721
--- /dev/null
+++ b/spec/views/password_resets/new.html.erb_spec.rb
@@ -0,0 +1,6 @@
+=begin require 'spec_helper'
+
+describe "password_resets/new.html.erb" do
+ pending "add some examples to (or delete) #{__FILE__}"
+end
+=end
\ No newline at end of file
diff --git a/spec/vulnerabilities/info_disclosure_spec.rb b/spec/vulnerabilities/sensitive_data_exposure.rb
similarity index 91%
rename from spec/vulnerabilities/info_disclosure_spec.rb
rename to spec/vulnerabilities/sensitive_data_exposure.rb
index ce0bd2a..bc1e72e 100644
--- a/spec/vulnerabilities/info_disclosure_spec.rb
+++ b/spec/vulnerabilities/sensitive_data_exposure.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-feature 'sensitive information disclosure' do
+feature 'sensitive data exposure' do
before do
UserFixture.reset_all_users
@normal_user = UserFixture.normal_user