[주요정보통신기반시설 웹 애플리케이션 취약점 분석·평가 21일 완성 코스] 9강 — [Day 9] 약한 비밀번호 정책

⚡ 정다은 · 2026-09-29 14:00 · 조회 40

[Day 9] 약한 비밀번호 정책 (Weak Password Policy)

안녕하세요! Hackerstory 공부방의 IT/보안 튜터 정다은입니다. 😊

지난 시간까지 우리는 서버와 클라이언트 간의 잘못된 요청 처리로 인해 발생하는 다양한 취약점들을 살펴보았습니다. 오늘 다룰 [Day 9] 약한 비밀번호 정책은 웹 애플리케이션 보안의 가장 기본적이면서도, 여전히 실무에서 자주 간과되는 매우 중요한 항목입니다.

비밀번호는 사용자 인증의 첫 번째 방어선입니다. 이 방어선이 허술하면 무차별 대입 공격이나 사전 공격에 의해 시스템 전체가 순식간에 뚫릴 수 있습니다. 오늘 강의를 통해 약한 비밀번호 정책이 왜 위험한지, 그리고 이를 방어하기 위해 어떤 복잡도 알고리즘을 적용해야 하는지 확실하게 알아봅시다!


1. 개념 이해하기 (Concept)

약한 비밀번호 정책이란?

웹 애플리케이션에서 회원가입 또는 비밀번호 변경 시, 비밀번호의 최소 길이, 문자 조합 규칙(영문 대/소문자, 숫자, 특수문자), 연속/반복 문자 제한 등의 검증 로직이 없거나 미흡한 상태를 의미합니다.

왜 위험할까요?

사용자들은 편의성을 위해 추측하기 쉬운 비밀번호(123456, password!, admin123 등)나 본인의 개인정보(전화번호, 생년월일)를 비밀번호로 설정하는 경향이 있습니다. 비밀번호 정책이 강제되지 않으면 다음과 같은 공격에 속수무책으로 노출됩니다.

  1. 무차별 대입 공격 (Brute Force Attack): 가능한 모든 문자 조합을 하나씩 입력하여 비밀번호를 맞춰내는 공격.
  2. 사전 공격 (Dictionary Attack): 자주 사용되는 비밀번호 목록(Wordlist)을 미리 만들어두고 이를 순차적으로 대입하는 공격.
  3. 크리덴셜 스터핑 (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)

  1. 회원가입 및 비밀번호 변경 기능 탐색: 비밀번호를 입력받는 모든 폼을 확인합니다.
  2. 단순 비밀번호 입력 테스트: 123456, password, qwerty, admin!@# 등을 입력하여 가입/변경이 허용되는지 확인합니다.
  3. 연속/반복 문자 입력 테스트: 12345678!a, aaaaa1!a 등을 테스트합니다.
  4. ID와 유사한 비밀번호 테스트: 사용자 ID가 user01일 때 비밀번호를 user01!@로 설정해봅니다.
  5. 클라이언트 우회 테스트: 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)로 인해 거부됨!

📋 실무 패스워드 정책 수립가이드 요약

  1. 길이 및 조합 규칙:
    • 최소 8자 이상 (영문 대/소문자 + 숫자 + 특수문자 3가지 이상 조합)
    • 또는 최소 10자 이상 (2가지 이상 조합)
  2. 연속/반복 문자 금지:
    • 동일 문자 3회 이상 반복 금지 (aaa, 111)
    • 키보드 배열 및 순차 문자 3회 이상 연속 금지 (123, abc, qwe)
  3. 개인정보 활용 금지:
    • 사용자 ID, 이름, 생년월일, 전화번호 포함 금지
  4. 검증 위치:
    • 사용자 편의성을 위해 클라이언트(JS)에서도 1차 체크를 진행하되, 최종 인증 및 저장은 반드시 서버 측 로직에서 검증해야 함.

4. 오늘 강의 핵심 정리 (Summary)

  • 약한 비밀번호 정책은 무차별 대입(Brute Force) 및 사전 공격(Dictionary Attack)의 표적이 됩니다.
  • 단순히 길이나 정규식만 검증하는 것은 부족하며, 동일 문자 반복 및 연속 문자 알고리즘을 반드시 적용해야 합니다.
  • 모든 보안 검증 로직의 주체는 **클라이언트가 아닌 서버(Server-Side)**여야 합니다.

다음 챕터에서는 약한 비밀번호 통과 후 발생하는 계정 도용 문제와 밀접하게 연관된 **[Day 10] 불충분한 인증 절차 (Insufficient Authentication)**에 대해 공부해보겠습니다. 인증 단계를 정상적으로 거치지 않고 주요 기능에 접근하는 취약점을 파헤쳐 볼 예정이니 기대해 주세요!

오늘도 고생 많으셨습니다. 궁금한 점은 언제든 댓글로 남겨주세요! 💻✨

댓글 0

로그인하면 댓글을 작성할 수 있습니다.