오늘은 최근에 겪은 SQL Injection 공격과 이에 대응하기 위해 적용한 보안 대책에 대해 공유하려고 한다.
어느 날 갑자기 시스템의 설문이 순식간에 2600개가 넘게 들어왔다..
분석 결과 SQL Injection 공격이었고 급하게 POST 요청을 차단했지만, 언제 다시 공격이 있을지 모르기에 좀 더 체계적인 보안 대책을 마련하기로 했다.
보안 대책
- Nginx Rate Limit
- google reCAPTCHA
- form 입력 유효성 검사
이 중에서 오늘은 Nginx Rate Limit에 대해 이야기하려고 한다.
Nginx Rate Limit
속도 제한은 보안 목적으로 사용될 수 있으며, 예를 들어 무차별 대입 공격(brute-force password guessing attack)의 속도를 늦추는 데 사용될 수 있습니다. 또한, 수신 요청 속도를 실제 사용자에게 일반적인 값으로 제한하고 (로깅을 통해) 대상 URL을 식별하여 DDoS 공격으로부터 보호하는 데 도움이 될 수 있습니다 . 더 일반적으로, 이는 동시에 너무 많은 사용자 요청으로 인해 업스트림 애플리케이션 서버가 과부하되는 것을 방지하는 데 사용됩니다.
첫번째 시도 : if문 사용 (실패)
처음에는 현재 들어온 요청이 POST인지 확인하고, POST 요청이라면 rate limit을 적용하는 방식으로 설정했다.
# http 블록 내에 추가
map $request_method $is_post_method {
default 0;
POST 1;
}
# POST 요청에만 사용될 rate limit 영역 정의
limit_req_zone $binary_remote_addr zone=post_limit:10m rate=1r/s;
server {
listen 80;
server_name example.com;
location / {
# POST 요청일 때만 rate limit 적용
if ($is_post_method) {
limit_req zone=post_limit burst=5 nodelay;
}
proxy_pass http://backend;
# 기타 필요한 설정...
}
}
[emerg] 403952#403952: invalid number of arguments in "limit_req" directive in /etc/nginx/sites-enabled/front-app:17 nginx: configuration file /etc/nginx/nginx.conf test failed ubuntu@:/etc/nginx$ sudo vi sites-enabled/front-app
하지만 지속해서 이런 오류가 나왔고, Nginx에서 if문 내에 limit_req를 사용해서 생긴 오류로 추측했다.
그리고 또 얼레벌레 고친줄 알았지만 받은 제보…^^ rate limit이 POST 요청에만 설정된게 아니라 모든 요청에 설정되서 생긴 오류였다.
두 번째 시도 : 스택오버플로우 (성공)
다행히 스택오버플로우에 나랑 같은 상황의 질문을 보게 되었고, 아래와 같은 방법으로 해결할 수 있었다.
http {
... # your nginx.conf here
# Maps ip address to $limit variable if request is of type POST
map $request_method $limit {
default "";
POST $binary_remote_addr;
}
# Creates 10mb zone in memory for storing binary ips
limit_req_zone $limit zone=my_zone:10m rate=1r/s;
}
**Rate limiting for the entire NGINX process:**
http {
... # your nginx.conf here
limit_req zone=global_zone;
}
map 지시어를 사용하여 POST 요청일 때만 클라이언트 IP를 저장하고, 다른 요청은 빈 문자열로 설정하였다. 이렇게 하니 POST 요청에만 rate limit이 적용되었다.
결론
웹 애플리케이션을 운영하다 보면 언제든 보안 공격의 대상이 될 수 있다. 이번 SQL Injection 공격 경험을 통해 미리 여러 층의 방어책을 마련하는 것이 얼마나 중요한지 다시 한번 깨달았다.
Nginx rate limit은 구현이 비교적 간단하면서도 효과적인 방어 수단이다. 하지만 구현 과정에서 보았듯이 사소한 문법 오류나 설정 실수가 전체 시스템에 영향을 줄 수 있으므로 신중하게 접근해야 한다.
완벽한 보안 시스템은 없지만 여러 단계의 보안 조치를 통해 공격자의 진입 장벽을 높이고 피해를 최소화할 수 있다.