AWS WAF의 COUNT 모드와 BLOCK 모드에 대해 확인해 봤습니다.
안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번 블로그에서는 AWS WAF의 COUNT 모드와 BLOCK 모드에 대해 확인해 봤습니다.
AWS WAF에서는 COUNT 모드와 BLOCK 모드를 포함하여 다양한 모드가 있지만, 그 중에서 가장 많이 사용되는 COUNT 모드와 BLOCK 모드에 대해서 알아보고자 합니다.
COUNT 모드?
COUNT 모드는 요청을 차단하지 않고, 단순히 탐지만 수행하는 모드입니다.
즉, 설정한 룰에 매칭되는 요청이 들어오더라도 실제로 차단하지 않고, 해당 요청을 로그 및 메트릭으로 기록하는 역할을 합니다.
특징은 다음과 같습니다.
- 요청을 차단하지 않음 (Allow와 동일하게 처리)
- 룰 매칭 여부를 로그로 확인 가능
- AWS CloudWatch를 통해 모니터링 가능
- WAF 룰 적용 전 테스트 용도로 많이 사용됨
사용 목적은 다음과 같습니다.
- 신규 룰 적용 전 영향도 분석
- 오탐(False Positive) 여부 확인
- 실제 차단 없이 트래픽 패턴 파악
예를 들어, 특정 IP나 패턴을 차단하는 룰을 생성했을 때 바로 BLOCK 모드를 적용하면 정상 사용자까지 차단될 수 있습니다.
이러한 상황을 방지하기 위해 먼저 COUNT 모드로 설정하여 실제 어떤 요청이 매칭되는지 확인한 후, 문제가 없을 때 BLOCK 모드로 전환하는 방식이 일반적입니다.
BLOCK 모드?
BLOCK 모드는 요청을 실제로 차단하는 모드입니다.
설정한 룰에 매칭되는 요청이 발생하면, 해당 요청은 애플리케이션까지 전달되지 않고 WAF 단계에서 즉시 차단됩니다. 일반적으로 차단된 요청은 403 Forbidden 응답을 반환하게 됩니다.
특징은 다음과 같습니다.
- 룰에 매칭된 요청을 즉시 차단
- 애플리케이션 레벨까지 요청이 도달하지 않음
- 보안 위협을 실시간으로 방어 가능
- 잘못 설정할 경우 정상 요청도 차단될 수 있음 (오탐 가능성)
사용 목적은 다음과 같습니다.
- 명확한 공격 패턴 차단 (SQL Injection, XSS 등)
- 특정 IP 또는 국가 차단
- 비정상 트래픽 필터링
- 보안 정책 강제 적용
BLOCK 모드는 실제 트래픽을 제어하는 강력한 기능이기 때문에, 운영 환경에 적용할 때는 신중한 접근이 필요합니다.
일반적으로는 COUNT 모드로 충분히 검증을 진행한 후, 오탐이 없다고 판단되는 경우에 BLOCK 모드로 전환하는 방식이 권장됩니다.
검증
COUNT 모드와 BLOCK 모드를 한 번 테스트해 봅시다.
준비한 환경은 간단합니다.
- Linux계 EC2에 Apache를 설치
- ALB와 ACM을 이용하여 HTTPS로 접속
WAF 룰은 다음과 같습니다.
- AWSManagedRulesCommonRuleSet
- AWSManagedRulesAmazonIpReputationList
- AWSManagedRulesSQLiRuleSet
- AWSManagedRulesKnownBadInputsRuleSet
- AWSManagedRulesLinuxRuleSet
COUNT 모드
먼저 WAF 룰이 COUNT 모드로 설정되어 있는지 확인합니다.
# WebACL ID 확인
WEBACL_ID=$(aws wafv2 list-web-acls \
--scope REGIONAL \
--region ap-northeast-1 \
--query "WebACLs[?Name=='sip3fm-dev-alb-webacl'].Id" \
--output text)
echo $WEBACL_ID
# 현재 모드 확인
aws wafv2 get-web-acl \
--name sip3fm-dev-alb-webacl \
--scope REGIONAL \
--id $WEBACL_ID \
--region ap-northeast-1 | \
jq '.WebACL.Rules[] | {Name: .Name, OverrideAction: .OverrideAction}'
결과 :
{
"Name": "AWSManagedRulesCommonRuleSet",
"OverrideAction": {
"Count": {}
}
}
{
"Name": "AWSManagedRulesAmazonIpReputationList",
"OverrideAction": {
"Count": {}
}
}
{
"Name": "AWSManagedRulesSQLiRuleSet",
"OverrideAction": {
"Count": {}
}
}
{
"Name": "AWSManagedRulesKnownBadInputsRuleSet",
"OverrideAction": {
"Count": {}
}
}
{
"Name": "AWSManagedRulesLinuxRuleSet",
"OverrideAction": {
"Count": {}
}
}
다음은 COUNT 모드 상태에서 요청을 전송해 봅시다.
먼저 정상 요청입니다.
curl -s -o /dev/null -w "%{http_code}" \
https://도메인.info
결과 :
200
다음은 SQL 인젝션입니다.
curl -s -o /dev/null -w "%{http_code}" \
"https://도메인.info/?id=1%27%20OR%20%271%27%3D%271"
결과 :
200
다음은 XSS 요청입니다.
curl -s -o /dev/null -w "%{http_code}" \
"https://도메인.info/?search=<script>alert(1)</script>"
결과 :
200
마지막으로 악의적인 경로 요청입니다.
curl -s -o /dev/null -w "%{http_code}" \
"https://도메인.info/?file=../../../../etc/passwd"
결과 :
200
결과적으로 전부 200 응답을 반환하고 있는 것을 확인할 수 있습니다.
로그를 확인해 보면 다음과 같습니다.
"action": "ALLOW" ← 최종 액션은 ALLOW (통과)
"terminatingRuleId": "Default_Action" ← 기본 액션으로 처리
탐지된 롤에 대한 상세한 정보는 다음과 같습니다.
"ruleGroupId": "AWS#AWSManagedRulesCommonRuleSet"
"ruleId": "CrossSiteScripting_QUERYARGUMENTS"
"action": "COUNT" ← COUNT 모드로 카운트만 기록
"overriddenAction": "BLOCK" ← 원래는 BLOCK 해야 하는 요청
"conditionType": "XSS" ← XSS 공격으로 탐지
"matchedData": ["<", "script"] ← 탐지된 패턴
"matchedFieldName": "search" ← search 파라미터에서 탐지
즉, XSS 공격 요청을 수신하고 AWSManagedRulesCommonRuleSet가 탐지합니다. 원래는 BLOCK 해야 하지만 (overriddenAction: BLOCK) COUNT 모드이므로 카운트만 기록 (action: COUNT)하여 Default_Action (ALLOW) 으로 요청을 통과시켜 200 응답이 반환되는 것입니다.
| 항목 | 내용 |
|---|---|
| 탐지 룰 | AWSManagedRulesCommonRuleSet |
| 탐지 패턴 | XSS (CrossSiteScripting_QUERYARGUMENTS) |
| COUNT 모드 동작 | 카운트만 기록 후 통과 |
| 최종 액션 | ALLOW (통과) |
| 원래 액션 | BLOCK (COUNT 모드로 오버라이드) |
BLOCK 모드
이번에는 BLOCK 모드를 확인해 봅시다.
먼저 정상 요청입니다.
curl -s -o /dev/null -w "%{http_code}" \
https://도메인.info
결과 :
200
다음은 SQL 인젝션입니다.
curl -s -o /dev/null -w "%{http_code}" \
"https://도메인.info/?id=1%27%20OR%20%271%27%3D%271"
결과 :
403
다음은 XSS 요청입니다.
curl -s -o /dev/null -w "%{http_code}" \
"https://도메인.info/?search=<script>alert(1)</script>"
결과 :
403
마지막으로 악의적인 경로 요청입니다.
curl -s -o /dev/null -w "%{http_code}" \
"https://도메인.info/?file=../../../../etc/passwd"
결과 :
403
BLOCK 모드에서는 정상적인 요청을 제외하고 모두 403이 표시되는 것을 확인할 수 있습니다.
로그를 살펴보면, SQL_INJECTION에 대한 요청이 BLOCK되는 것을 확인할 수 있습니다.
"action": "BLOCK" ← 차단
"terminatingRuleId": "AWSManagedRulesSQLiRuleSet" ← 탐지 룰
"conditionType": "SQL_INJECTION" ← SQL 인젝션으로 탐지
"matchedData": ["1","OR","1","=","1"] ← 탐지된 패턴
"matchedFieldName": "id" ← id 파라미터에서 탐지
"args": "id=1%27%20OR%20%271%27%3D%271" ← URL 디코딩 시 1' OR '1'='1
테스트 결과
COUNT모드와 BLOCK모드의 테스트 결과는 다음과 같습니다.
| 테스트 항목 | COUNT 모드 | BLOCK 모드 |
|---|---|---|
| 정상 요청 | 200 ALLOW | 200 ALLOW |
| XSS | 200 ALLOW (COUNT 기록) | 403 BLOCK |
| SQL 인젝션 | 200 ALLOW (COUNT 기록) | 403 BLOCK |
| 로그 action | COUNT | BLOCK |
| terminatingRule | null | 탐지 룰 표시 |
위 결과를 통해 COUNT 모드와 BLOCK 모드의 동작 차이를 명확하게 확인할 수 있습니다.
COUNT 모드에서는 공격으로 탐지된 요청이라 하더라도 실제 차단은 수행되지 않고, 로그에만 기록된 후 정상 요청과 동일하게 처리됩니다. 즉, 서비스에 영향을 주지 않으면서 룰의 동작을 검증할 수 있는 "테스트 모드"로 활용할 수 있습니다.
반면 BLOCK 모드에서는 동일한 요청이 실제로 차단되며, 애플리케이션까지 도달하지 않고 WAF 단계에서 403 응답을 반환하는 것을 확인할 수 있습니다. 이를 통해 SQL Injection, XSS와 같은 공격을 효과적으로 방어할 수 있습니다.
특히 주목할 점은, COUNT 모드에서는 overriddenAction: BLOCK으로 표시되듯 원래는 차단되어야 할 요청이 COUNT 모드에 의해 허용되고 있다는 점입니다. 이는 COUNT 모드가 단순 로깅 목적이 아니라, 실제 차단 정책을 적용하기 전 검증 단계로 설계되었음을 의미합니다.
따라서 실무에서는 다음과 같은 순서로 사용하는 것이 일반적입니다.
- COUNT 모드로 룰 적용 및 트래픽 분석
- 오탐(False Positive) 여부 확인
- 문제 없는 룰에 한해 BLOCK 모드로 전환
이러한 과정을 통해 정상 사용자에 대한 영향 없이 보안 정책을 안정적으로 적용할 수 있습니다.
마지막으로
AWS WAF의 COUNT 모드와 BLOCK 모드는 각각 역할이 명확하게 나뉘어 있습니다.
COUNT 모드는 실제 트래픽에 영향을 주지 않으면서 룰의 동작을 검증할 수 있는 단계이며, BLOCK 모드는 검증이 완료된 룰을 기반으로 실제 공격 트래픽을 차단하는 보호 단계입니다.
따라서 두 모드는 서로 대체 관계가 아니라, 보안 정책을 안전하게 적용하기 위한 단계적인 구성 요소라고 볼 수 있습니다.
실무에서는 COUNT 모드로 충분히 트래픽을 확인한 뒤 오탐 여부를 제거하고 BLOCK 모드로 전환하는 방식이 가장 안정적인 운영 방법입니다.
AWS WAF를 효과적으로 활용하기 위해서는 바로 차단보다는 검증 후 차단이라는 흐름을 가져가는 것이 중요합니다. 이 글이 AWS WAF의 COUNT 모드와 BLOCK 모드를 이해하는 데 도움이 되었으면 합니다.







