웹 어플리케이션은 수많은 위협에 노출되어 있습니다. SQL injection은 공격자가 SQL 여러가지 방법으로 구문을 DB에 주입해 특정 동작을 이끌어내는 공격입니다.
이러한 L7단 공격을 막기위해 AWS에서는 AWS WAF라는 웹 어플리케이션 방화벽을 만들었습니다.
이번 글에서는 이AWS WAF(Web Application Firewall)로 SQL injection 공격을 방어해보도록 하겠습니다.
Web Application 띄우기
S3에 정적 웹 파일 저장하기
먼저 Web Application을 띄워보겠습니다. WAF를 CloudFront에 설치할 것이기 때문에 간단한 HTML파일 하나를 S3 버킷에 넣어주겠습니다.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WAF</title>
</head>
<body>
<center>
<p>WAF Test page</p>
<h1><br> unlucky</h1>
기를 쓰고 사랑해야 하는 건 아냐 <br><br>
하루 정도는 행복하지 않아도 괜찮아<br>
그럼에도 역시 완벽하군 나의 여인 hmm<br>
여전히 무수한 빈칸들이 있지<br>
끝없이 헤맬 듯해<br>
풀리지 않는 얄미운 숙제들 사이로 oh<br><br>
마치 하루하루가<br>
잘 짜여진 장난 같아<br>
달릴수록 내게서 달아나<br><br>
Just life, we're still good without luck<br>
길을 잃어도 계속 또각또각 또 가볍게 걸어 (Take your time)<br>
There's no right 실은 모두가 울고 싶을지 몰라<br>
슬퍼지고 싶지 않아서 화내는지도 몰라<br><br>
여전히 무수한 질문들이 있지<br>
이번에도 틀린 듯해<br>
아주 사소한 토씨 하나의 차이로<br>
No- wo- ah<br><br>
마치 하루하루가<br>
삐뚤은 동그라미 같아<br>
도망쳐도 여기로 돌아와<br><br>
Just life, we're still good without luck<br>
비틀거려도 계속 또박또박 똑바르게 걸어 (Take your time)<br>
There's no right 때론 모두가 외로운지도 몰라<br>
지워지고 싶지 않아서 악쓰는지도 몰라<br>
I know that life is sometimes so mean<br>
(La-la-la-la la-la, I love my days)<br>
It is true, so I'm trying<br><br>
난 나의 보폭으로 갈게 hmm<br>
불안해 돌아보면서도<br>
별 큰일 없이 지나온 언제나처럼<br>
이번에도 그래 볼게 음<br><br>
Just life, we're still cool without sluck<br>
길을 잃어도 계속 또각또각 또 가볍게 걸어<br>
There's no right 실은 모두가 모르는지도 몰라<br>
어쩌면 나름대로 더디게 느림보 같은<br>
지금 이대로 괜찮은지도 몰라<br>
</center>
</body>
</html>
죄송합니다..
그리고 아래의 과정을 거쳐 S3에 올려줍니다.
- 버킷 생성하기 (나머지는 Default로)
2. 생성한 버킷으로 들어가 index.html 업로드하기
Cloudfront로 웹 어플리케이션 띄우기
AWS 콘솔에서 Cloudfront -> create로 들어가 다음과 같이 속성을 설정하여 cloudfront를 배포해줍니다. 설정하지 않아도 되는 값은 적지 않았습니다. (비워도 되거나 Default가 있는 값)
- Origin domain : 위에서 생성한 S3
- Name : 마음대로
- S3 bucket access : Yes use OAI
- Create new OAI (뒤에서 웹페이지가 아닌 xml로 이루어진 error가 떳다면 OAI를 다시 발급 받아줘야 한다)
- Yes, update the bucket policy
- Origin request policy : AllViewer
그 후 생성한 cloudfront에 들어가 Behaviors에서 Create Behavior를 클릭해줍니다. Behavior에 정의해준 값에 따라 client에서 coudfornt로 access할 수 있습니다. Behavior또한 아래 속성과 같이 설정해줍니다. 만약 미리 생성되있는 사람은 하지 않아도 됩니다.
- Origin and origin groups : 위에서 지정해준 S3 오리진
- Origin request policy - AllViewer
기다리면 배포가 완료될 때 까지 약 5분정도(더 기다려야 할 수 도 있다) 기다렸다가 Cloudfront도메인/index.html으로 들어가면 다음과 같이 창이 뜹니다.
AWS WAF 생성하기
AWS Console -> AWS WAF -> Web ACLs -> Create web ACL로 들어가 AWS WAF를 생성 해줍니다. 속성은 아래와 같이 따르면 됩니다.
리소스 타입 먼저 지정하고 시작하세요. (나중에 지정하면 모든 지정한 값들이 초기화 됩니다.)
- Resource type : CloudFront distributions
- Name : 마음대로
- CloudWatch metric name : Default는 Name과 같지만 A-Z, a-z, 0-9, - (hyphen), and _ (underscore) 만 들어가기에 꼼꼼히 살펴보고 안되는 게 있다면 바꾸자
- Associated AWS resources : 위에서 만든 cloudfornt 배포
- Rules - Add rules - Add my own rules and rule groups
- Name : 마음대로
- If a request : matches the statement
- Statement
- inspect : query string
- Match type : Contains SQL injection attacks
- Text transformation : URL decode Unicode
이렇게 WAF를 달아주고 테스트를 위해 sqlmap으로 트래픽을 보내보도록 하겠습니다.
아래와 같이 sqlmap을 다운받아줍니다.
wget {sqlmap 홈페이지 우측 tar.gz파일의 주소}
tar -zxvf master
echo "alias sqlmap='python3 설치한디렉터리/sqlmap-dev/sqlmap.py'" | tee -a /etc/bashrc
source {사용할 유저의 홈 디렉터리 path}/.bash_profile
source /root/.bash_profile
다운이 정상적으로 되었다면, 아래 명령어로 타겟을 설정하고 request를 날려주면
sqlmap -u "https://cloudfront dns 주소/index.html"
.
.
403 (Forbidden) - 1 times
다음과 같이 403에러가 뜨며 막힙니다.
그리고 WAF로 가보시면 다음과 같이 SQL injection 공격을 블록한 기록이 남아있습니다.
이렇게 AWS WAF를 사용하여 SQL injection을 방어해 보았습니다. 최근 클라우드 네이티브/하이브리드 환경이 늘어나면서 오히려 클라우드에 올라가는 리소스는 보안에 신경을 덜 쓰는 경우가 많아지는 것 같습니다. 그에 대비해 퍼블릭 클라우드 서비스들도 여러 보안 솔루션을 준비해두었고, 여러 회사들의 기술블로그에서도 심심치않게 보이는 주제니 각종 사례들과 함께 조금 더 재밌게 진행했습니다.