Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Authentication Security – RUBYSPB
Search
Sergey Nartimov
September 21, 2013
Programming
200
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Authentication Security – RUBYSPB
Sergey Nartimov
September 21, 2013
More Decks by Sergey Nartimov
See All by Sergey Nartimov
PubSub at Rails
lest
0
140
Rails in production - RubyConfBY 22 Mar 2015
lest
1
160
Sequel - BRUG 21 Feb 2015
lest
0
100
Elixir – Belarus Ruby User Group 25 Jan 2014
lest
3
670
Geospatial applications on Rails
lest
8
440
Design patterns – Belarus Ruby on Rails User Group 23 Feb 2013
lest
8
670
Ruby Stdlib – Minsk.rb October 2012
lest
10
420
Background jobs with realtime results – RailsClub'Moscow 2012
lest
5
230
Other Decks in Programming
See All in Programming
How I Won Prize Money at a Hackathon Using Codex and Symphony Alpha
yasei_no_otoko
0
110
AWS DevOps AgentのAzure接続機能を検証して見えた活用法/Use Cases Verified for the AWS DevOps Agent's Azure Connectivity Feature
masakiokuda
1
240
生成AI導入の「期待外れ」を乗り越える ー 開発フロー改革が目指す、真の組織変革
starfish719
0
4.7k
Jindong: Introducing Declarative Haptics in Compose Multiplatform
l2hyunwoo
0
120
Foundation Models frameworkで画像分析
ryodeveloper
1
620
進化を続けるGo toolsの現在地 / The Current State of Ever-Evolving Go Tools
hond0413
0
240
関東Kaggler会_NVIDIA_Nemotron_コンペ_振り返り
rick_ds
0
650
言葉の格闘技のススメ~紙とペンと言葉から始める、キャリアの描き方~
progresscicada
2
160
Android CLI
fornewid
0
220
Terraform標準の組織で AWS CDKをどう使うか
mu7889yoon
1
530
メールのエイリアス機能を履き違えない
isshinfunada
0
240
ソフトウェア設計に溶けるインフラ ― AWS CDK のインフラ認識論
konokenj
3
800
Featured
See All Featured
How to make the Groovebox
asonas
2
2.3k
The agentic SEO stack - context over prompts
schlessera
0
860
Code Review Best Practice
trishagee
74
20k
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
870
Mobile First: as difficult as doing things right
swwweet
225
10k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Statistics for Hackers
jakevdp
799
230k
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
540
Large-scale JavaScript Application Architecture
addyosmani
515
110k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
1.2k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.3k
Transcript
Безопасность аутентификации веб-приложений Сергей Нартымов Brainspec https://github.com/lest twitter: @just_lest
None
Хэш с солью
None
Хэш с солью create_table :users do |t| t.string :name t.string
:salt t.string :hashed_password end
Хэш с солью 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_s end
Хэш с солью 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 user end
has_secure_password
create_table :users do |t| t.string :name t.string :password_digest end class
User < ActiveRecord::Base has_secure_password end
user = User.new(name: "david") user.password = "mUc3m00RsqyRe" user.password_digest # =>
"$2a$10$4LEA7r4YmNHtvlAvHhsYAeZmk/ xeUVtMTYqwIvYY76EW5GUqDiP4." user.save user.authenticate("notright") # => false user.authenticate("mUc3m00RsqyRe") # => user
bcrypt
bcrypt $2a$10$vI8aWBnW3fID.ZQ4/z идентификатор алгоритма
bcrypt $2a$10$vI8aWBnW3fID.ZQ4/zo1G сложность
bcrypt $2a$10$vI8aWBnW3fID.ZQ4/zo1G.q1lRps соль
bcrypt o1G.q1lRps.9cGLcZEiGDMVr5yUP1KUOYTa
bcrypt def 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) end end def authenticate(unencrypted_password) BCrypt::Password.new(password_digest) == unencrypted_password && self end
bcrypt def 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) end end def authenticate(unencrypted_password) BCrypt::Password.new(password_digest) == unencrypted_password && self end
bcrypt
PBKDF2 scrypt bcrypt
PBKDF2 scrypt bcrypt
Инвалидация сессии
Инвалидация сессии 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_password end
Блокировка доступа
Блокировка доступа • для пользователя • для IP-адреса
Блокировка доступа • CAPTCHA • разблокировка по ссылке из письма
Запомнить меня
Запомнить меня • добавляем токен и время • храним токен
в 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
Перебор пользователей
• Неверный адрес 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) end end
Тайминговые атаки user = User.last Benchmark.realtime { user.valid_password?('lolwut') } #
=> 0.321346
Восстановление пароля • не стоит генерировать пароль и присылать его
на почту • лучше генерировать токен и отправлять ссылку, по которой можно задать новый пароль
Сложность пароля
Сложность пароля validates :password, length: { minimum: 5, maximum: 20
}
SSL
SSL startssl.com
Двухэтапная аутентификация
Google Двухэтапная аутентификация
Google Facebook Двухэтапная аутентификация
Google Facebook Dropbox Двухэтапная аутентификация
Google Facebook AWS Dropbox Двухэтапная аутентификация
Google Facebook AWS Dropbox GitHub Двухэтапная аутентификация
Open Web Application Security Project • https://www.owasp.org/ • https://www.owasp.org/index.php/ Cheat_Sheets
Спасибо https://github.com/lest twitter: @just_lest Сергей Нартымов Brainspec