diff --git a/README.md b/README.md index 005ac87..5bd8797 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@ vulnerable and configurable in its vulnerability. Route | Required parameters | Optional Parameters --- | --- | --- -`/timing/conditional_hashing` | `login` | `delta` +`/timing/conditional_hashing` | `email` | `delta` `/timing/string_comparison` | `password` | `delta` -`/timing/login` | `login`, `password` | `delta` +`/timing/login` | `email`, `password` | `delta` `/timing/basic_auth` | `password` | `delta` `/injections/sql/raw_sql` | `name` | `/injections/sql/raw_where` | `name` | @@ -27,7 +27,7 @@ Edit `.env` to contain appropriate values, then ## Timing Vulnerabilities ### Conditional Hashing -The `login` parameter is the email address to test for inclusion in the +The `email` parameter is the email address to test for inclusion in the "database," and is required. The `delta` URL parameter can be provided to tell the application the timing @@ -48,7 +48,7 @@ comparison (that is, no additional delay is introduced). ### Login -`login` and `password` parameters are required. +`email` and `password` parameters are required. This endpoint simply combines conditional hashing and insecure string comparison for a full vulnerable login experience. A provided `delta` parameter will be diff --git a/app/controllers/injections/template_injections_controller.rb b/app/controllers/injections/template_injections_controller.rb index 9259845..f8adef1 100644 --- a/app/controllers/injections/template_injections_controller.rb +++ b/app/controllers/injections/template_injections_controller.rb @@ -7,7 +7,7 @@ def index end def interpolation - render plain: injection_command.execute + render html: injection_command.execute end private diff --git a/app/controllers/timing_vulnerabilities_controller.rb b/app/controllers/timing_vulnerabilities_controller.rb index 544af0b..ee59df4 100644 --- a/app/controllers/timing_vulnerabilities_controller.rb +++ b/app/controllers/timing_vulnerabilities_controller.rb @@ -1,8 +1,13 @@ class TimingVulnerabilitiesController < ApplicationController def login - user_result = user_finder.execute - comparator_result = string_comparator.execute - determine_access(user_result && comparator_result) + user_result = ConditionalHashing.new(timing_params[:email], + delta: timing_params[:delta] + ).execute + actual_password = Camel.where(email: timing_params[:email]).pluck(:password).first + comparator_result = InsecureStringComparison.new(timing_params[:password], + against: actual_password + ).execute + determine_access(user_result && comparator_result, set: timing_params[:email]) end def conditional_hashing @@ -30,7 +35,7 @@ def index private def user_finder - @user_finder ||= ConditionalHashing.new(timing_params[:login], + @user_finder ||= ConditionalHashing.new(timing_params[:email], delta: timing_params[:delta]) end @@ -40,11 +45,12 @@ def string_comparator end def timing_params - params.permit(:login, :password, :delta) + params.permit(:email, :password, :delta) end - def determine_access(bool) + def determine_access(bool, set: nil) if bool + session[:email] = set if set render plain: "Authorized", status: :ok else render plain: "Unauthorized", status: :unauthorized diff --git a/app/models/camel.rb b/app/models/camel.rb index 91aa43a..84f02ab 100644 --- a/app/models/camel.rb +++ b/app/models/camel.rb @@ -1,2 +1,7 @@ class Camel < ApplicationRecord + validates :name, presence: true + validates :breed, presence: true + validates :email, presence: true + validates_uniqueness_of :email + validates :password, presence: true end diff --git a/app/services/conditional_hashing.rb b/app/services/conditional_hashing.rb index ddf1c31..35943eb 100644 --- a/app/services/conditional_hashing.rb +++ b/app/services/conditional_hashing.rb @@ -8,7 +8,7 @@ def initialize(login, delta: max_delta) # Return value is whether @login is valid def execute - found = valid_logins.include?(login) + found = Camel.where(email: login).present? sleep(delta) if found found end @@ -22,13 +22,8 @@ def hint attr_reader :login, :delta MAX_DELTA = 0.10 - LOGINS = %w(charles@poodles.com camel@sahara.com bactrian@dev.null dromedary@dev.null).freeze def max_delta MAX_DELTA end - - def valid_logins - LOGINS - end end diff --git a/app/services/insecure_string_comparison.rb b/app/services/insecure_string_comparison.rb index 3c8afd5..f29a581 100644 --- a/app/services/insecure_string_comparison.rb +++ b/app/services/insecure_string_comparison.rb @@ -1,9 +1,10 @@ # Performs insecure string comparison, wherein the first non-matching byte # causes an early return. class InsecureStringComparison - def initialize(candidate, delta: max_delta) + def initialize(candidate, delta: max_delta, against: BITSTREAM) @delta = [max_delta, delta.to_f].min @candidate = candidate.to_s.bytes + @bitstream = against.to_s end def execute @@ -39,12 +40,8 @@ def hint MAX_DELTA = 0.05 - def bitstream - BITSTREAM - end - def max_delta MAX_DELTA end - attr_reader :candidate, :delta + attr_reader :candidate, :delta, :bitstream end diff --git a/app/services/template_injection.rb b/app/services/template_injection.rb index 7e2f633..df98248 100644 --- a/app/services/template_injection.rb +++ b/app/services/template_injection.rb @@ -8,13 +8,14 @@ def hint end def execute - erb.result + erb.result.html_safe end private def interpolate(string) <<-EOF.strip_heredoc +
+--------------------------------------+
| Hello, #{string} |
+--------------------------------------+
@@ -24,6 +25,7 @@ def interpolate(string)
`-,,, ,_ ;'~U'
_,-' ,'`-__; '--.
(_/'~~ ''''(;
+
EOF
end
diff --git a/config/application.rb b/config/application.rb
index 2bfb086..fe9049a 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -8,6 +8,10 @@
module Camelflage
class Application < Rails::Application
- # config.api_only = true
+ config.action_dispatch.default_headers = {
+ 'X-Frame-Options' => 'SAMEORIGIN',
+ 'X-XSS-Protection' => '0',
+ 'X-Content-Type-Options' => 'nosniff'
+ }
end
end
diff --git a/config/routes.rb b/config/routes.rb
index 98fdf3e..18e916d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,4 +1,6 @@
Rails.application.routes.draw do
+ post :login, to: 'timing_vulnerabilities#login'
+
resource :timing, controller: 'timing_vulnerabilities', only: [] do
get :index
match :login, via: %i(post get)
diff --git a/db/migrate/20170512021209_add_login_fields_to_camels.rb b/db/migrate/20170512021209_add_login_fields_to_camels.rb
new file mode 100644
index 0000000..cd9a2fa
--- /dev/null
+++ b/db/migrate/20170512021209_add_login_fields_to_camels.rb
@@ -0,0 +1,7 @@
+class AddLoginFieldsToCamels < ActiveRecord::Migration[5.0]
+ def change
+ add_column :camels, :email, :string, unique: true
+ add_column :camels, :password, :string
+ add_column :camels, :is_admin, :boolean, default: false
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 44f2a65..4286e11 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,14 +10,20 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20161224052218) do
+ActiveRecord::Schema.define(version: 20170512021209) do
+
+ # These are extensions that must be enabled in order to support this database
+ enable_extension "plpgsql"
create_table "camels", force: :cascade do |t|
- t.string "name", null: false
- t.string "breed", null: false
+ t.string "name", null: false
+ t.string "breed", null: false
t.string "notes"
- 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.string "email"
+ t.string "password"
+ t.boolean "is_admin", default: false
end
end
diff --git a/db/seeds.rb b/db/seeds.rb
index ec199b7..d0429e9 100644
--- a/db/seeds.rb
+++ b/db/seeds.rb
@@ -1,3 +1,24 @@
-Camel.create!(name: "Perl", breed: "dromedary", notes: "Enjoys regex")
-Camel.create!(name: "Joe", breed: "dromedary", notes: "Particularly cool")
-Camel.create!(name: "Alphons", breed: "bactrian", notes: "Has pretty eyes")
+Camel.create!(name: "Perl",
+ breed: "dromedary",
+ notes: "Enjoys regex",
+ email: "perl@perl.org",
+ password: "3usq7#bJCn4E",
+ is_admin: true)
+Camel.create!(name: "Joe",
+ breed: "dromedary",
+ notes: "Particularly cool",
+ email: "joe@camel.com",
+ password: "love",
+ is_admin: false)
+Camel.create!(name: "Alphons",
+ breed: "bactrian",
+ notes: "Has pretty eyes",
+ email: "alphons@perl.net",
+ password: "zKQ4xFZn!7g%",
+ is_admin: false)
+Camel.create!(name: "Charles",
+ breed: "ACTUALLY A POODLE",
+ notes: "How did a dog get in the camels table computers are hard",
+ email: "charles@poodleparade.com",
+ password: "i<3p0rkC#opz",
+ is_admin: false)
diff --git a/public/index.html b/public/index.html
index 3554f03..1063d75 100644
--- a/public/index.html
+++ b/public/index.html
@@ -12,7 +12,7 @@ /timing/conditional_hashingloginemaildelta/timing/loginlogin, passwordemail, passworddeltaThe login parameter is the email address to test for inclusion in the
+
The email parameter is the email address to test for inclusion in the
"database," and is required.
The delta URL parameter can be provided to tell the application the timing
@@ -77,7 +77,7 @@
login and password parameters are required.
email and password parameters are required.
This endpoint simply combines conditional hashing and insecure string comparison
for a full vulnerable login experience. A provided delta parameter will be