Coraza WAF
Coraza는 엔터프라이즈급 고성능 웹 애플리케이션 방화벽 (WAF) 이다. Go 언어로 작성되었으며 Modsecurity SecLang Rule set을 지원하고 OWASP Core Rule Set v4와 100% 호환한다.
✏️ Coraza를 알아보기 전에..
Coraza를 알아보기 전에 WAF와 OWASP에 대해 간단히 알아보면 좋을 것 같다.
Coraza 특징
- Drop-in: Coraza는 ModSecurity Engine과 일부 호환하는 엔진이며, 산업 표준의 SecLang Rule set을 제공한다.
- Security: Coraza는 OWASP CRS V4를 실행하여 최소한의 거짓 경고로 OWASP Top 10을 포함한 광범위한 공격으로부터 웹 애플리케이션을 보호한다. CRS는 대표적으로 다음을 포함한 공격으로부터 보호한다.
- SQL Injection
- XSS (Cross Site Scripting)
- PHP & Java Code Injection
- HTTProxy
- Shellshock
- Scripting / Scanner / Bot Detection & Metadata & Error Leakages
- Extensible: Coraza는 온프레미스 WAF 인스턴스를 배포하기 위한 다양한 통합 기능을 갖춘 라이브러리이다. Audit logger, persistence engines, operators, action 등을 사용하여 Coraza의 기능을 확장할 수 있다.
- Performance: Coraza는 최소한의 성능 영향으로 부하를 처리할 수 있다.
Istio에 Coraza WAF 적용하기
Istio는 Envoy proxy를 활용하여 쿠버네티스 클러스터 내의 트래픽 흐름을 제어하는 오픈소스 서비스 메쉬 이다. Istio를 사용하면 클러스터 내로 들어오는 트래픽, 클러스터 내부에서 내부로 향하는 트래픽, 클러스터 내부에서 외부로 나가는 트래픽 등을 애플리케이션 코드 변경 없이 제어할 수 있다.
WAF는 웹 애플리케이션 방화벽으로, 들어오는 요청에 대해 부적한 요청이 있는지 검사한 후 부적절한 요청이라면 차단시키는 것이 WAF의 역할이므로, Istio에서는 들어오는 트래픽을 제어하는 Ingressgateway에 WAF를 추가해야 할 것이다.
Coraza를 도입하면 그림과 같은 형태가 될 것인데, 들어오는 모든 요청들이 ingressgateway로 들어올 때 Coraza에서 요청을 검사한 후 부적절한 요청이 있으면 차단시키고 나머지 요청들은 ingressgateway에서 트래픽을 제어하여 적절한 하위 애플리케이션에게 요청을 전달하게 된다.
Wasm Plugin
Coraza를 ingressgateway에 배포할 때는 사이드카 형태로 배포하지 않고 Wasm Plugin (Web Assembly Plugin) 을 사용하여 Ingressgateway에 Web Assembly Filter를 추가하는 형태로 Coraza를 적용시킬 수 있다. Coraza 공식 레포지토리에서 Envoy proxy와 Istio를 위한 Web Assembly Plugin을 제공해주기 때문에 이것을 사용하여 간단히 ingressgateway에 Coraza WAF를 적용시킬 수 있다.
https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/
https://github.com/corazawaf/coraza-proxy-wasm/tree/main/example/istio
Wasm Plugin은 다음과 같이 적용시키면 된다.
apiVersion: extensions.istio.io/v1alpha1
kind: WasmPlugin
metadata:
name: coraza-waf
namespace: istio-ingress
spec:
selector:
matchLabels:
app: ingressgateway
url: oci://ghcr.io/corazawaf/coraza-proxy-wasm
imagePullPolicy: IfNotPresent
phase: AUTHN
pluginConfig:
default_directives: default
directives_map:
default:
- Include @recommended-conf
- SecDebugLogLevel 9
- SecRuleEngine On
- Include @crs-setup-conf
- Include @owasp_crs/*.conf
spec.selector.matchLabels
: 적용시킬 ingressgateway 파드를 특정시킬 있는 레이블을 입력한다. 환경에 따라 여러 ingressgateway가 나뉘어져 있을 수 있기 때문에 신중히 설정하자.spec.phase
: 필터 체인의 어느 부분에서 WasmPlugin을 삽입할지 결정한다. AUTHN으로 하는 경우 인증필터 이후에 WasmFilter를 넣기 때문에 mTLS를 사용하지 않는다는 전제하에 Coraza로 트래픽이 들어오는 순간 HTTP Payload는 복호화가 되어 평문으로 전달된다. (Request body를 검사하려면 평문으로 전달되어야 함)spec.pluginConfig
: 이건 어떤 플러그인을 사용하는지에 따라 필드가 달라지는데 Coraza에서는 크게 두 가지 필드를 제공하고 있다.directives_map
: key - value 형태로 되어있으며, value는 문자열 배열 형태로 이루어진다. 추후에 추가로 설명하겠지만 여러가지 Directive를 사용하여 Coraza Core rule set을 설정할 수 있으며 directives_map을 통해 여러 버전의 Rule Set을 관리할 수 있다.default_directives
: directives_map에 설정한 것 중에 실제로 사용할 directive이다.
여기서 Include라는 directive가 있는데, Include가 하는 역할은 특정 파일에 써있는 Directive를 가져온다는 의미이다. nginx의 include directive와 비슷하다.
위에서 선언되어있는 Include된 파일 내용은 링크된 파일과 동일하다.
- @recommended-conf
- @crs-setup-conf
- @owasp_crs/*.conf
- 여기에 XSS, SQL Injection 등의 여러 보안 공격에 대한 Core Rule Set이 정의되어 있다.
- 실제로 적용하고 싶은 Rule Set만을 활성화 하고 싶다면
@owasp_crs/REQUEST-941-APPLICATION-ATTACK-XSS.conf
과 같이 설정하면 된다.
coraza-waf wasm filter를 적용하면 ingressgateway에 다음과 같은 로그가 뜰 것이다.
2024-11-10T12:01:42.689297Z info wasm fetching image corazawaf/coraza-proxy-wasm from registry ghcr.io with tag main
2024-11-10T12:01:55.084334Z info Readiness succeeded in 13.041890911s
2024-11-10T12:01:55.084942Z info Envoy proxy is ready
❗️주의해야 할 점❗️
Wasm Plugin을 사용하면 적용시키는 사이드카에 Web Assembly가 실행되기 때문에 추가적인 리소스를 사용하게 된다. 경험상 Coraza wasm plugin을 도입만 할 경우 트래픽이 없어도 약 200MB의 메모리 점유가 발생하는 것으로 보인다.
그래서 도입 전에는 반드시 ingressgateway의 Memory requests를 256MB 이상으로 설정한 후 wasm plugin을 적용시키자. Wasm Plugin 도입은 롤링 배포가 아니기 떄문에 잘못 적용하면 ingressgateway 전체적으로 OOM이 발생할 것이다.
Test
테스트는 간단하게 XSS 가능성이 있는 요청을 날려보면 된다. 403 에러가 발생하면 성공. (기본적으로 Coraza는 부적절한 요청을 403으로 리턴시켜 차단시킨다.)
$ curl -XGET -I ${SERVER_HOST}/xss-test?script=<script>alert(\"test\")</scrpt>"
HTTP/2 403
요청 후 ingressgateway 로그를 확인하면 어떤 요청에 어떤 위반사항이 발생하는지 확인이 가능하다.
2024-11-10T12:13:30.065257Z critical envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1204 wasm log istio-system.coraza-waf: [client "${CLIENT_IP}"] Coraza: Warning. XSS Attack Detected via libinjection [file "@owasp_crs/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "7795"] [id "941100"] [rev ""] [msg "XSS Attack Detected via libinjection"] [data "Matched Data: XSS data found within ARGS_GET:script: <script></script>"] [severity "critical"] [ver "OWASP_CRS/4.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "xss-perf-disable"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "${HOST_IP}"] [uri "/xss-test?script=<script></script>"] [unique_id "fWBmusFpUfJhjGlQnOa"] thread=35
2024-11-10T12:13:30.065350Z critical envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1204 wasm log istio-system.coraza-waf: [client "${CLIENT_IP}"] Coraza: Warning. XSS Filter - Category 1: Script Tag Vector [file "@owasp_crs/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "7822"] [id "941110"] [rev ""] [msg "XSS Filter - Category 1: Script Tag Vector"] [data "Matched Data: <script> found within ARGS_GET:script: <script></script>"] [severity "critical"] [ver "OWASP_CRS/4.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "xss-perf-disable"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "${HOST_IP}"] [uri "/xss-test?script=<script></script>"] [unique_id "fWBmusFpUfJhjGlQnOa"] thread=35
2024-11-10T12:13:30.065407Z critical envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1204 wasm log istio-system.coraza-waf: [client "${CLIENT_IP}"] Coraza: Warning. NoScript XSS InjectionChecker: HTML Injection [file "@owasp_crs/REQUEST-941-APPLICATION-ATTACK-XSS.conf"] [line "7914"] [id "941160"] [rev ""] [msg "NoScript XSS InjectionChecker: HTML Injection"] [data "Matched Data: <script found within ARGS_GET:script: <script></script>"] [severity "critical"] [ver "OWASP_CRS/4.3.0"] [maturity "0"] [accuracy "0"] [tag "application-multi"] [tag "language-multi"] [tag "platform-multi"] [tag "attack-xss"] [tag "xss-perf-disable"] [tag "paranoia-level/1"] [tag "OWASP_CRS"] [tag "capec/1000/152/242"] [hostname "${HOST_IP}"] [uri "/xss-test?script=<script></script>"] [unique_id "fWBmusFpUfJhjGlQnOa"] thread=35
2024-11-10T12:13:30.065845Z critical envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1204 wasm log istio-system.coraza-waf: [client "${CLIENT_IP}"] Coraza: Warning. Inbound Anomaly Score Exceeded in phase 1 (Total Score: 15) [file "@owasp_crs/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "11560"] [id "949111"] [rev ""] [msg "Inbound Anomaly Score Exceeded in phase 1 (Total Score: 15)"] [data ""] [severity "emergency"] [ver "OWASP_CRS/4.3.0"] [maturity "0"] [accuracy "0"] [tag "anomaly-evaluation"] [tag "OWASP_CRS"] [hostname "${HOST_IP}"] [uri "/xss-test?script=<script></script>"] [unique_id "fWBmusFpUfJhjGlQnOa"] thread=35
2024-11-10T12:13:30.069020Z critical envoy wasm external/envoy/source/extensions/common/wasm/context.cc:1204 wasm log istio-system.coraza-waf: [client "${CLIENT_IP}"] Coraza: Warning. Inbound Anomaly Score Exceeded (Total Score: 15) [file "@owasp_crs/REQUEST-949-BLOCKING-EVALUATION.conf"] [line "11572"] [id "949110"] [rev ""] [msg "Inbound Anomaly Score Exceeded (Total Score: 15)"] [data ""] [severity "emergency"] [ver "OWASP_CRS/4.3.0"] [maturity "0"] [accuracy "0"] [tag "anomaly-evaluation"] [tag "OWASP_CRS"] [hostname "${HOST_IP}"] [uri "/xss-test?script=<script></script>"] [unique_id "fWBmusFpUfJhjGlQnOa"] thread=35
- clinet: 요청자의 IP
- file: 요청에 대해 위반했다고 판단한 Rule이 있는 파일
- id: 요청에 대해 위반했다고 판단한 Rule의 id, 어떤 위반사항이 발생했는지 Rule을 알고싶으면
file
에 있는 파일에서 id를 검색해보면 된다. - msg: 위반사항 내용
- data: 위반사항 상세로그 정도로 확인하면 됨.
- severity: 위반사항 심각도
- tag: Rule이 가지고 있는 태그값 (여러개 있음.)
- hostname: host name이라고 하지만 사실상 호스트 IP임. istio에서는 ingressgateway IP
- uri: 요청 URI, host, protocol, method가 왜 없는지는 모르겠다.
- unique_id: 트랜잭션 id이다. 한 트랜잭션에서 여러 rule 위반사항이 발생할 수 있으며, 위반사항 마다 로그가 찍힌다.
마무리
istio에서 간단히 coraza WAF를 적용하는 방법에 대해 알아보았다. 사실 WAF 도입 자체는 쉽지만 WAF를 관리하는 것이 어렵다고 생각한다. 관리를 할 때는 어떤 Core Rule Set을 활성화 할지/비활성화 할지 결정해야 하며, Core Rule Set을 바로 프로덕션에 적용한다면 이미 자주 들어오는 (정상적이라고 생각하는) 일부 트래픽은 모두 403 에러로 예상치 못하게 리턴되는 일이 발생할 수 있다.
그래서 WAF를 프로덕션에서 적용시키기 전에 Detection Mode로 적용시켜서 평소에 들어오는 요청 중에 기본 CRS에 위반되는 트래픽이 있는지 확인한 다음, 적용시킬 Rule Set을 정하는 것이 우선이며, 이 선택을 하기 위해서는 로깅 및 모니터링 시스템이 우선적으로 받쳐줘야 한다. Coraza에서 쌓이는 로그를 Elasticsearch와 같은 로그 백엔드에 먼저 적재시킨 후 걸리는 CRS를 분석한 후 필요한 Rule Set을 걸러낸 다음 프로덕션에 적용시켜야 할 것이다.
시간이 된다면 Core Rule Set을 적용시키는 방법에 대한 글을 작성해 볼 에정이다.
'보안' 카테고리의 다른 글
OWASP란? (1) | 2024.11.06 |
---|---|
WAF(웹 방화벽) 소개 (2) | 2024.11.05 |
댓글