2015년 6월 14일 일요일

Snort 분석(WEB-MISC weblogic/tomcat .jsp view source attempt - 2nd)

지난 글에서 'WEB-MISC weblogic/tomcat .jsp view source attempt' 룰에 의해 발생한 로그의 오탐 근거를 찾고, 룰 개선을 시도했었다. 하지만 데이터베이스 저장 오류(2개의 패킷이 하나로 저장?)로 인해 로그 분석이 여의치 않았었다. 상용 보안장비에서는 경험하기 힘든 오류라 당황스럽긴 하지만 그렇다고 분석을 안할 수는 없는 노릇. 방법을 찾아야 한다.

다행히 Snort는 로그를 발생시킨 원인 패킷을 같이 저장해주기 때문에 Wireshark를 이용해서 해당 패킷을 분석할 수 있었지만, 아무래도 로그 분석은 결국 텍스트 분석이다 보니 특정 패턴이 포함된 패킷을 알려줄 뿐, 해당 패턴의 위치를 표시해주지 못하는 Wireshark로는 정확한 분석이 힘들 수 밖에 없다. 가장 좋은 방법은 패킷에서 텍스트를 추출하는 것.



텍스트로 저장한 결과는 다음과 같다. 패킷과 패킷은 빈 행으로 구분되어 있음을 알 수 있다. 일단 HEX Byte 영역은 필요없으니 다 지워버리자.


  • '^.\{56}' 은 행의 첫번째 문자열부터 56개만을 검색해주는 VI 정규표현식

HEX Byte 영역을 지워놓고 보니 데이터를 16Byte 씩 표현하는 Wireshark 구조때문에 여전히 텍스트 분석이 여의치 않다. 연속되는 패턴 검색을 위해서는 동일 패킷에 해당하는 텍스트를 한 줄로 표시할 필요가 있다. 일단 패킷과 패킷을 구분해주는 빈 행에 'ㅋ' 문자를 채워 넣자. (그 이유는 잠시 후에)

  • '^'는 행의 첫번째 문자열, '$'는 마지막 문자열을 의미하는 정규표현식 Anchor 문자인데, '^$' 표현식에는 지정된 문자열이 없기 때문에 빈 행만을 검색해준다.

어떻게 하면 텍스트를 한 줄로 표시할 수 있을까? 눈에는 안보이지만 모든 행의 마지막엔 줄바꿈 문자가 위치한다. 윈도우 계열은 'CRLF(\r\n)', 리눅스 계열은 'LF(\n)'라는 줄바꿈 문자가 행의 끝에 위치한다는 것. 그럼 줄바꿈 문자를 없애버리면 줄 구분이 사라지겠네?



30,000 행이 안되는데 메모리가 부족하단다. (사용중인 노트북 메모리는 4GB) 이래서 엔지니어는 좋은 장비를 써야 한다! 일단 나눠서 작업을 해야할 듯.


'split'은 텍스트 파일을 원하는 단위로 잘라주는 도구이며, '-l 10000'은 10,000개 행(line) 단위로 자르라는 의미이다. 해당 명령어를 실행하면 로그 파일이 'xa'로 시작하는 3개의 파일로 분할됨을 알 수 있다.



'%s/\n//' 명령어를 실행하니 줄바꿈 문자가 삭제되면서 10,000개의 행이 하나로 합쳐졌다. 나머지 분할된 파일도 같은 작업을 반복한 후, 3개의 행을 가진 파일로 합친 다음(cat xa* >> snort.log.jsp_all_ascii.log), 줄바꿈 문자를 한번 더 삭제해주면 결국 전체 패킷 텍스트 데이터가 하나로 합쳐진다.


이제 하나의 행으로 합쳐진 텍스트를 다시 패킷 단위로 구분해야 한다. 작업을 시작할 때 패킷을 구분해주던 빈 행에 'ㅋ' 문자를 채워 넣었음을 기억할 것이다. 'ㅋ' 문자를 줄바꿈 문자 'CarriageReturn'을 의미하는 '\r'로 바꿔주면 텍스트를 패킷 단위로 구분할 수 있다. ('LineFeed'를 의미하는 '\n'으로 바꾸면 행 구분이 안됨)

  • '%s//\r/g' 명령어에서 'g(global)' 옵션을 사용한 이유는 매칭되는 모든 문자열을 치환해야 하기 때문이다. ('g' 옵션이 없으면 첫번째 매칭된 문자열만 치환)

해당 로그를 발생시킨 룰은 URI 영역을 검사하므로 당연히 모든 패킷은 웹 요청 트래픽이다. 그런데 웹 요청을 의미하는 GET 메소드 전에 의미를 알 수 없는 문자열들이 표시되고 있다. 패킷 헤더(MAC, IP, TCP 등)가 Ascii 문자로 디코딩된 경우인데 분석에 불필요하다. URI를 제외한 나머지 영역 역시 다 필요없다. 지워버리자.


  • '%s/치환 전 패턴/치환 후 패턴/' 명령어를 이용해서 각각 '%s/^.\{-}get\(\s\/\)\@=//', '%s/http\/1.*//' 명령어를 실행하면 된다. 

문자열 치환 작업 시,
1. 먼저 치환을 원하는 패턴을 검색한 후, 검색 표현식에 문제가 없으면 
2. 해당 검색 표현식을 치환 명령어의 '치환 전 패턴' 영역에 다시 사용하는 과정을 거치는데, 

검색 표현식이 길어질수록 다시 입력하는 과정이 한없이 귀찮을 수가 있다.^^; 이럴 때는 검색 모드('/' 입력)에서 'CTRL+F' 키를 입력하면 사용했던 검색 표현식 리스트를 불러올 수 있다. (물론 복사도 가능)


이제 탐지로그의 발생현황을 파악해보자. '.jsp'가 필수 탐지패턴이므로 해당 패턴을 기준으로 텍스트 정규화를 실시해보자.

  • VI 정규표현식은 예외처리할 게 많아서 복잡하다. 그냥 pcre 지원하면 얼마나 좋을까? 참고로 VI에서는 '()' 그룹을 9개까지만 지원하는 듯 하다.
vim : \(\.\|%\(25\)\{-}2e\)\(j\|%\(25\)\{-}6a\)\(s\|%\(25\)\{-}73\)\(p\|%\(25\)\{-}70\)
pcre: (\.|%(25)?2e)(j|%(25)?6a)(s|%(25)?73)(p|%(25)?70)
pcre 구조 : '.jsp' 및 소문자와 대응하는 URL 인코딩 패턴을 OR 조건 검색


구분기호 'ㅋ'을 기준으로 텍스트 정규화를 진행한 결과는 다음과 같다. URL 인코딩된 패턴(.js%2570)이 있는데 모두 룰 테스트 과정에서 발생한 것으로 실제 공격 시도는 없었다.



해당 로그를 발생시킨 룰은 'pcre:!"/^\w+\s+[^\n\s\?]*\.jsp/smi";' 옵션에 의해 '.jsp' 문자열 전에 '?' 문자열이 없는 패턴을 검사해서 탐지에서 제외(!)한다. 즉 해당 룰이 제대로 동작했다면 '패턴 전' 영역에는 '?' 문자열이 존재해야 한다.

  • 엑셀은 '?'를 특수문자로 인식하기 때문에 '~'를 이용해서 예외처리


(지난 글에서 이미 확인했듯이) '패턴 전' 영역에 '?' 문자열이 존재한다는 얘기는 JSP 파일이 변수로 사용되었다는 뜻이며, 해당 변수를 처리하는 (최종 요청된) 파일은 모두 JSP가 아니다. 즉 '패턴 전' 영역에 '?' 문자열이 존재하는 로그는 룰 의도와는 일치하지만 공격은 아니다. (룰에 문제가 있다는 뜻)

해당 룰은 다음 그림처럼 '패턴 전' 영역에 '?' 문자열이 없는, 즉 JSP 파일에 대한 웹 요청을 탐지할 수 있도록, 그리고 결정적으로 JSP 파일 확장자의 인코딩 여부를 검사할 수 있도록 수정이 필요함을 알 수 있다.


이 결론을 내보겠다고 데이터를 수도 없이 뜯어고쳐야만 했다. 보통 '분석' 하면 해킹만 잘하면, 취약점이나 공격 코드 등의 지식만 있으면 잘 할 수 있을 것으로 생각하기 쉽지만 현실은 로그 등의 원천 데이터를 모으고, 정합성을 맞추고, '분석'에 적합한 형태로 가공하는, 지루하고 반복적인 과정을 거쳐야만 비로소 '분석'을 시도해볼 수 있게 된다.  

빅데이터가 유행하면서 '데이터는 21세기 원유'라는 말까지 등장했다. 휘발유를 추출하기 위해 온갖 화학처리를 하기 전까지, 원유는 쓸모 없는 물질에 불과하다. 그렇기 때문에 원유를 용도별로 처리하는 과정은 매우 중요하며, '분석'의 기초와 토대가 되는 데이터 처리 과정 역시 마찬가지라고 할 수 있다.

이런 과정이 단순 노가다(?) 취급을 받기 시작하면 제대로된 '분석'은 영원히 기대하기 어렵지 않을까?

댓글 없음:

댓글 쓰기

크리에이티브 커먼즈 라이선스