WAF 워크숍을 해보았습니다.(Protect your application security perimeter with AWS WAF)

2023.11.09

안녕하세요, 클래스메소드의 서은우 입니다.

AWS에는 보안과 관련된 여러 서비스 중, AWS WAF 서비스를 이용하면 손 쉽게 웹 어플리케이션을 보호할 수 있습니다.

AWS에서는 AWS WAF에 관한 지식을 배울 수 있는 워크숍을 제공하고 있는데요, 본 블로그에서는 해당 워크숍을 제가 직접 진행해보고 그 내용을 여러분에게 소개 시켜드리고자합니다.

지난 블로그에서는 WAF 기초에 관한 워크숍을 진행해 보았습니다. WAF의 기초에 대해서 알아보고자 하시는 분들은 지난 블로그의 워크숍을 진행해보시는 것을 추천드립니다.

본 블로그에서 소개해드릴 워크숍은 "Protect your application security perimeter with AWS WAF"로 지난 블로그의 "Introduction to WAF" 와 본 블로그에서 소개해 드릴 워크숍은 아래의 링크를 통해 이동하실 수 있습니다.

목차

워크숍은 다음과 같은 순서로 진행됩니다.

  • Getting started at an AWS hosted event
  • Creating Web ACLs and Enabling WAF Logging
  • Working with Managed Rules
  • Working with Custom Rules
  • Managing SQLi Sensitivity Levels
  • Protecting against application-layer floods
  • Analyzing WAF Logs using CloudWatch
  • Summary
  • Takeaway resources
  • Cleanup

Getting started at an AWS hosted event

워크숍에 필요한 인프라와 리소스를 구성하는 파트입니다.

AWS 계정이 없는 경우, Workshop Studio에 가입하여 제공되는 리소스를 사용하여 워크숍을 진행할 수 있습니다. AWS 계정이 있는 경우에는 제공되는 CloudFormation 스택을 사용하여 워크숍에 필요한 환경을 구축할 수 있습니다.

테스트 리퀘스트 등 테스트는 CloudShell을 통해 이루어집니다.

테스트를 위해 생성완료 된 CloudFormation 스택의 Output 에서 JuiceShopURL 의 값을 CloudShell 에 변수로 설정합니다.

# CloudShell
JUICESHOP_URL=<Your JuiceShopURL CloudFormation Output>

Creating Web ACLs and Enabling WAF Logging

Web ACL을 생성하고 생성된 Web ACL의 로깅 설정을 활성화 하는 파트입니다.

먼저 Web ACL을 생성하기 위해 AWS WAF 콘솔 화면으로 이동하여 WebACL 항목으로 이동합니다.

Web ACL의 생성 리전으로 Global(CloudFront) 를 선택합니다.

WebACL 이름과 설명을 입력하면 CloudWatch 지표 이름이 자동으로 생성되는 것을 확인할 수 있습니다. 그리고 리소스 타입이 Amazon CloudFront distributions 임을 확인해주세요.

스트롤을 내려 WAF를 연결시킬 AWS 리소스를 선택해줍니다. CloudFormation 으로 미리 생성된 리소스를 선택한 후 다음으로 넘어가주세요.

나머지 설정들은 기본으로 설정되어 있는 값들을 그대로 둔 후 Web ACL의 생성을 완료합니다.

생성된 Web ACL의 로깅을 활성화 합니다.

로깅 옵션으로 CloudWatch Logs log group을 선택하고 로그 그룹을 지정합니다. (CloudWatch 로그 그룹이 없다면 생성해주세요)

다른 설정 값들은 기본으로 두고, Logging 설정을 완료합니다.

Working with Managed Rules

다음으로는 Web ACL에 관리형 규칙을 추가합니다.

관리형 규칙은 AWS가 관리하고 제공하는 규칙입니다. 일반적인 유형의 공격으로부터 보호하기 위해 사용할 수 있습니다.

해당 워크숍에서는 다음과 같은 룰을 설정해 공격들을 막습니다.

AWS Managed Rule Groups - Core rule set: 웹 애플리케이션에 공통적인 광범위한 취약성을 다루는 규칙 - SQL database: SQL 인젝션과 같은 SQL 데이터베이스 공격으로부터 보호하기 위한 규칙

생성한 Web ACL의 콘솔 화면의 Rules 항목에서 관리형 규칙을 추가합니다.

Add manged rule groups 버튼을 눌러 주세요. AWS Managed Rule Groups - Free rule groups 에서 해당 룰 그룹을 추가하고 설정을 완료합니다.

CloudShell 터미널에서 다음 명령을 입력하여 테스트를 진행합니다.

# 테스트 요청
curl -I $JUICESHOP_URL?execute=http://sneaky-domain.io/file.

Working with Custom Rules

이번 파트에서는 직접 규칙을 설정할 수 있는 사용자 지정 규칙을 생성합니다.

본 워크숍에서는 X-Weak-Spot 또는 x-sneaky-attack 이라는 헤더의 요청을 차단하는 사용자 지정 규칙을 생성합니다. 콘솔 화면에서 Add my own rulse and rule groups 버튼을 눌러 설정을 진행합니다.

요청에 X-Weak-Spot 또는 x-sneaky-attack 헤더 둘 중 하나라도 포함되어 있는 경우 차단을 해야하기 때문에 OR 문을 선택하고 설정 값을 입력해주세요.

Size in bytes 항목을 0으로 입력할 경우, 빈 칸으로 출력하게 됩니다.

CloudShell 터미널에서 다음 명령을 입력하여 테스트를 진행합니다.

# 테스트 요청
# X-Weak-Spot 헤더가 포함된 요청
curl -I -H "X-Weak-Spot: Exploit" "${JUICESHOP_URL}"

# x-sneaky-attack 헤더가 포함된 요청
curl -I "${JUICESHOP_URL}?x-sneaky-attack=exploit"

Managing SQLi Sensitivity Levels

이번 파트에서는 SQL Injection 공격에 대한 규칙을 설정합니다.

AWS WAF에서는 SQIL Inejection에 대해 LOW, HIGH 두 종류의 민감도를 설정할 수 있습니다. 더 많은 SQL Injection 공격을 탐지할 수 있기 때문에 HIGH 를 사용하는 것이 좋지만, LOW 보다 많은 오탐지를 생성할 가능성도 높습니다.

각각의 민감도 레벨이 설정된 룰을 추가합니다.

「Custom response」 를 설정하여 해당 룰에 해당 되는 요청의 경우, 지정해둔 액션(워크숍의 경우 Block)과 함께 원하는 응답을 보낼 수 있습니다.

본 워크숍에서는 응답 코드 200과 아래의 내용을 반환합니다.

# 민감도 LOW의 경우
SQLi **LOW** Sensitivity Level rule match

<br>

# 민감도 HIGH의 경우
SQLi **HIGH** Sensitivity Level rule match

<br>

테스트를 진행합니다.

# 민감도 LOW 테스트
curl -X POST $JUICESHOP_URL -F "user='AND 1=1;"

# 민감도 HIGH 테스트
curl -X POST $JUICESHOP_URL -F "1094 and 3=substirng(version(),1,1)"

Protecting against application-layer floods

해당 파트에서는 RBR(Rate-Based Rule) 사용에 대해 다루고 있습니다.

RBR은 비율을 기반으로 한 룰로, 예를 들어 5분에 1000개 이상의 요청을 보내는 모든 IP를 차단할 수 있습니다.

RBR 타입의 룰을 직접 생성해봅시다. 콘솔 화면에서 Add my own rulse and rule groups 버튼을 눌러 설정을 진행합니다.

룰 이름을 설정하고 Rate-based rule 옵션을 선택합니다.

다음으로는 비율 제한을 위한 설정이 있습니다. 각 설정에 대한 설명은 다음과 같습니다.

  • Rate limit: 5분 동안 허용되는 최대 요청 수
  • Request aggregation: 요청을 집계하기 위해 사용할 요소로 소스 IP, 헤더 속의 IP(예: X-Forwarded-For), 직접 집계 요소를 구성할 수 있는 커스텀 키, 규칙문 등을 설정 가능
  • Scope of inspection and rate limiting: Source IP를 선택할 경우 설정 가능한 옵션
    • Consider all requests: 해당 소스 IP로 부터의 모든 요청을 집계
    • Only consider requests that match the criteria in a rule statement: 규칙에 해당하는 요청만 집계

집계 요소로 Source IP를 선택한 경우, 해당 소스 IP로 부터의 오청에 대해 WAF가 검사할 범위를 설정할 수 있습니다.

워크샵에 경우, login 이라는 단어가 포함된 URL에 관한 요청을 검사하도록 설정하였습니다.

그리고 해당하는 요청을 거부하기 위해 Action 항목에서는 Block을 선택합니다.

CloudShell 터미널에서 다음 명령을 입력하여 테스트를 진행합니다.

# 요청이 제대로 보내지는지 확인
curl -I "${JUICESHOP_URL}/login"

# 해당 요청을 100번 반복
for i in {1..100}; do curl -I "${JUICESHOP_URL}/login" | grep title; done

다시 요청을 시도하면 다음과 같은 결과를 확인할 수 있습니다.

# 다시 요청을 시도
curl -I "${JUICESHOP_URL}/login"

# 해당 요청이 거부됨
HTTP/1.1 403 Forbidden
...

Analyzing WAF Logs using CloudWatch

이번 파트에서는 CloudWatch log insights 를 사용하여 WAF 로그를 분석합니다.

몇 가지의 쿼리 예제를 통해 이전 파트에서 테스트했던 내용에 관한 로그들을 분석해봅시다.

콘솔에서 CloudWatch log insights로 이동합니다. 분석을 하기 위한 로그 그룹을 선택하고 초기로 설정되어있는 쿼리를 실행합니다. 해당 쿼리는 20개의 최신 로그를 확인할 수 있습니다.

또한, 다음과 같은 쿼리를 실행하면 Country, ClientIP, URI, 일치하는 Rule 별로 차단된 요청에 대해 확인할 수 있습니다.

fields httpRequest.clientIp as ClientIP, httpRequest.country as Country, httpRequest.uri as URI, terminatingRuleId as Rule
| filter action = "BLOCK"
| stats count(*) as RequestCount by Country, ClientIP, URI, Rule
| sort RequestCount desc

다음은 쿼리는 관리형 룰인 Core rule set에서 감지한 모든 요청들을 확인할 수 있습니다.

fields @timestamp, @message
|filter @message like 'awswaf:managed:aws:core-rule-set'
| parse @message '"labels":[*]' as Labels
| sort @timestamp desc

Cleanup

끝으로 워크숍을 위해 생성한 리소스들을 삭제해주세요

  • Sample Web Application
    • CloudFormation 스택을 삭제
  • Web ACL
  • CloudWatch Log Group

끝으로

워크숍을 통해 AWS WAF의 다양한 기능들을 알아보고, 로그를 활용하는 방법까지 배울 수 있어서 좋았습니다.

배운 것을 바탕으로 앞으로 AWS WAF를 더욱 유용하게 활용할 수 있을 것 같습니다.