오라클 데이터베이스를 운영하다 보면 애플리케이션 서비스가 갑자기 중단되거나 배치 작업이 실패하면서 다음과 같은 에러를 마주치는 순간이 있습니다.
ORA-28000: the account is locked
ORA-28001: the password has expired
단순히 ALTER USER 계정명 IDENTIFIED BY 비밀번호; 명령어로 해결되는 단순한 상황도 있지만, 실무 환경에서는 그렇게 단순하지 않습니다.
운영 중인 계정의 기존 패스워드를 모르는 상태에서 잠김(Lock)만 해제해야 하거나, 애플리케이션 소스 코드 수정 없이 패스워드 만료 주기(Lifetime)를 우회하여 계정을 연장해야 하는 상황, 그리고 Oracle 11g/12c 이후 강화된 해시 알고리즘과 대소문자 구분 파라미터가 얽혀 발생하는 사이드 이펙트가 빈번하게 발생하기 때문입니다.
이번 포스팅에서는 오라클의 사용자 인증 및 프로파일(Profile) 내부 메커니즘, 계정 잠김/만료 트러블슈팅, 그리고 기존 비밀번호를 그대로 유지하면서 만료 상태를 초기화하는 실무 팁을 상세히 정리합니다.
1. 내부 아키텍처: 계정 상태와 인증 메커니즘
1) 오라클의 계정 상태 머신 (Account Status)
오라클 딕셔너리 뷰 DBA_USERS의 ACCOUNT_STATUS 컬럼은 계정의 현재 라이프사이클을 나타내며, 내부적으로 다음과 같은 우선순위와 전이 규칙을 가집니다.
- OPEN: 정상적으로 로그인이 가능한 상태.
- EXPIRED: 패스워드 유효기간(PASSWORD_LIFE_TIME)이 만료된 상태. 신규 세션 연결 시 ORA-28001을 반환하며 접속이 거부됩니다.
- LOCKED: 로그인 실패 횟수 초과(FAILED_LOGIN_ATTEMPTS) 또는 관리자의 수동 조치로 계정이 잠긴 상태. 접속 시 ORA-28000을 반환합니다.
- EXPIRED & LOCKED: 만료와 잠김이 동시에 발생한 복합 상태.
[정상 로그인]
┌─────────────────┐
│ OPEN │
└────────┬────────┘
│
┌─────────┴─────────┐
│ │
[유효기간 만료] [로그인 실패 N회 초과]
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ EXPIRED │ │ LOCKED │
│ (ORA-28001) │ │ (ORA-28000) │
└──────┬──────┘ └──────┬──────┘
│ │
└────────┬────────┘
▼
┌──────────────────┐
│ EXPIRED & LOCKED │
└──────────────────┘
2) Password Hash 저장 구조의 변화
오라클은 보안성 강화를 위해 버전에 따라 패스워드 검증자(Verifier) 체계를 단계적으로 확장해 왔습니다.
- Oracle 10g 이전: DES 기반의 16진수 대소문자 비구분 해시(DBA_USERS.PASSWORD).
- Oracle 11g: SHA-1 기반의 대소문자 구분 해시(11G Verifier, PASSWORD_VERSIONS 컬럼에 10G 11G 형태로 표시).
- Oracle 12c Release 1 (12.1): SHA-512 기반 해시 도입(12C Verifier).
- Oracle 12c Release 2 (12.2) 이상: PBKDF2 기반의 고강도 파생 키 알고리즘 적용.
SEC_CASE_SENSITIVE_LOGON 파라미터 주의점
Oracle 11g 이상에서는 기본적으로 SEC_CASE_SENSITIVE_LOGON = TRUE로 설정되어 패스워드 대소문자를 엄격하게 구분합니다. 레거시 시스템 마이그레이션 시 해당 설정 때문에 의도치 않은 로그인 실패가 발생하고 연쇄적으로 ORA-28000 계정 잠김이 발생할 수 있습니다.
2. 프로파일(Profile) 파라미터와 발생 원인 분석
계정이 잠기거나 만료되는 근본 원인은 해당 계정에 매핑된 RESOURCE PROFILE의 보안 파라미터 때문입니다. 별도로 지정하지 않는 한 모든 계정은 기본적으로 DEFAULT 프로파일을 따릅니다.
주요 패스워드 제어 파라미터
| 파라미터 | 기본값 (11g/12c 기준) | 설명 |
| FAILED_LOGIN_ATTEMPTS | 10회 | 연속 인증 실패 시 계정이 자동 잠김(Lock) 처리되는 한계치 |
| PASSWORD_LIFE_TIME | 180일 | 패스워드 만료까지의 유효 일수 (초과 시 ORA-28001) |
| PASSWORD_GRACE_TIME | 7일 | 만료 경고 후 비밀번호 변경을 유예해 주는 기간 |
| PASSWORD_REUSE_TIME | UNLIMITED | 이전 비밀번호를 다시 사용하기까지 대기해야 하는 일수 |
| PASSWORD_REUSE_MAX | UNLIMITED | 이전 비밀번호 재사용 전 거쳐야 하는 변경 횟수 |
- 개발/운영 미분리 환경의 연쇄 Lock: 배치 서버나 WAS의 DB Connection Pool 설정 중 특정 노드 하나에 잘못된 비밀번호가 설정되어 있으면 백그라운드 재접속 시도(Retry)로 인해 순식간에 FAILED_LOGIN_ATTEMPTS를 초과하여 계정이 잠기게 됩니다.
- 기본값 방치로 인한 돌발 만료: 데이터베이스 설치 후 DEFAULT 프로파일의 PASSWORD_LIFE_TIME(보통 180일)을 UNLIMITED로 전환하지 않아, 정확히 6개월 뒤 실서비스 계정이 정지되는 사고가 발생합니다.
3. 실무 트러블슈팅: 단계별 진단 및 복구
Step 1. 문제 계정의 상태 및 프로파일 점검
장애 발생 즉시 계정의 상태, 사용 중인 프로파일, 잠긴 일시를 조회합니다.
SELECT
username,
account_status,
profile,
lock_date,
expiry_date
FROM
dba_users
WHERE
username = UPPER('&input_username');
해당 계정에 적용된 프로파일의 상세 보안 정책도 함께 확인합니다.
SELECT
profile,
resource_name,
limit
FROM
dba_profiles
WHERE
resource_type = 'PASSWORD'
AND profile = (SELECT profile FROM dba_users WHERE username = UPPER('&input_username'))
ORDER BY
resource_name;
Step 2. 단순 계정 잠김 해제 (비밀번호를 알고 있는 경우)
관리자 권한(SYSDBA)으로 접속하여 계정 잠금을 해제하고, 필요 시 비밀번호를 재설정합니다.
-- 1) 단순 Lock 해제 (비밀번호는 그대로 유지)
ALTER USER app_user ACCOUNT UNLOCK;
-- 2) 만료(EXPIRED) 해제 및 신규 비밀번호 변경
ALTER USER app_user IDENTIFIED BY "NewPassword123#";
Step 3. [고급 실무] 기존 비밀번호를 유지하면서 만료 상태 해제하기
실무에서 가장 난감한 상황은 "WAS 애플리케이션 설정 파일에 암호화되어 있어 기존 비밀번호를 모르는데, 패스워드가 만료되어 접속이 안 되는 상황"입니다. 비밀번호를 바꾸면 운영 중인 수십 대의 WAS 인스턴스를 재기동해야 하는 대형 작업이 됩니다.
이때 오라클 내부의 Password Hash Verifier를 활용하여 비밀번호를 변경하지 않고 만료 상태만 OPEN으로 리셋할 수 있습니다.
① Oracle 11g R2 이전 (패스워드 해시 직접 대입)
-- 기존 10g 해시값 백업 조회
SELECT password FROM sys.user$ WHERE name = 'APP_USER';
-- 결과 예: 9A8B7C6D5E4F3210
-- 백업받은 해시값을 IDENTIFIED BY VALUES 절로 재지정 (만료 상태 초기화)
ALTER USER app_user IDENTIFIED BY VALUES '9A8B7C6D5E4F3210';
ALTER USER app_user ACCOUNT UNLOCK;
② Oracle 12c 이상 (동일 비밀번호 재할당 우회)
Oracle 12c 이상에서는 멀티플 해시 구조로 인해 VALUES 절 문법이 제한되는 경우가 많습니다. 만약 기존 비밀번호를 관리자나 개발팀이 알고 있다면, 단순히 기존 비밀번호를 한 번 더 덮어쓰는 것만으로 ACCOUNT_STATUS가 OPEN으로 돌아오며 만료 카운트다운이 리셋됩니다.
-- 기존 비밀번호와 동일한 값을 대입하여 만료 기한 연장
ALTER USER app_user IDENTIFIED BY "CurrentPassword123#";
ALTER USER app_user ACCOUNT UNLOCK;
Step 4. 무중단 비밀번호 전환 (Oracle 19c 이상: Gradual Database Password Rollover)
Oracle 19c(19.12 RU)부터는 애플리케이션 중단 없이 안전하게 비밀번호를 교체할 수 있는 혁신적인 기능이 제공됩니다. 바로 비밀번호 롤오버 유예 기간(Rollover Period) 설정입니다.
-- 이전 비밀번호와 신규 비밀번호가 7일간 동시에 인증되도록 설정
ALTER USER app_user IDENTIFIED BY "NewSecurePassword456#"
HTTP_DIGEST_ENABLE
RETAIN BATCH
PASSWORD ROLLOVER 7 DAYS;
이 기능을 활용하면 무중단 환경에서 DB 비밀번호를 먼저 변경한 뒤, 운영 시간 동안 순차적으로 WAS 인스턴스들의 설정 파일을 수정 및 재기동할 수 있습니다.
4. 재발 방지를 위한 운영 모범 권고안 (Best Practices)
- 서비스 계정 전용 프로파일 분리 생성
-- 서비스 계정 전용 무제한 프로파일 생성 CREATE PROFILE prf_app_service LIMIT FAILED_LOGIN_ATTEMPTS UNLIMITED PASSWORD_LIFE_TIME UNLIMITED PASSWORD_GRACE_TIME UNLIMITED PASSWORD_REUSE_TIME UNLIMITED PASSWORD_REUSE_MAX UNLIMITED; -- 운영 계정에 할당 ALTER USER app_user PROFILE prf_app_service; - 어플리케이션 연동용 계정에 DEFAULT 프로파일을 부여하는 것은 잠재적 장애 요인입니다. 서비스 계정 전용 프로파일을 별도로 생성하여 만료와 잠김 위험을 원천 차단해야 합니다.
- 반복적인 FAILED_LOGIN_ATTEMPTS 발생 시 유입 IP 추적
-- 로그인 실패 Audit 설정 (전통적 감사 기준) AUDIT SESSION WHENEVER NOT SUCCESSFUL; -- 실패 이력 및 접속 시도 터미널/IP 확인 SELECT username, os_username, userhost, timestamp, returncode FROM dba_audit_session WHERE returncode IN (1017, 28000) ORDER BY timestamp DESC; - 계정이 특정 주기로 자꾸 잠긴다면 내부 보안 사고이거나 잘못 설정된 배치가 도는 것입니다. 오라클 감사(Audit)나 시스템 트리거를 활용해 실패 로그를 수집해야 합니다.
5. 요약
계정 잠김(ORA-28000)과 만료(ORA-28001)는 발생 즉시 비즈니스 서비스 정지로 이어지는 크리티컬한 이슈입니다.
단순한 잠금 해제에 그치지 않고,
1) 원인이 된 유입 세션 추적,
2) 서비스 전용 프로파일 격리(PASSWORD_LIFE_TIME UNLIMITED), 그리고
3) 비밀번호를 모르는 긴급 상황에서의 해시 기반 복구 기법을 숙지해 두는 것이 안정적인 데이터베이스 운영의 핵심입니다.
