2.3 비밀번호 관리

개요

비밀번호는 가장 널리 사용되는 인증 수단이지만, 동시에 많은 공격의 주요 대상이 됩니다. 취약한 비밀번호 정책, 안전하지 않은 저장 방식, 평문 전송 등은 계정 탈취로 이어지는 심각한 보안 문제를 야기합니다.

따라서 소프트웨어는 사용자가 안전한 비밀번호를 설정하도록 유도하고, 설정된 비밀번호를 안전하게 저장 및 관리하며, 전송 과정에서의 노출을 방지해야 합니다. 또한, 주기적인 변경을 권고하고 과거 비밀번호 재사용을 제한하는 등 지속적인 관리 방안을 마련해야 합니다.

이 기준은 비밀번호 생성, 저장, 변경, 검증 등 비밀번호 관리 전 과정에 걸쳐 적용되어야 할 필수적인 보안 요구사항을 정의합니다.

보안 대책

  • - 비밀번호 정책 강제:
    • 길이 제한: 최소 길이(예: 8자 이상, 권장 10자 이상)를 설정합니다.
    • 복잡도 요구: 영문 대/소문자, 숫자, 특수문자 중 일정 개수 이상(예: 3종류 이상)을 조합하도록 강제합니다.
    • 단순/예측 가능한 비밀번호 금지: 사용자 ID와 동일하거나 유사한 비밀번호, 연속된 문자/숫자(abc, 123), 키보드 패턴(qwerty), 사전에 등재된 단어 등의 사용을 금지합니다.
  • - 안전한 저장 (Hashing with Salt): 비밀번호는 절대로 평문으로 저장해서는 안 되며, 사용자별로 고유한 솔트(Salt)를 추가하여 안전하고 검증된 해시 함수(예: bcrypt, scrypt, Argon2, PBKDF2)를 사용하여 해시값을 저장해야 합니다. (MD5, SHA-1 등 취약한 해시 함수 사용 금지)
  • - 주기적인 변경 권고 및 강제: 사용자가 주기적으로(예: 90일마다) 비밀번호를 변경하도록 권고하거나 강제합니다.
  • - 비밀번호 재사용 금지: 이전에 사용했던 비밀번호(예: 최근 3~5개)를 다시 사용하지 못하도록 제한합니다. (이전 비밀번호 해시값 저장 필요)
  • - 초기/임시 비밀번호 관리: 초기 설정된 비밀번호나 임시 비밀번호는 사용자가 첫 로그인 시 반드시 변경하도록 강제합니다.
  • - 안전한 전송: 로그인, 비밀번호 변경 등 비밀번호가 전송되는 모든 구간은 반드시 암호화 통신(TLS/SSL)을 사용합니다.
  • - 비밀번호 복구/재설정 절차 보안: 비밀번호 찾기 또는 재설정 시 안전한 본인 확인 절차(예: 이메일 인증 링크, SMS 인증 코드)를 구현하고, 임시 비밀번호 발급 시 유효 시간을 제한합니다.

코드 예시 (C# - ASP.NET Core Identity 사용)

ASP.NET Core Identity는 안전한 비밀번호 해싱(PBKDF2 사용) 및 검증 기능을 내장하고 있습니다.

안전한 코드 (비밀번호 생성/해싱 - Identity 사용):

using Microsoft.AspNetCore.Identity;
// ...

// UserManager userManager; (DI 등으로 주입받음)
// ApplicationUser user; (사용자 객체)
// string password; (사용자가 입력한 새 비밀번호)

// PasswordHasher가 내부적으로 솔트를 생성하고 PBKDF2 HMAC SHA256 (기본값)으로 해싱
var passwordHasher = new PasswordHasher();
user.PasswordHash = passwordHasher.HashPassword(user, password); 

// 사용자 정보 업데이트 (DB 저장)
var result = await userManager.UpdateAsync(user);

if (result.Succeeded) {
    // 성공 처리
} else {
    // 오류 처리
}
                        
안전한 코드 (비밀번호 검증 - Identity 사용):

using Microsoft.AspNetCore.Identity;
// ...

// UserManager userManager;
// ApplicationUser user; (DB에서 조회한 사용자 객체, PasswordHash 포함)
// string providedPassword; (로그인 시 사용자가 입력한 비밀번호)

// CheckPasswordAsync 또는 PasswordHasher.VerifyHashedPassword 사용
var result = await userManager.CheckPasswordAsync(user, providedPassword);
// 또는
// var passwordHasher = new PasswordHasher();
// var verificationResult = passwordHasher.VerifyHashedPassword(user, user.PasswordHash, providedPassword);
// (verificationResult == PasswordVerificationResult.Success)

if (result) { // 또는 verificationResult == PasswordVerificationResult.Success
    // 로그인 성공
} else {
    // 비밀번호 불일치
}
                        

Java(Spring Security), Python(Passlib, Werkzeug), JavaScript(Node.js - bcrypt), PHP(password_hash) 등 대부분의 현대 웹 프레임워크와 라이브러리는 안전한 비밀번호 관리를 위한 기능을 제공하므로 이를 활용하는 것이 권장됩니다.