1. Password Storage
- Spring Security는 비밀번호를 안전하게 저장하기 위해 단방향 변환만 지원합니다.
- 입력 패스워드를 테이블에 저장된 해시 비밀번호와 비교하는데 유용합니다.
Password 보안 기술 발전과정
초기 보안 처리의 문제점
- 초기에는 데이터베이스의 접근제어 기능에 의존하여 보안을 처리하였으며, 패스워드를 평문으로 저장하였습니다.
- 그러나 악의적인 공격자들의 공격으로 인해 아이디 - 패스워드 정보가 탈취되는 위험을 내포하고 있었습니다.
- 입력값을 악용한 공격이 생겨났습니다. (SQL Injection)
단방향 해싱의 도입
- 데이터베이스에 패스워드를 단방향 해싱하여 저장하도록 권장받았습니다.
- 단방향 해싱 값은 노출되더라도 원본을 알아내는 것이 매우 어렵습니다.
- 비선형 연산, 혼돈 및 확산과 같은 성질을 근거로 해시 함수의 복구 안전성이 확보됩니다.
- 입력 패스워드 값을 해싱된 패스워드 저장값과 비교하면서 인증을 수행합니다.
사전공격과 Salt의 사용
- 단방향 해싱의 도입으로, 공격자들은 이를 극복하기 위해 레인보우 테이블을 사용하여 공격하기 시작합니다
- 레인보우 테이블은 다양한 원본값에 대응되는 단방향 해시값을 미리 계산해둔 테이블입니다.
- 이를 통해 해시값과 일치하는 원본 비밀번호를 빠르게 찾아낼 수 있습니다.
- 개발자들은 레인보우 테이블 공격을 대응하기 위해, 해싱값에 salt값을 추가하는 방법이 도입됩니다.
- salt값은 입력 패스워드를 사용하여 만든 랜덤 바이트값입니다.
- salt는 입력 패스워드와 함께 사용되어 유일한 단방향 해싱값을 만들어 사용합니다.
- 레인보우 테이블의 효과를 무력화 합니다.
Adaptive one-way functions의 도입
- 현대의 하드웨어 기술 발전으로 인해, 해시 기술은 보안성이 충분하지 않습니다.
- 1초에 몇백만 연산을 수행할 수 있어 salt별 레인보우 테이블을 마음먹으면 만들수 있습니다.
- 이에 따라 adaptive one-way functions 가 사용되도록 권장받았습니다.
- 해싱 과정에서 보안 강도를 조정할 수 있는 기능을 제공하는 암호화 함수입니다.
- work-factor
- 해싱 과정에서 필요한 작업의 양을 나타내는 매개변수입니다.
- 값을 조정하여 보안을 강화하는 기능을 가지고 있습니다.
- work-factor가 높아질수록 해싱에 필요한 하드웨어 계산 양이 크게 늘어납니다.
- 그러나 work-factor가 높아질수록 해시값을 생성하는 비용도 높아지므로 trade-off 고려가 필요합니다.
- Spring Security 는 work-factor 커스터마이징 기능을 제공하며 여러 adaptive one-way functions를 제공합니다.
단기 자격증명 권장
- 지금까지 입력받은 아이디-패스워드을 기반으로 인증하는 장기 자격 증명은 단점이 있습니다.
- 보안 매커니즘에 따른 성능 저하
- 민감정보 노출에 대한 보안 리스크
- 최근에는 유저들에게 장기 자격 증명이 아닌, 단기 자격 증명을 요청하도록 권장합니다.
- 단기 자격 증명은 로그인 성공 후에 시스템에서 발급되는 인증 토큰이나 세션 ID 정보를 의미합니다.
- 제한시간까지 유효하며, 그 기간이 지나면 만료됩니다.
- 빠르고 안전한 요청 인증 방법입니다.
2. DelegatingPasswordEncoder
- Spring Security 5.0 전에, 기본 PasswordEncoder는 NoOpPasswordEncoder 입니다
- NoOpPasswordEncoder는 평문을 그대로 데이터베이스에 저장하므로 보안에 취약합니다.
- 그러나 해싱된 패스워드를 저장할 경우 현실적인 문제를 만나게 됩니다.
- 많은 애플리케이션이 이미 NoOpPasswordEncoder를 쓰고 있고, 마이그레이션도 쉽지 않은 환경에 놓여있습니다.
- 비밀번호 저장에 대한 최선의 방법은 다시 변합니다.
- 그럴 때마다 Spring Security가 기본 PasswordEncoder를 업데이트하는 것은 어렵습니다.
- 이러한 점을 해결하기 위해 Spring Security는 DelegatingPasswordEncoder를 도입하였습니다.
- 현재 보안 권장사항에 따라 비밀번호를 안전하게 저장하도록 합니다.
- 현재 보안 권장사항 뿐만 아니라 이전에 사용한 권장사항으로도 비밀번호를 검증할 수 있도록 둘다 지원합니다.
- 미래에 보안 권장 사항이 변경될 때 쉽게 인코딩 방식을 업데이트하도록 지원합니다.
Password Storage Format
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
{noop}password
{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc
{scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=
{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0
- {id}encodedPassword
- id : 원본 패스워드를 해싱한 PasswordEncoder
- encodedPassword : PasswordEncoder가 해싱한 값
Password Encoding
- password storage format의 {id} 값은 DelegatingPasswordEncoder 생성자의 idForEncode 값으로 전달됩니다
- idForEncode 값을 통해 PasswordEncoder의 구현체가 결정됩니다.
- PasswordEncoder의 구현체는 passwordEncoderForEncode 필드로 담겨지며 encoding 작업을 위임받게 됩니다.
Password Matching
- DelegatingPasswordEncoder에서 match() 호출을 통해 입력된 패스워드와 해싱 패스워드의 일치를 검사합니다.
- DelegatingPasswordEncoder가 해싱 패스워드의 {id} 값에 알맞는 위임할 PasswordEncoder 구현체를 찾습니다.
- 위임할 PasswordEncoder가 없거나, 매핑되어 있지 않다면 IllegalArgumentException를 던집니다.
- 위임할 PasswordEncoder가 일치여부를 검사하여 인증을 시도합니다.
3. BCryptPasswordEncoder
- bcrypt 알고리즘은 패스워드 해싱에 보편적으로 사용되는 알고리즘입니다.
- bcrypt 알고리즘은 패스워드 보안의 저항성을 늘리기 위해 의도적으로 많은 연산을 수행합니다.
- 기본적으로 강도 10으로 셋팅되어 있습니다.
- bcrypt 알고리즘의 연산 강도를 trade-off를 고려하여 1정도로 맞추는 것이 일반적입니다.
4. Change Password Configuration
- 패스워드 재설정을 위한 Well-Known URL을 제공함으로써 클라이언트는 패스워드 재설정 URL을 쉽게 알 수 있습니다.
- 비밀번호 변경 페이지 확인 Well-Known URL은 /.well-known/change-password 입니다.
- Spring Security은 /.well-known/change-password 접근시, 패스워드 재설정 페이지로 리다이렉트 되도록 설정을 제공합니다.
http
.passwordManagement((management) -> management
.changePasswordPage("/update-password")
)
참고
'Spring > Spring Security' 카테고리의 다른 글
[JWT] 1. JWT Token (0) | 2023.10.03 |
---|---|
[Spring Security] 3-4. 인증: 로그아웃 (0) | 2023.10.03 |
[Spring Security] 3-2. 인증: 아이디 / 패스워드 (2) | 2023.10.02 |
[Spring Security] 5. 예외 처리 (0) | 2023.09.30 |
[Spring Security] 3. 인증: 아키텍쳐 (0) | 2021.07.28 |