사용자의 비밀번호는 평문으로 저장되서는 안되며, 보안 알고리즘을 사용하여 해시값을 생성해야합니다.
- 무차별 공격에 취약해서는 안됩니다.
- collision attacks 에 취약해서는 안됩니다. (룰 S4790 을 참고하세요.)
- 레인보우 테이블 공격의 위험성을 줄이기 위해 솔트 값을 패스워드에 추가해야 합니다. (룰 S2053 을 참고하세요.)
이 룰은 암호가 평문으로 저장되거나 무차별 공격에 취약한 해싱 알고리즘을 사용했을 때 문제를 제기합니다.
md5나, SHA 종류의 함수들은 해시값을 빠르게 계산할 수 있기에, 특히 GPU, FPGA 혹은 ASIC 과 같은 하드웨어 장비를 통해 무차별 대입 공격이 가능합니다.(가능한 모든 암호에 대한 전체 해시 공간을 소진하기가 쉽습니다.)
bcrypt, PBKDF2 혹은 argon2 와 같은 최신 패스워드 해싱 알고리즘이 권장됩니다.
규칙을 어긴 코드
@Override
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("SELECT * FROM users WHERE username = ?")
.passwordEncoder(new StandardPasswordEncoder()); // 규칙을 어긴 코드
// OR
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("SELECT * FROM users WHERE username = ?"); // 규칙을 어긴 코드; 기본값으로 평문을 사용합니다.
// OR
auth.userDetailsService(...); // 규칙을 어긴 코드; 기본값으로 평문을 사용합니다.
// OR
auth.userDetailsService(...).passwordEncoder(new StandardPasswordEncoder()); // 규칙을 어긴 코드
}
규칙을 준수한 해결책
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth, DataSource dataSource) throws Exception {
auth.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery("Select * from users where username=?")
.passwordEncoder(new BCryptPasswordEncoder());
// or
auth.userDetailsService(null).passwordEncoder(new BCryptPasswordEncoder());
}
참고
- OWASP Top 10 2021 Category A2 - Cryptographic Failures
- OWASP Top 10 2021 Category A4 - Insecure Design
- OWASP CheatSheet - Password Storage Cheat Sheet
- OWASP Top 10 2017 Category A3 - Sensitive Data Exposure
- MITRE, CWE-256 - Plaintext Storage of a Password
- MITRE, CWE-916 - Use of Password Hash With Insufficient Computational Effort
- SANS Top 25 - Porous Defenses
If you like SONARKUBE, don’t forget to give me a star.