[네트워크] 스노트(snort) content를 사용한 XSS 공격 탐지
- 네트워크
- 2020. 2. 6. 22:50
실습환경 설명
웹서버로 사용하기 위해 Ubuntu 16.04에 apache2, MySQL, PHP를 설치했고 XSS를 테스트할 목적으로 간단하게 'xss_test.php'와 'xss_test_server.php'를 넣어놓았다.
xss_test.php는 클라이언트가 입력값을 입력할 수 있는 폼 하나이고 이 폼에 입력한 값이 GET으로 서버에 넘어가면, xss_test_server.php에서 넘어온 값을 처리하는 형태이다.
- 웹서버: Ubuntu 16.04, 192.168.21.142
- XSS 공격 PC : Kali Linux, 192.168.21.139
XSS(Cross-Site Scripting) 공격이란
XSS는 Cross Site Scripting의 약자로, 가장 빈번하게 일어나는 웹해킹 공격 중 하나이다. 특이한 것은 웹서버를 공격하는 것이 목적이 아니라 해당 웹서비스를 이용하는 클라이언트를 공격한다는 점이다. 웹 카테고리가 아니므로 XSS 공격에 대해 자세히 다루지는 않겠지만 아래 아주아주 간단한 예제를 봐보자.
아래와 같이 웹서버의 xss_test.php 페이지를 사용하는 클라이언트는 Name 입력 폼에 넣은 입력값이 GET 형태로 서버에 넘어가고 XSS 취약점이 있다고 판단했다(XSS 공격시 입력하는 입력값에 대한 필터링이 없다고 판단).
그런 경우, 아래와 같이 입력 폼에 script를 삽입하는 형태로 XSS 공격을 수행할 수 있다.
혹은 Get으로 넘어가기 때문에 URL에 입력해주어도 상관없다. (URL에 입력해주는 경우 당연히 xss_test.php를 xss_test_server.php로 변경해주어야 겠죠?)
그럼, 아래와 같이 서버 코드에서 클라이언트가 넘겨준 <sciprt> 구문이 실행되면서 클라이언트에 'XSS Test'라는 alert 창이 뜨게 된다.
이게 왜 이렇게 되는지 정확히 알지는 못하고 쓰는 사람도 있을 수 있어 설명하자면 서버에서 사용자가 넘겨준 입력값을 처리하는 코드가 있기 때문이다.
즉, xss_test_server.php의 php 코드 중간에 $_GET['xss_test'] 변수가 사용되기 때문에 원래라면 그냥 정상적인 string 값이 넘어와 echo가 수행되어야 하지만 script 코드가 넘어왔기 때문에 서버가 클라이언트에 내려주는 코드에 script 코드가 삽입됐고 따라서 클라이언트 페이지에서 echo "Hello " 까지 실행되고 난 후에 <script> 구문이 실행된 것이다.
어쨌든, 위의 경우는 XSS가 어떤식으로 동작하는지 보여주는 단적인 예이고 시나리오를 그릴 수는 없다. 만약에 저 폼이 게시글이라고 생각하면 말이 달라진다. 공격자가 특정 게시판의 게시글 작성 폼이 스크립트 작성이 가능하다는 것을 알았고 script가 쓰인 게시글을 작성했다고 해보자. 그리고 만약에 다른 정상 사용자가 해당 게시글을 누르면? 서버는 해당 게시글에 작성되어 있는 script를 그대로 사용자에게 내려줄 것이고 공격자가 작성한 악성 script가 클라이언트 PC에 돌게 되는 것이다.
script로 할 수 있는 건 아주 다양하다. 세션값, 쿠키값을 탈취할 수도 있고 악성 프로그램을 다운받게끔 공격자의 서버 URL로 리다이렉트를 시킬 수도 있다.
잡설이 길었다! 오늘 포스팅의 목적은 snort의 content 옵션을 활용해보는 것이다.
snort content 옵션
snort의 content 옵션을 사용하면 패킷의 페이로드 내부 문자열을 검색할 수 있다. 검색 문자열은 단순 텍스트 데이터로 줄수도 있고 바이너리 데이터로 줄수도 있다. 바이너리 데이터일 경우는 '|'로 hex를 감싸주면 된다. 혹은 섞어 쓸수도 있다.
문자열인 경우 : "ABC";
hex 값인 경우 : "|AA BB CC|"
문자열 + hex 값인 경우 : "|AA BB|ABC|CC|"
content 옵션 사용에는 수많은 부가 옵션들이 따라온다.
offset : 패턴 매칭을 시작할 위치를 지정
depth : 패턴 매칭을 끝낼 위치를 지정
nocase : 대소문자 구분 없음을 명시
distance : content 옵션으로 매칭된 지점에서부터 상대적인 위치를 지정
http_header: HTTP header 부분에 대한 패턴 매칭 시도
http_client_body: HTTP body 부분에 대한 패턴 매칭 시도
http_cookie: HTTP cookie 부분에 대한 패턴 매칭 시도
http_method: HTTP method 부분에 대한 패턴 매칭 시도
http_uri: HTTP URI 부분에 대한 패턴 매칭 시도
여기서 http_~ 옵션들은 그냥 content 옵션 옆에 아래와 같이 기입만 해주면 된다.
content: "test"; http_header;
content: "test"; http_client_body;
content: "test"; http_cookie;
content: "test"; http_method;
content: "test"; http_uri;
XSS 공격 탐지를 위한 snort 룰 추가
Wireshark로 간단히 패킷 확인을 해보면 GET 요청으로 입력값이 넘어가는 것을 확인할 수 있다.
따라서, cotent와 nocase 옵션을 사용하여 아래와 같이 snort 룰을 작성할 수 있다. 물론 <sciprt> 같은 입력값을 필터링해놓치 않은 곳은 거의... 없을 것이다. 그냥 snort content 옵션을 사용해보기 위한 극단적 예로 생각해주기 바란다!
그런데 한가지 주의점은, 여기서 content에 <script>를 그대로 쓰면 안된다. "<"는 인코딩되어 넘어가기 때문에 '%3C'로 변한다. 이 부분은 hex값으로 써주도록 한다. (|25 33 43|)
그럼, 아래와 같이 snort 룰을 완성할 수 있다.
alert tcp any any -> 192.168.21.142 80
(msg:"XSS Detection";
content:"|25 33 43|script>";
nocase;
sid:1000003;)
위 룰을 아래와 같이 '/etc/snort/rules/local.rules'에 추가한다.
snort 실행 및 로그파일 확인
snort를 'snort -v -c /etc/snort/rules/local.rules'로 실행시킨 후 칼리리눅스 클라이언트 PC에서 XSS script를 폼에 전달해주면 snort log 파일에 'XSS Detection'로그가 남은 것을 볼 수 있다.
또한, snort 종료 후 'Action Stats'에서도 alert 수가 기록되었음을 확인할 수 있다.
관련포스팅
[네트워크] 스노트(snort) TCP SYN Flooding(DDoS) 공격 탐지
[네트워크] 스노트(snort) threshold를 사용한 nmap 포트스캐닝 탐지
[네트워크] 스노트(snort) 우분투(ubuntu) 설치 방법
[네트워크] 오픈소스 무료 IDS/IPS/방화벽/웹방화벽 추천
'네트워크' 카테고리의 다른 글
[네트워크] 프록시 서버란? 원리와 사용 목적 (0) | 2020.06.27 |
---|---|
[네트워크] 서브넷마스크 계산문제 풀이 (8) | 2020.05.26 |
[네트워크] 스노트(snort) TCP SYN Flooding(DDoS) 공격 탐지 (1) | 2020.02.04 |
[네트워크] 눈으로 확인해보는 Vmware Host-Only, Nat, Bridge 차이 (0) | 2020.02.01 |
[네트워크] 스노트(snort) threshold를 사용한 nmap 포트스캐닝 탐지 (0) | 2020.01.22 |