[주요정보통신기반시설 웹 애플리케이션 취약점 분석·평가 21일 완성 코스] 9강 — [Day 9] 약한 비밀번호 정책
[Day 9] 약한 비밀번호 정책 (Weak Password Policy)
안녕하세요! Hackerstory 공부방의 IT/보안 튜터 정다은입니다. 😊
지난 시간까지 우리는 서버와 클라이언트 간의 잘못된 요청 처리로 인해 발생하는 다양한 취약점들을 살펴보았습니다. 오늘 다룰 [Day 9] 약한 비밀번호 정책은 웹 애플리케이션 보안의 가장 기본적이면서도, 여전히 실무에서 자주 간과되는 매우 중요한 항목입니다.
비밀번호는 사용자 인증의 첫 번째 방어선입니다. 이 방어선이 허술하면 무차별 대입 공격이나 사전 공격에 의해 시스템 전체가 순식간에 뚫릴 수 있습니다. 오늘 강의를 통해 약한 비밀번호 정책이 왜 위험한지, 그리고 이를 방어하기 위해 어떤 복잡도 알고리즘을 적용해야 하는지 확실하게 알아봅시다!
1. 개념 이해하기 (Concept)
약한 비밀번호 정책이란?
웹 애플리케이션에서 회원가입 또는 비밀번호 변경 시, 비밀번호의 최소 길이, 문자 조합 규칙(영문 대/소문자, 숫자, 특수문자), 연속/반복 문자 제한 등의 검증 로직이 없거나 미흡한 상태를 의미합니다.
왜 위험할까요?
사용자들은 편의성을 위해 추측하기 쉬운 비밀번호(123456, password!, admin123 등)나 본인의 개인정보(전화번호, 생년월일)를 비밀번호로 설정하는 경향이 있습니다. 비밀번호 정책이 강제되지 않으면 다음과 같은 공격에 속수무책으로 노출됩니다.
- 무차별 대입 공격 (Brute Force Attack): 가능한 모든 문자 조합을 하나씩 입력하여 비밀번호를 맞춰내는 공격.
- 사전 공격 (Dictionary Attack): 자주 사용되는 비밀번호 목록(Wordlist)을 미리 만들어두고 이를 순차적으로 대입하는 공격.
- 크리덴셜 스터핑 (Credential Stuffing): 유출된 타 사이트의 계정 정보를 재사용하여 로그인을 시도하는 공격.
KISA 가이드라인 진단 기준
주요정보통신기반시설 기술적 취약점 분석·평가 가이드에 따른 판단 기준은 다음과 같습니다.
- 취약: 비밀번호 설정 시 영문, 숫자, 특수문자 중 2가지 이상 조합 10자리 이상 또는 3가지 이상 조합 8자리 이상으로 제한하지 않거나, 추측하기 쉬운 비밀번호(연속된 숫자/문자, ID와 동일한 비밀번호 등)가 설정 가능한 경우.
- 양호: 비밀번호 복잡도 규칙을 준수하고, 연속/반복 문자 및 ID 재사용 제한 알고리즘이 서버 측에 적절히 구현되어 있는 경우.
2. 취약점 동작 원리 및 예시 (Examples)
취약한 시나리오 1: 클라이언트 측(JavaScript) 검증만 존재하는 경우
개발자가 회원가입 페이지에서 프론트엔드 JavaScript로만 비밀번호 길이를 검증하는 경우가 많습니다.
// [취약한 코드 예시 - Client Side]
function validatePassword() {
var pw = document.getElementById("password").value;
// 단순히 길이만 6자리 이상인지 체크
if (pw.length < 6) {
alert("비밀번호는 6자리 이상이어야 합니다.");
return false;
}
return true;
}
공격 방법: 공격자는 Burp Suite와 같은 프록시 툴을 사용하여 웹 브라우저의 JavaScript 검증을 우회하고,
1234또는a같은 단순한 1자리 비밀번호를 백엔드 서버로 직접 전송(POST)하여 회원가입을 완료할 수 있습니다.
취약한 시나리오 2: 단순 정규식 미비로 인한 연속 문자 허용
단순히 문자 종류 조합 조건만 정규식으로 검증하고, 연속되거나 반복되는 문자를 제한하지 않는 경우입니다.
- 설정된 규칙: 영문 + 숫자 + 특수문자 조합 8자리 이상
- 통과된 취약한 비밀번호:
aaaaaa1!(동일 문자 반복),123456a!(연속된 숫자)
이러한 패턴은 사전 공격 및 자동화 툴을 통한 파싱 공격에 매우 취약합니다.
3. 진단 방법 및 실무 보안 대책 (Remediation)
🔍 진단 방법 (Checklist)
- 회원가입 및 비밀번호 변경 기능 탐색: 비밀번호를 입력받는 모든 폼을 확인합니다.
- 단순 비밀번호 입력 테스트:
123456,password,qwerty,admin!@#등을 입력하여 가입/변경이 허용되는지 확인합니다. - 연속/반복 문자 입력 테스트:
12345678!a,aaaaa1!a등을 테스트합니다. - ID와 유사한 비밀번호 테스트: 사용자 ID가
user01일 때 비밀번호를user01!@로 설정해봅니다. - 클라이언트 우회 테스트: Burp Suite를 이용해 클라이언트 검증을 스킵하고 서버로 파라미터를 직접 전송해 봅니다.
🛡️ 안전한 보안 대책 구현 코드
안전한 비밀번호 정책을 적용하려면 **반드시 서버 측(Server-side)**에서 검증을 수행해야 하며, 정규표현식과 연속성 체크 알고리즘을 결합해야 합니다.
[Python/Flask 기반의 안전한 비밀번호 검증 예시]
import re
def is_strong_password(password, user_id=""):
# 1. 최소 길이 및 문자 조합 검증 (3가지 조합 이상 8자리 이상 또는 2가지 조합 10자리 이상)
# 아래 예시는 8자리 이상 + 영문 대/소문자, 숫자, 특수문자 포함 규칙
pattern = r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,20}$'
if not re.match(pattern, password):
return False, "비밀번호는 8~20자의 영문 대/소문자, 숫자, 특수문자 조합이어야 합니다."
# 2. 아이디 포함 여부 검증
if user_id and user_id.lower() in password.lower():
return False, "비밀번호에 아이디를 포함할 수 없습니다."
# 3. 동일 문자 3회 이상 반복 제한 (예: aaa, 111, !!!)
if re.search(r'(.)\1\1', password):
return False, "동일한 문자를 3회 이상 연속해서 사용할 수 없습니다."
# 4. 연속된 문자/숫자 3회 이상 제한 (예: 123, abc, cba, 321)
for i in range(len(password) - 2):
o1, o2, o3 = ord(password[i]), ord(password[i+1]), ord(password[i+2])
# 오름차순 연속 (1-2-3, a-b-c) 또는 내림차순 연속 (3-2-1, c-b-a)
if (o2 == o1 + 1 and o3 == o2 + 1) or (o2 == o1 - 1 and o3 == o2 - 1):
return False, "연속된 문자/숫자를 3자리 이상 사용할 수 없습니다."
return True, "안전한 비밀번호입니다."
# 테스트
status, message = is_strong_password("P@ssword123", user_id="user01")
print(message) # 연속된 숫자(123)로 인해 거부됨!
📋 실무 패스워드 정책 수립가이드 요약
- 길이 및 조합 규칙:
- 최소 8자 이상 (영문 대/소문자 + 숫자 + 특수문자 3가지 이상 조합)
- 또는 최소 10자 이상 (2가지 이상 조합)
- 연속/반복 문자 금지:
- 동일 문자 3회 이상 반복 금지 (
aaa,111) - 키보드 배열 및 순차 문자 3회 이상 연속 금지 (
123,abc,qwe)
- 동일 문자 3회 이상 반복 금지 (
- 개인정보 활용 금지:
- 사용자 ID, 이름, 생년월일, 전화번호 포함 금지
- 검증 위치:
- 사용자 편의성을 위해 클라이언트(JS)에서도 1차 체크를 진행하되, 최종 인증 및 저장은 반드시 서버 측 로직에서 검증해야 함.
4. 오늘 강의 핵심 정리 (Summary)
- 약한 비밀번호 정책은 무차별 대입(Brute Force) 및 사전 공격(Dictionary Attack)의 표적이 됩니다.
- 단순히 길이나 정규식만 검증하는 것은 부족하며, 동일 문자 반복 및 연속 문자 알고리즘을 반드시 적용해야 합니다.
- 모든 보안 검증 로직의 주체는 **클라이언트가 아닌 서버(Server-Side)**여야 합니다.
다음 챕터에서는 약한 비밀번호 통과 후 발생하는 계정 도용 문제와 밀접하게 연관된 **[Day 10] 불충분한 인증 절차 (Insufficient Authentication)**에 대해 공부해보겠습니다. 인증 단계를 정상적으로 거치지 않고 주요 기능에 접근하는 취약점을 파헤쳐 볼 예정이니 기대해 주세요!
오늘도 고생 많으셨습니다. 궁금한 점은 언제든 댓글로 남겨주세요! 💻✨
댓글 0
로그인하면 댓글을 작성할 수 있습니다.