해커가 우리 사이트를 공격했다 - WAF(웹 방화벽)로 방어한 썰
1. DB에 이상한 데이터가 들어오고 있다
보안 이슈 사례를 공부하다 보면 빠지지 않고 등장하는 상황이 있습니다.
서비스 런칭 초기, order_note 컬럼에 이런 데이터가 쌓이기 시작하는 것입니다.
' OR 1=1 --
'; DROP TABLE users; --
UNION SELECT 1, @@version --
등골이 서늘해지는 데이터입니다. SQL Injection 공격입니다. 누군가 사이트의 취약점을 찾기 위해 자동화된 스캐너를 돌리고 있는 것이죠. ORM이 기본적인 방어는 해주더라도, 로그를 보면 초당 100회 이상의 접속 시도로 서버 CPU가 100%를 치고 있는 경우가 많습니다.
이런 상황에서 "코드 레벨에서 IP 차단할까?"라는 생각이 들 수 있지만, 그렇게 하면 서버가 그 IP 검사하느라 또 자원을 씁니다. 애플리케이션 서버에 도달하기 전에 막아야 합니다.
2. 구원투수 등판: Web Application Firewall (WAF)
WAF는 말 그대로 '웹 애플리케이션 방화벽'입니다. 이해하기 쉽게 공항 보안 검색대에 비유해 보겠습니다.
- Network Firewall (L3/L4): 여권 심사대
- IP(국적)와 Port(목적)만 봅니다.
- "너 차단된 국가(IP)에서 왔네? 입국 금지."
- 하지만 여권이 정상이면 가방 속에 폭탄이 있어도 통과시킵니다.
- WAF (L7): 수하물 검색대 (X-ray)
- HTTP 패킷의 내용(Body, Header, Cookie)을 뜯어봅니다.
- "너 정상적인 IP네? 근데 가방(Body) 속에 칼(SQL Injection)이 있네? 차단."
우리는 급하게 AWS WAF를 ALB(Load Balancer) 앞에 붙였습니다.
2.1. 방어 1단계: OWASP Core Rule Set (CRS)
WAF에는 OWASP CRS라는 표준 규칙 세트가 있습니다. 이걸 켜기만 하면, 전 세계적으로 알려진 공격 패턴들을 자동으로 막아줍니다.
- SQL Injection:
' OR 1=1같은 패턴 차단. - XSS:
<script>태그 포함 시 차단. - LFI/RFI:
/etc/passwd같은 시스템 파일 경로 접근 차단. - ShellShock, Java Serializaion 등: 알려진 CVE 취약점 차단.
적용하자마자 공격 로그가 뚝 끊겼습니다. 빨갛게 달아올랐던 서버 CPU가 평온을 되찾았습니다.
3. 보안 모델: Positive vs Negative
WAF를 운영할 때 반드시 알아야 할 두 가지 철학이 있습니다.
1) Negative Security Model (블랙리스트)
- 개념: "일단 다 들어와. 근데 나쁜 놈(공격 패턴)은 막을 거야."
- 장점: 정상적인 사용자에게 불편을 덜 줍니다.
- 단점: 신종 공격(Zero-day)은 못 막습니다. (패턴에 없으니까요)
- 예시: AWS Managed Rules, OWASP CRS. 대부분의 WAF가 기본으로 쓰는 방식입니다.
2) Positive Security Model (화이트리스트)
- 개념: "일단 다 꺼져. 내가 허락한 놈(정상 패턴)만 들어와."
- 장점: 가장 안전합니다. 신종 공격도 막습니다. (허락 안 했으니까요)
- 단점: 설정이 매우 어렵습니다. 정상 유저가 차단될 확률(False Positive)이 높습니다.
- 예시: "API 요청은 반드시 JSON 포맷이어야 하고,
id필드는 숫자여야만 해"라고 WAF에 정의하는 것.
4. WAF 운영의 적 - 오탐(False Positive)
WAF를 도입하고 며칠 뒤, 이런 문제가 보고됩니다. 회원가입이 안 된다는 사용자 신고가 들어온 것입니다.
로그를 보니 차단된 사용자의 닉네임이 "Select" 였습니다.
WAF가 Select라는 단어를 보고 "어? 이거 SQL Injection 구문(SELECT * FROM) 아니야?" 하고 차단해버린 겁니다. (실화입니다)
이것이 오탐(False Positive)입니다. 보안이 너무 강력해서 정상적인 사용자를 범죄자 취급하는 것이죠.
해결책:
- Count Mode (Log Only): 처음엔 차단하지 말고 로그만 남깁니다.
- Tuning: 로그를 분석해서 "닉네임 필드에서는 SQL 패턴 검사를 끈다"는 예외 규칙(Exception)을 추가합니다.
- Enforce: 안전하다 싶으면 차단 모드로 전환합니다.
5. 클라우드 WAF가 대세인 이유
옛날에는 ModSecurity 같은 오픈소스 WAF를 직접 서버(Nginx)에 설치해서 썼습니다. 하지만 요즘은 무조건 Cloud WAF (AWS, Cloudflare)를 추천합니다.
- 성능: WAF 검사 자체가 CPU를 많이 먹습니다. 클라우드는 이 부하를 엣지(Edge)에서 처리해주므로 우리 서버는 쾌적합니다.
- 최신성: 새로운 취약점(예: Log4Shell)이 나오면 클라우드 보안 팀이 몇 시간 안에 규칙을 업데이트해줍니다. 내가 잘 때도 방패가 업그레이드됩니다.
- DDoS 방어: 클라우드 WAF는 거대한 대역폭을 가지고 있어서, 대규모 네트워크 공격도 흡수해줍니다.
6. 마무리 - 보안은 '돈'으로 사는 게 싸다
스타트업 CTO분들이 흔히 하는 말. "AWS WAF 비싸지 않나요?"
계산해 봅시다. AWS WAF는 월 $5 + 요청 100만 건당 $0.6입니다. 트래픽이 적은 스타트업이라면 커피 두 잔 값도 안 나옵니다.
반면, 보안 사고가 터지면? 개인정보 유출 과태료, 고객 신뢰 하락, 복구 비용... 수억 원이 깨집니다. 회사가 문을 닫을 수도 있습니다.
개발자 여러분, SQL Injection 방어 코드를 짜느라 밤새지 마세요. 정규식 깎고 있지 마세요. 그냥 WAF를 켜세요. 그리고 남은 시간에 비즈니스 로직을 짜세요. 그게 회사와 여러분의 정신건강 모두를 지키는 길입니다.
9. ModSecurity (오픈소스 WAF의 제왕) 제대로 이해하기
클라우드 WAF를 쓸 돈이 없다면, ModSecurity가 대안입니다. Nginx, Apache에 플러그인으로 설치하는 가장 유명한 오픈소스 WAF입니다. 하지만 설정이 악명 높기로 유명합니다.
예를 들어 SQL Injection을 막는 규칙은 이렇게 생겼습니다:
SecRule ARGS "DELETE[[:space:]]+FROM" "id:1000,deny,msg:'SQL Injection Attempt'"
이걸 직접 짜는 건 무모한 일이고, 보통 OWASP CRS라는 규칙 세트를 다운받아 적용합니다. 단점은 성능입니다. 모든 요청의 본문을 정규표현식으로 검사하느라 서버 속도가 10~20% 느려질 수 있습니다. 트래픽이 많은 서비스라면 서버 비용이 WAF 비용보다 더 나올 수도 있습니다.