취약하거나 위험한 암호 알고리즘 사용 (MD5 비밀번호 해시)
Use of a Broken or Risky Cryptographic Algorithm
설명
이 취약점은 비밀번호를 저장하거나 검증할 때 MD5 같은 오래되거나 취약한 해시 알고리즘을 사용하는 경우 발생합니다. MD5는 설계가 오래되었고, 매우 빠르며, 충돌 공격과 무차별 대입(brute-force), 레인보우 테이블 공격에 취약합니다. 공격자는 유출된 해시 값만 가지고도 짧은 시간 안에 원래 비밀번호를 복구하거나, 같은 해시를 만드는 다른 비밀번호를 찾아 계정을 탈취할 수 있습니다.
잠재적 영향
비밀번호 크래킹(비밀번호 탈취): 빠른 MD5 연산 속도를 이용하여 공격자가 대규모 무차별 대입 공격을 수행해 해시된 비밀번호를 실제 비밀번호로 복구할 수 있습니다.
계정 탈취 및 권한 오남용: 탈취된 비밀번호를 이용해 사용자 계정에 로그인하고, 개인 정보 조회, 결제, 관리자 기능 수행 등 계정을 악용할 수 있습니다.
재사용 비밀번호로 인한 2차 피해: 사용자가 다른 서비스에서도 같은 비밀번호를 사용하는 경우, 한 번 노출된 MD5 해시로 여러 시스템이 연쇄적으로 침해될 수 있습니다.
규정 위반 및 법적 리스크: 안전하지 않은 비밀번호 저장 방식은 개인정보보호법, 컴플라이언스(예: GDPR 유사 규제) 요구사항을 위반해 과징금·제재 대상이 될 수 있습니다.
해결 방법
비밀번호 전용 해시 함수 사용: bcrypt, scrypt, Argon2 같은 비밀번호 해시 알고리즘을 사용합니다. Go에서는
golang.org/x/crypto/bcrypt패키지 사용을 권장합니다.느린 해시(연산 비용) 설정: bcrypt의 cost 값을 충분히 크게 설정해 무차별 대입 공격을 어렵게 합니다(예: 10 이상, 성능 테스트 후 결정).
솔트(Salt) 자동 사용: bcrypt/Argon2는 내부적으로 솔트를 포함하므로, 별도의 수동 솔트 관리 대신 검증된 라이브러리를 그대로 사용합니다.
기존 MD5 해시 마이그레이션: 로그인 시 MD5 해시를 검증한 뒤, 성공하면 즉시 bcrypt 등 안전한 해시로 재해시하여 저장하는 점진적 마이그레이션을 적용합니다.
직접 구현 금지: 직접 해시·솔트·PBKDF 함수를 구현하지 말고, 검증된 라이브러리(bcrypt, Argon2 등)를 그대로 사용합니다.
취약한 코드 및 안전한 코드 예시
취약한 코드
안전한 코드
설명:
취약한 코드: 위 비준수 코드에서는 사용자 비밀번호를
crypto/md5로 해시해 그대로 저장합니다. MD5는 매우 빠르게 계산되기 때문에 공격자가 GPU/ASIC 등을 사용해 초당 엄청난 양의 후보 비밀번호를 시도할 수 있어, 해시만 유출돼도 비밀번호를 쉽게 크래킹할 수 있습니다. 또한 솔트(salt) 사용도 없기 때문에, 같은 비밀번호는 항상 같은 해시를 만들어 레인보우 테이블 공격에 특히 취약합니다.안전한 코드: 준수 코드에서는 MD5 대신 비밀번호 전용 해시 알고리즘인
bcrypt를 사용합니다.bcrypt.GenerateFromPassword는 내부적으로 무작위 솔트를 포함해 느린 연산을 수행하므로 무차별 대입 공격의 비용을 크게 높입니다.bcrypt.CompareHashAndPassword를 통해, 저장된 해시와 입력 비밀번호를 안전하게 비교할 수 있습니다. 직접 솔트·반복 횟수를 구현하지 않고 검증된 라이브러리를 그대로 사용함으로써 MD5 사용으로 인한 취약점을 제거합니다.
참조
Last updated