이 문서를 통해 아래 질문들에 답할 수 있게 됩니다.
- Abuse detection은 취약점 탐지와 무엇이 다른가?
- 단일 요청이 정상이어도 어떤 반복, 순서, 비율, 분산 패턴을 봐야 하는가?
- 탐지 규칙을 차단, 추가 인증, 알림, shadow mode로 어떻게 연결해야 하는가?
개요
Abuse는 정상 기능을 비정상적인 방식으로 사용하는 행위다. SQL Injection처럼 payload가 명확한 공격도 있지만, 쿠폰 대입, OTP 발송 남용, credential stuffing, 검색 scraping, 고비용 export 반복처럼 요청 하나만 보면 정상일 수 있다.
따라서 abuse detection은 단일 요청의 유효성보다 시간 창 안의 패턴을 본다. 실패 후 성공, 여러 계정에 대한 같은 IP, 여러 IP에서 한 계정, 같은 리소스에 대한 빠른 반복, 정상 사용자와 다른 순서가 신호가 된다.
차단은 항상 오탐 비용을 만든다. 그래서 어떤 규칙은 shadow mode로 먼저 관찰하고, 어떤 규칙은 429, step-up 인증, temporary hold, 운영 알림으로 연결해야 한다.
이 문서의 핵심은 “이상한 요청을 찾는다”가 아니라 “정상 기능의 남용 패턴과 대응 action을 함께 설계한다”는 것이다.
공격 시나리오
- 공격자는 로그인 API에 낮은 빈도로 비밀번호 후보를 분산 입력한다.
- OTP 발송 API를 여러 IP에서 같은 전화번호로 호출해 비용과 사용자 피해를 만든다.
- 쿠폰 코드나 추천 코드를 수만 개 대입하되 각 IP당 속도는 낮게 유지한다.
- 검색 API를 page와 keyword를 바꿔가며 scraping한다.
- 비밀번호 재설정 flow를 이용해 계정 존재 여부를 추론한다.
- 관리자 검색, report export, AI API처럼 비용이 큰 기능을 반복 호출한다.
취약한 요청/응답 예시
level=INFO event=request_completed path=/api/coupons/validate status=200 user=anonymous
level=INFO event=request_completed path=/api/coupons/validate status=404 user=anonymousHTTP/1.1 200 OK
Content-Type: application/json
{"valid":false}단일 요청 로그만으로는 같은 IP 대역, device, user agent, 실패율, code prefix, 시간 창을 볼 수 없다. 탐지가 되지 않으면 공격자는 정상 API 호출만으로 brute force를 지속한다.
주제별 핵심 판단
- abuse rule은 endpoint별 업무 위험에서 시작한다.
- key는 IP, 계정, device, subject, endpoint, resource, cost를 조합한다.
- 단일 threshold보다 실패율, 순서, velocity, entropy, 분산 정도가 중요할 수 있다.
- 대응 action은 allow, observe, step-up, throttle, block, hold, alert로 나눠야 한다.
- shadow mode는 오탐과 정상 패턴을 학습하는 기간이다.
- 탐지 규칙에는 owner, review 주기, 해제 조건이 있어야 한다.
- 탐지 로그는 개인정보를 최소화하면서 correlation이 가능해야 한다.
개선된 요청/응답 예시
level=WARN event=abuse_rule_matched result=throttled rule=coupon_bruteforce_v3 actor=anonymous endpoint=POST /api/coupons/validate ipBucket=203.0.113.0/24 deviceHash=92af attempts=180 failures=176 window=10m action=429 traceId=0ff12a90HTTP/1.1 429 Too Many Requests
Retry-After: 120
Content-Type: application/json
{"code":"TOO_MANY_REQUESTS","message":"잠시 후 다시 시도해 주세요.","traceId":"0ff12a90"}사용자에게는 짧은 안내를 주고, 로그에는 어떤 규칙이 어떤 key와 window에서 매칭되었는지 남긴다.
방어 설계
- 기능별 abuse story를 작성한다.
- login, OTP, reset, coupon, search, export, payment, admin search는 서로 다른 rule을 둔다.
- 이벤트 stream은 성공과 실패를 모두 포함해야 한다.
- rule은 key, window, threshold, confidence, action으로 표현한다.
- 오탐 비용이 큰 rule은 shadow mode에서 metric만 수집한다.
- 차단 rule에는 사용자 회복 경로와 support override 절차를 둔다.
- 위험 score는 단일 이벤트보다 최근 행동 context를 반영한다.
- 탐지 결과는 rate limit, step-up 인증, fraud review, incident response로 연결한다.
Spring/HTTP 예시
public AbuseDecision evaluateCouponAttempt(CouponAttempt attempt) {
AbuseWindow window = abuseStore.window(
"coupon.validate",
attempt.ipBucket(),
attempt.deviceHash(),
Duration.ofMinutes(10)
);
if (window.failures() > 150 && window.failureRate() > 0.9) {
return AbuseDecision.throttle("coupon_bruteforce_v3", Duration.ofMinutes(2));
}
return AbuseDecision.allow();
}if (decision.throttled()) {
audit.recordAbuseRuleMatched(decision, attempt);
return ResponseEntity.status(429)
.header(HttpHeaders.RETRY_AFTER, String.valueOf(decision.retryAfter().toSeconds()))
.body(ApiError.tooManyRequests(traceId));
}business context가 필요한 rule은 application service에서 평가한다. edge rate limit는 보조 방어로 두고, 업무 의미를 가진 이벤트를 별도로 남긴다.
운영 로그와 감사 지점
level=INFO event=abuse_rule_shadow_matched result=observed rule=reset_enumeration_v1 actor=anonymous subjects=42 ipBuckets=6 window=15m action=none traceId=0ff12a90level=WARN event=credential_stuffing_detected result=blocked usernames=320 ipBuckets=44 successAfterFailures=7 window=30m action=force_password_reset traceId=0ff12a90- rule id와 version을 남겨 배포 전후 탐지 품질을 비교한다.
- action이 없는 shadow event도 metric으로 본다.
- false positive review 결과를 rule tuning에 반영한다.
- 차단 이벤트와 사용자 문의를 연결해 정상 사용자 피해를 측정한다.
- 탐지 store 장애 시 fail-open/fail-closed 정책을 endpoint별로 정한다.
실전 판단 기준
- 단일 IP threshold만 있으면 분산 공격에 약하다.
- 실패 로그만 있고 성공 로그가 없으면 실패 후 성공 패턴을 볼 수 없다.
- 모든 rule을 즉시 block하면 오탐으로 서비스 신뢰가 깨질 수 있다.
- 모든 rule을 observe만 하면 공격을 멈추지 못한다.
- business abuse는 WAF만으로 보기 어렵다.
- 탐지 이벤트에 rule version이 없으면 개선 효과를 측정하기 어렵다.
테스트 포인트
- 여러 IP에서 한 계정으로 로그인 실패가 반복될 때 탐지되는지 확인한다.
- 한 IP에서 여러 계정으로 실패가 반복될 때 credential stuffing으로 분류되는지 확인한다.
- 쿠폰 대입 실패율이 높은 window에서 429가 반환되는지 확인한다.
- shadow rule이 차단 없이 metric만 남기는지 확인한다.
- 탐지 store 장애 시 endpoint별 정책대로 동작하는지 확인한다.
- rule tuning 후 false positive와 false negative를 기록하는지 확인한다.
위험 신호!
- abuse detection이 “rate limit 있음” 한 줄로 끝난다.
- 성공 이벤트가 없어서 실패 후 성공을 볼 수 없다.
- rule id와 version이 없다.
- shadow mode 없이 바로 모든 요청을 차단한다.
- 탐지 결과가 어떤 대응 action에도 연결되지 않는다.
- 고객지원이 차단 해제 이유를 기록하지 않는다.
확인 질문
확인 질문
- Abuse detection이 취약점 탐지와 다른 점은 무엇인가?
- 요청 하나가 정상이어도 반복, 순서, 비율, 분산 패턴이 비정상일 수 있다는 점이다.
- 탐지 rule의 기본 구성은 무엇인가?
- key, window, threshold 또는 score, confidence, action, owner, version이다.
- shadow mode가 필요한 이유는 무엇인가?
- 실제 차단 전에 정상 사용자 영향과 오탐을 측정하기 위해서다.