DB 복제 지연과 SQL Injection(1)

이슈 발생

지난 주 화요일, 아침부터 급한 에러가 발생했다. PO분은 아직 하시기 전이지만 슬랙에서 상황을 공유해주셨고 다행히 일찍 출근했던터라 바로 이슈를 확인했다. 먼저 New relic에서 로그를 살펴봤다. (MySQLdb._exceptions.OperationalError)Disk full 에러를 확인할 수 있었다. 처음 본 에러였지만 누가봐도 지금 DB가 부족하구나라는 생각을 할 수 있을 것이다. 이미 새벽에도 DB 용량 알림이 와서 플랫폼 챕터에서 스토리지 확장을 했는데도 불구하고 새벽 3시 48분쯤부터 에러가 지속적으로 발생했었다.

바로 플랫폼 챕터에 에러를 공유하고 AWS에서도 RDS를 확인해봤다. 문제가 되는 DB는 여러 slave DB 중 하나였다. FreeStorageSpace 그래프가 빨갛게 일직선으로 죽 그어져 있었다. 여유 공간이 하나도 없다는 의미였다. 아직 출근 중이셨던 플랫폼 챕터 리드분의 설명대로 해당 DB 상세에서 최대 스토리지와 할당 스토리지를 확인하고 요청하신대로 용량을 늘리도록 했다. 이때 중요한 건 예약 수정을 하지 않고 즉시 수정을 해야한다는 것이다. 수정 사항은 바로 반영되지는 않아서 기다리는 시간이 필요했다.

그동안 해당 DB를 사용하는 서비스를 모두 찾아서 다른 slave DB로 바꿔서 배포하는 작업을 진행했다. 배포라 완료된 후 PO분이 공유해주신 이슈는 우선 해결된 걸 확인한 후 채널에 다시 공유한 후 계속 DB 모니터링을 했다. slave DB의 복제 지연, CPU 사용률, DB 연결 그래프 등을 계속 슬랙에 공유하면서 다른 개발자분들과 지켜보았다. 복제 지연에 대한 경험은 이번이 처음이었는데 기다리는 방법 밖에는 없다는 생각이 들었다.

끝난 줄 알았지만..

문제되는 slave DB 변경 사항이 적용되고 복제 지연이 해결되길 기다리다가 오후에 다시 DB를 변경하고 배포한 후 문제가 해결되었다고 생각하고 다시 원래 업무를 하고 있었다. 그런데 복제 지연이 다시 발생했다. 플랫폼 챕터에서 쿼리문을 공유해주시는데 where 절에 이상한 조건이 있었다. 해당 쿼리를 찾아보니 django 기반의 레거시 프로젝트에서 사용되는 쿼리였다.

해당 프로젝트에서는 대부분 ORM을 사용하지만 그 API에서는 긴 raw query를 사용하고 있었다. 이상한 조건이 들어갔던 파리미터에 대한 유효성을 확인하는 부분이 없어서 급하게 코드를 추가하고 다시 배포를 했다. 나중에 다른 팀원분이 뭔가 이상했던 쿼리가 sql injection이라는 걸 확인해주셨다. 이전 회사에서 겪어본 적이 있으셔서 쿼리를 보시더니 금방 파악하셨다. 아침부터 발생한 Disk full 에러도 결국은 sql injection으로부터 시작된 일이었다.

많은 걸 겪게 된 하루였다. 더불어 보안에 대해 다시 한 번 생각하게 되었다. 이 일을 겪고 나서 우아한 형제들 컨퍼런스를 보다가 보안 엔지니어분의 발표를 보게 되었다. AWS의 WAF 운영에 과한 발표(우아한형제들의 AWS WAF 운영 이야기)였는데 이 발표를 통해 WAF라는 서비스를 처음 알게 되었다. 발표를 들으면서 WAF를 이용하면 보안에 관한 문제를 해결하는데에 도움이 될 수 있을 것 같다는 생각이 들어 플랫폼 챕터와도 회사에서 WAF를 도입할 수 있는지 얘기해보았다. WAF를 사용하게 될지는 플랫폼 챕터에서 결정하는 일이지만, 이번 일을 통해 스스로도 보안에 대해 생각해보는 계기가 되었다. 보안에 관한 책도 읽어보고 공부해보고 싶다는 생각은 했지만, 못하고 있었는데 이번 일이 좋은 동기부여가 되었다.