재생 공격
재생 공격 (Replay Attack)
1. 개요
재생 공격(Replay Attack)이란 공격자가 네트워크상에서 정당한 사용자가 전송한 유효한 데이터 패킷을 가로채어(Capture), 이를 그대로 다시 전송(Replay)함으로써 수신자로 하여금 정당한 사용자가 요청한 것으로 오인하게 만들어 인증을 우회하거나 권한을 획득하는 공격 기법이다.
이 공격의 핵심은 데이터의 내용을 수정하는 것이 아니라, 유효한 데이터 자체를 복제하여 재사용한다는 점에 있다. 따라서 데이터가 암호화되어 있더라도, 서버가 해당 데이터의 '신선도(Freshness)'를 검증하지 않는다면 공격자는 암호 해독 없이도 인증에 성공할 수 있다.
2. 공격 원리 및 과정
2.1 공격 메커니즘
재생 공격은 일반적으로 다음과 같은 단계로 진행된다.
- 패킷 스니핑(Packet Sniffing): 공격자가 네트워크 경로 상에 위치하여 사용자와 서버 간의 통신 패킷을 몰래 훔쳐본다.
- 데이터 캡처: 인증 토큰, 세션 쿠키, 또는 암호화된 로그인 요청과 같은 유효한 인증 데이터를 저장한다.
- 재전송: 저장해둔 패킷을 서버에 다시 전송한다.
- 권한 획득: 서버는 전송된 패킷이 이전에 인증된 유효한 패킷과 동일하므로, 이를 정당한 요청으로 판단하여 접근을 허용한다.
2.2 공격 시나리오 다이어그램
sequenceDiagram
participant User as 정당한 사용자
participant Attacker as 공격자 (Sniffer)
participant Server as 인증 서버
User->>Attacker: [인증 요청 패킷 전송] (가로채기)
Attacker->>Server: [인증 요청 패킷 전달] (정상 전달)
Server-->>User: [인증 성공 응답]
Note over Attacker: 캡처한 패킷을 보관함
Note over Attacker: 일정 시간 후 또는 세션 만료 전
Attacker->>Server: [캡처한 인증 요청 패킷 재전송]
Server-->>Attacker: [인증 성공 응답] (공격자 권한 획득)
2.3 정상 과정 vs 재생 공격 과정 비교
| 구분 | 정상적인 인증 과정 | 재생 공격 발생 과정 |
|---|---|---|
| 데이터 생성 | 사용자가 실시간으로 생성 및 전송 | 공격자가 과거에 캡처한 데이터를 전송 |
| 데이터 내용 | 최신 상태의 인증 정보 포함 | 과거의 유효했던 인증 정보 포함 |
| 서버 검증 | 데이터의 유효성 및 권한 확인 | 데이터의 유효성만 확인 (신선도 미검증) |
| 결과 | 정당한 사용자 접근 허용 | 공격자가 사용자 권한으로 위장 접근 |
3. 주요 공격 사례
3.1 HTTP 세션 하이재킹 (Session Hijacking)
웹 애플리케이션에서 사용자가 로그인 후 발급받은 세션 쿠키(Session Cookie)를 공격자가 가로채는 경우이다. 단순히 쿠키를 브라우저에 설정하는 '세션 도용'을 넘어, 탈취한 세션 쿠키가 포함된 HTTP 요청 패킷을 그대로 다시 전송하여 서버를 속이는 행위가 재생 공격의 관점에서의 핵심이다. 이를 통해 서버는 공격자의 요청을 로그인된 정당한 사용자의 요청으로 인식하게 된다.
3.2 원격 키리스 진입 시스템 (Remote Keyless Entry)
자동차의 스마트키 시스템에서 발생하는 사례이다. 사용자가 차 문을 열기 위해 누른 무선 신호를 공격자가 특수 장비로 캡처한 뒤, 사용자가 떠난 후 해당 신호를 다시 송신하여 차량의 잠금을 해제하는 방식이다.
3.3 금융 거래 및 API 요청
API 통신 시 인증 헤더를 고정적으로 사용하는 경우, 공격자가 특정 송금 요청 패킷을 캡처하여 반복적으로 전송함으로써 동일한 금액이 여러 번 송금되게 만드는 공격이 가능하다.
4. 방어 기법 및 대응 방안
재생 공격을 방어하기 위한 핵심은 "동일한 요청이 두 번 이상 처리되지 않도록" 보장하는 것이다.
4.1 주요 기술적 해결책
- 논스 (Nonce): 'Number used once'의 약자로, 요청마다 생성되는 일회성 무작위 값이다. 서버는 사용된 논스 목록을 저장하고, 이미 사용된 논스가 포함된 요청은 거부한다. 다만, 모든 논스를 영구 저장하면 저장소가 비대해지므로, 보통 타임스탬프와 결합하여 특정 시간 윈도우 내의 논스만 저장하고 오래된 논스는 삭제하는 방식으로 운영한다.
- 타임스탬프 (Timestamp): 요청 패킷에 생성 시간을 포함시킨다. 서버는 현재 시간과 패킷의 시간 차이가 허용 범위(예: 5초 이내)를 벗어나면 요청을 무효화한다.
- 시퀀스 번호 (Sequence Number): 패킷에 순차적인 번호를 부여한다. 서버는 마지막으로 받은 번호보다 큰 번호의 패킷만 수용한다.
4.2 방어 기법별 장단점 비교
| 기법 | 작동 원리 | 장점 | 단점 |
|---|---|---|---|
| Nonce | 일회성 무작위 값 검증 | 매우 강력한 보안성, 정확한 중복 제거 | 서버 측 저장 공간 필요 (타임스탬프 병행 권장) |
| Timestamp | 시간 윈도우 기반 검증 | 저장 공간 최소화, 구현이 비교적 간단 | 클라이언트-서버 간 시간 동기화 필수 |
| Sequence No. | 순차적 번호 증가 검증 | 패킷 순서 보장 및 누락 확인 가능 | 상태 유지(Stateful) 필요, 연결 끊김 시 재설정 필요 |
4.3 Nonce 활용 검증 로직 예시 (Python)
import secrets
import hmac
import hashlib
# 서버 측 저장소 (실제 환경에서는 Redis와 같은 분산 캐시 사용 권장)
# 메모리 저장 시 서버 재시작 시 초기화되므로 주의 필요
used_nonces = set()
SECRET_KEY = b'server_secret_key'
def validate_signature(data, nonce, signature):
"""
논스와 데이터가 결합된 형태의 디지털 서명을 검증한다.
논스 값만 전송할 경우 공격자가 논스만 바꿔서 보낼 수 있으므로,
반드시 데이터와 논스를 묶어 서명해야 한다.
"""
message = f"{data}_{nonce}".encode()
expected_signature = hmac.new(SECRET_KEY, message, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected_signature, signature)
def verify_request(request_data, nonce, signature):
# 1. 논스가 이미 사용되었는지 확인 (재생 공격 감지)
if nonce in used_nonces:
print("Error: Replay Attack Detected! Nonce already used.")
return False
# 2. 데이터와 논스의 무결성 및 인증 확인 (서명 검증)
if validate_signature(request_data, nonce, signature):
# 3. 검증 성공 시 사용된 논스를 저장소에 추가하여 재사용 방지
used_nonces.add(nonce)
print("Success: Request authenticated.")
return True
print("Error: Invalid Signature.")
return False
# --- 시나리오 테스트 ---
data = "transfer_1000_won"
nonce_val = secrets.token_hex(16)
# 클라이언트가 서명 생성 (실제로는 클라이언트가 비밀키를 가지거나 PKI 사용)
msg = f"{data}_{nonce_val}".encode()
sig_val = hmac.new(SECRET_KEY, msg, hashlib.sha256).hexdigest()
# 첫 번째 요청: 성공
verify_request(data, nonce_val, sig_val)
# 동일 패킷 재전송: 실패 (재생 공격 감지)
verify_request(data, nonce_val, sig_val)
# 논스만 변경하여 전송: 실패 (서명 불일치)
verify_request(data, secrets.token_hex(16), sig_val)
5. 유사 공격과의 비교
재생 공격은 다른 네트워크 공격과 혼동되기 쉬우나, 데이터의 조작 여부와 목적에서 차이가 있다.
| 구분 | 재생 공격 (Replay) | 중간자 공격 (MITM) | 세션 하이재킹 (Hijacking) |
|---|---|---|---|
| 핵심 특징 | 유효한 패킷의 단순 재전송 | 통신 경로 중간에서 데이터 가로채기 및 수정 | 인증된 세션 식별자(ID) 탈취 |
| 데이터 수정 | 수정하지 않음 (그대로 복제) | 실시간으로 수정 가능 | 수정 가능 또는 단순 도용 |
| 공격 시점 | 패킷 캡처 후 나중에 수행 가능 | 통신이 일어나는 실시간 상황 | 세션이 유지되고 있는 동안 |
| 상관관계 | MITM을 통한 패킷 획득 후 수행 | 재생 공격을 위한 전제 조건이 될 수 있음 | 탈취한 세션 ID의 재사용 |
6. 최신 프로토콜의 적용 사례
현대적인 보안 프로토콜들은 재생 공격을 기본적으로 방어하도록 설계되어 있다.
- TLS (Transport Layer Security): HTTPS의 기반이 되는 TLS 프로토콜은 핸드셰이크 과정에서 무작위 값(Random Number)을 교환하여 세션 키를 생성하며, 레코드 계층에서 시퀀스 번호를 사용하여 패킷의 순서를 관리함으로써 재생 공격을 원천 차단한다.
- OAuth 2.0 / OpenID Connect: 인증 코드(Authorization Code)나 액세스 토큰(Access Token)에 짧은 유효 기간(Expiration Time)을 설정하고,
state파라미터를 통해 CSRF 및 재생 공격을 방지한다. - Kerberos: 티켓 기반 인증 시스템으로, 티켓 내부에 타임스탬프를 포함시켜 특정 시간 범위 내에서만 유효하도록 제한함으로써 재생 공격을 방어한다.
이 문서는 AI 모델(gemma-4-31b)에 의해 생성된 콘텐츠입니다.
주의사항: AI가 생성한 내용은 부정확하거나 편향된 정보를 포함할 수 있습니다. 중요한 결정을 내리기 전에 반드시 신뢰할 수 있는 출처를 통해 정보를 확인하시기 바랍니다.