fix for possible injection with mongo

Signed-off-by: José Valim <jose.valim@gmail.com>

Conflicts:

	lib/devise/models/authenticatable.rb
	test/integration/token_authenticatable_test.rb
	test/models/token_authenticatable_test.rb
This commit is contained in:
José Valim
2011-03-11 21:07:48 +01:00
parent 2b123f3017
commit 12ba8603a5
3 changed files with 83 additions and 1 deletions

View File

@@ -90,6 +90,12 @@ module Devise
# end
#
def find_for_authentication(conditions)
#the to_s is here to avoid mongodb injection where 'field => value' becomes 'field => {$ne => value}' thourgh the magic of rails
#still this does not prevent the leak if user1.token == '$ne' + user2.token (the chance of that is poor though)
#this might not be the best place or the best method, please change
conditions.each do |k, v|
conditions[k] = v.to_s
end
find(:first, :conditions => conditions)
end

View File

@@ -65,6 +65,31 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
end
end
test 'authenticate with valid authentication token key and do not store if stateless and timeoutable are enabled' do
swap Devise, :token_authentication_key => :secret_token, :stateless_token => true, :timeout_in => (0.1).second do
user = sign_in_as_new_user_with_token
assert warden.authenticated?(:user)
# Expiring does not work because we are setting the session value when accessing it
sleep 0.3
get_users_path_as_existing_user(user)
assert warden.authenticated?(:user)
end
end
test 'should not be subject to injection' do
swap Devise, :token_authentication_key => :secret_token do
user1 = create_user_with_authentication_token()
user2 = create_another_user_with_authentication_token(:auth_token => "ANOTHERTOKEN")
visit users_path(Devise.token_authentication_key.to_s + '[$ne]' => user1.authentication_token)
assert warden.user(:user) == nil
end
end
private
def sign_in_as_new_user_with_token(options = {})
@@ -85,4 +110,33 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
user
end
def create_user_with_authentication_token(options = {})
user = create_user(options)
user.authentication_token = options[:auth_token] || VALID_AUTHENTICATION_TOKEN
user.save
user
end
def create_another_user_with_authentication_token(options = {})
@anotheruser ||= begin
user = User.create!(
:username => 'anotherusertest',
:email => options[:email] || 'anotheruser@test.com',
:password => options[:password] || '123456',
:password_confirmation => options[:password] || '123456',
:created_at => Time.now.utc
)
user.confirm! unless options[:confirm] == false
user.lock_access! if options[:locked] == true
user.authentication_token = options[:auth_token] || VALID_AUTHENTICATION_TOKEN
user.save
user
end
end
def get_users_path_as_existing_user(user)
sign_in_as_new_user_with_token(:user => user)
end
end

View File

@@ -34,4 +34,26 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase
assert_nil authenticated_user
end
end
test 'should not be subject to injection' do
if DEVISE_ORM != :mongoid
assert_nil(nil)
else
user1 = create_user
user1.ensure_authentication_token!
user1.confirm!
user2 = create_user
user2.ensure_authentication_token!
user2.confirm!
#now trick it
user = User.find_for_token_authentication(:auth_token => {'$ne' => user1.authentication_token})
assert_nil user
end
end
end