Authentication security
-
Upload
- -
Category
Technology
-
view
443 -
download
0
description
Transcript of Authentication security
Безопасность аутентификациивеб-приложений
Сергей НартымовBrainspec
https://github.com/lesttwitter: @just_lest
Хэш с солью
Хэш с солью
create_table :users do |t| t.string :name t.string :salt t.string :hashed_passwordend
Хэш с солью
def self.encrypted_password(password, salt) string_to_hash = password + "wibble" + salt Digest::SHA1.hexdigest(string_to_hash)end
def create_new_salt self.salt = self.object_id.to_s + rand.to_send
Хэш с солью
def password=(pwd) @password = pwd return if pwd.blank? create_new_salt self.hashed_password = User.encrypted_password(self.password, self.salt)end
Хэш с солью
def self.authenticate(name, password) user = self.find_by_name(name) if user expected_password = encrypted_password(password, user.salt) if user.hashed_password != expected_password user = nil end end userend
has_secure_password
create_table :users do |t| t.string :name t.string :password_digestend
class User < ActiveRecord::Base has_secure_passwordend
user = User.new(name: "david")user.password = "mUc3m00RsqyRe"user.password_digest# => "$2a$10$4LEA7r4YmNHtvlAvHhsYAeZmk/xeUVtMTYqwIvYY76EW5GUqDiP4."
user.save
user.authenticate("notright") # => falseuser.authenticate("mUc3m00RsqyRe") # => user
bcrypt
bcrypt
$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
идентификатор алгоритма
bcrypt
$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
сложность
bcrypt
$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
соль
bcrypt
$2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
bcryptdef password=(unencrypted_password) unless unencrypted_password.blank? @password = unencrypted_password cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine::DEFAULT_COST self.password_digest = BCrypt::Password.create(unencrypted_password, cost: cost) endend
def authenticate(unencrypted_password) BCrypt::Password.new(password_digest) == unencrypted_password && selfend
bcryptdef password=(unencrypted_password) unless unencrypted_password.blank? @password = unencrypted_password cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine::DEFAULT_COST self.password_digest = BCrypt::Password.create(unencrypted_password, cost: cost) endend
def authenticate(unencrypted_password) BCrypt::Password.new(password_digest) == unencrypted_password && selfend
bcrypt
PBKDF2
scryptbcrypt
PBKDF2
scryptbcrypt
Перебор пользователей
• Неверный адрес e-mail или пароль.
• Если ваш адрес e-mail есть в нашей базе данных, то в течение нескольких минут вы получите письмо с инструкциями по восстановлению вашего пароля.
Тайминговые атаки
Тайминговые атаки
def authenticate! resource = valid_password? && mapping.to.find_for_database_authentication(authentication_hash) return fail(:not_found_in_database) unless resource
if validate(resource){ resource.valid_password?(password) } resource.after_database_authentication success!(resource) endend
Тайминговые атаки
user = User.last
Benchmark.realtime { user.valid_password?('lolwut') }# => 0.321346
Блокировка доступа
Блокировка доступа
• для пользователя• для IP-адреса
Блокировка доступа
• CAPTCHA
• разблокировка по ссылке из письма
Инвалидация сессии
Инвалидация сессии
user = User.authenticate(params[:name], params[:password])if user session[:user_id] = user.id redirect_to(:action => "index")else flash.now[:notice] = "Invalid user/password combination"end
Инвалидация сессии
• хранить в сессии данные, которые изменяются при изменении пароля
• например, соль пароля (так делает devise)
Инвалидация сессии
def serialize_into_session(record) [record.to_key, record.authenticatable_salt]end
def authenticatable_salt encrypted_password[0,29] if encrypted_passwordend
Запомнить меня
Запомнить меня
• добавляем токен и время
• храним токен в HttpOnly cookie
Запомнить меня
def remember_me!(extend_period=false) self.remember_token = self.class.remember_token if generate_remember_token? self.remember_created_at = Time.now.utc if generate_remember_timestamp?(extend_period) save(:validate => false) if self.changed?end
Запомнить меня
cookies.signed[remember_key(resource, scope)] = remember_cookie_values(resource)
def remember_cookie_values(resource) options = { :httponly => true } # ... options.merge!( :value => resource.class.serialize_into_cookie(resource), :expires => resource.remember_expires_at )end
Восстановление пароля
• не стоит генерировать пароль и присылать его на почту
• лучше генерировать токен и отправлять ссылку, по которой можно задать новый пароль
Сложность пароля
Сложность пароля
validates :password, length: { minimum: 5, maximum: 20 }
SSL
SSL
startssl.com
Двухэтапная аутентификация
Двухэтапная аутентификация
Двухэтапная аутентификация
Dropbox
Двухэтапная аутентификация
AWS
Dropbox
Двухэтапная аутентификация
AWS
Dropbox
GitHub
Двухэтапная аутентификация
Open Web ApplicationSecurity Project
• https://www.owasp.org/
• https://www.owasp.org/index.php/Cheat_Sheets
Спасибо
https://github.com/lesttwitter: @just_lest
Сергей НартымовBrainspec