2024-03-29 05:35 (금)
[강명훈-Snort 분석 사례 연재①] WEB-MISC Checkpoint Firewall-1
상태바
[강명훈-Snort 분석 사례 연재①] WEB-MISC Checkpoint Firewall-1
  • 길민권
  • 승인 2015.11.26 09:54
이 기사를 공유합니다

HTTP parsing format string vulnerability attempt
오늘 살펴볼 Snort 룰은 다음과 같다.

 
해당 룰은 2004년 체크포인트 방화벽 'Firewall-1'에 존재했던 포맷 스트링 취약점(CVE-2004-0039) 공격을 탐지한다. 포맷 스트링 공격이란 무엇일까?

 
프로그래밍에 문외한이다 보니 설명을 봐도 이해는 잘 가지 않지만, 관련된 취약점 정보를 보면 공격자가 전송한 악의적 웹 요청에 의해 응답 에러가 발생하는 과정에서 포맷 스트링에 공격자가 전송한 임의 코드가 영향을 주는 공격인 듯하다.
 
"When Firewall-1 generates an error message in response to the invalid request,
a portion of the input supplied by the attacker is included in the format string for a call to sprintf()."

 
일단 해당 룰의 핵심 탐지패턴은 '3A2F(:/)'이다. 왜 해당 패턴을 탐지하려고 하는 걸까? 포맷 스트링 공격이 버퍼 오버플로우랑 유사 성격임을 감안했을 때, 아마도 쉘 실행을 위한 환경변수 패턴 탐지가 목적이 아닐까 싶다.

 
두 번째 궁금증. PCRE 옵션에 사용된 정규표현식 '^[^x3ax3f]{11,}'는 '3A(:)' 또는 '3F(?)'를 제외한 11개 이상의 문자열을 의미한다. 일단 '3A2F(:/)' 패턴이 왜 URI 영역의 시작 지점에서 최소 11byte 이후에 존재해야 하는지는 잘 모르겠다. (제보 바랍니다.)
 
그런데 3A(:)'와 '3F(?)'는 왜 그 영역에서 제외했을까? [그림3]의 정규표현식 '^.{11,}:'에서 수량자 '{11,}'는 메타문자 '.'의 검사 범위를 11개 이상으로 결정하며, 가능한 검사 범위를 최대한 검사하려는 특성에 의해 첫 번째 ':'이 있음에도 두 번째 ':', 즉 ':' 문자가 더는 존재하지 않음을 확인하고 나서야 검사를 중지한다.

 
그러나 '.'을 ':'을 제외한 임의 문자를 의미하는 '[^:]'으로 바꿔주면 ':'을 제외한 문자만을 검사해야 하기 때문에 첫 번째 ':' 문자를 만나자마자 검사는 중지된다. 검사 범위를 좁힐 수 있으며, 더 정밀한 검사가 가능해지는 것이다.

 
'3F(?)'는 왜 제외했을까? 해당 룰은 URI 영역만을 검사하는데, URI는 URL과 '?'로 구분되는 변수 영역으로 나뉜다. 이 때 '[^?]'와 같은 정규표현식을 사용하면 '?'를 제외한 임의 문자만을 검사하게 되며, '?' 문자를 만나면 역시 검사는 중지된다.

 
결과적으로 정규표현식 '^[^x3ax3f]{11,}'는  '3A(:)'나 '3F(?)' 패턴을 만나면 검사가 중지된다. 이유는 모르겠지만 해당 룰 개발자는 URI 영역 중, 변수 영역을 제외한 URL 영역에서만 '3A2F(:/)'로 끝나는 패턴을 검사하고자 한 듯하다.

 
이제 제대로 탐지했는지 로그를 확인해보자. 'HTTP/1.'으로 시작되는 문자열 삭제를 통해 URI 영역만을 추출한 후, 정규표현식 '^[^:?]{-11,}:/'로 검색을 해봤다. 가만 보니 탐지패턴이 없는 로그가 있다. 그런데 아예 없는 건 아니고, URL 인코딩된 '%3A(:)' 패턴 때문에 검색식과 일치하지 않을 뿐이다.

 
정규표현식을 수정해보자. ':/'의 URL 인코딩 수준이 복잡한 바람에 최종 사용된 정규표현식도 좀 복잡해졌다.


 
사실 그리 복잡한 정규표현식은 아닌데 VIM의 예외처리 구문()때문에 한없이 복잡해 보인다. 어떻게 하면 PCRE처럼 VIM에서도 정규표현식을 단순하게 사용할 수 있을까? 
이럴 때 사용할 수 있는 아주 유용한 기능이 VIM에 숨어 있다. 바로 이름도 멋진 '매직(Magic) 모드'. [그림9]처럼 정규표현식을 작성할 때 최초 'v' 구문을 붙여주면 VIM에서도 마치 마법처럼 PCRE 형식의 정규표현식 사용이 가능함을 알 수 있다.
 

참고로 URL 인코딩은 '%' 기호와 HEX 값을 합쳐서 URL에 문자를 표현하는 방식이며, (그래서 퍼센트 인코딩이라고도 함) 시스템마다 다른 문자열 해석으로 인한 오류를 막기 위해 사용하는 공통 표기 방식이라고 할 수 있다. 아스키코드 체계에서 문자 'A'에 대응하는 HEX 값은 '41'이므로 'A'를 URL 인코딩하면 '%41'이 되는 것.
 
':'의 HEX 값은 '3A'이므로 URL 인코딩하면 '%3A'가 된다. 그런데 이 '%'를 한 번 더 인코딩하면? '%'의 HEX 값은 '25'이므로 '%253A', 이런 식의 중복 인코딩이 가능한데, 해석 여부는 웹서버 종류 및 구현 방식에 따라 달라지며, 공격자가 IDS의 탐지패턴을 우회하기 위해서 이런 인코딩 방식을 악용할 때도 종종 있다.


 
결국 정규표현식 ':|%(25|2525){-}3a'는 ':', '%3A', '%253A', '%25253A' 패턴 모두를 검사한다. 이제 텍스트 정규화를 통해서 ':/' 패턴이 과연 쉘 환경변수로 사용됐는지 여부를 확인해보자.

 
탐지로그를 핵심 탐지패턴인 ':/'를 기준으로 텍스트 정규화한 결과는 다음과 같다. ':/' 패턴이 이중, 삼중으로 인코딩된 바람에 총 여섯 가지 패턴으로 표시되고 있음을 알 수 있다.

 
대충 봐도 대부분 'http://' 문자열의 일부라는 사실을 알 수 있지만, 더 명확한 근거 자료가 필요하다. '패턴'과 연결되는 '패턴 전' 열의 '끝 문자' 분포를 파악해보자.

 
참고로 필터 검색에 사용된 'http*'은 PCRE의 'http.*'과 같은 의미로 사용되는 (변형된) Windows 정규표현식이다.

 
'사용자 지정 자동 필터' 기능을 이용한 결과 핵심 탐지패턴 ':/'는 전부 'http', 'https' 또는 'resource' 문자열 이후에 발생한다는 사실이 확인되었다. 결국 핵심 탐지패턴인 ':/'는 쉘 환경변수가 아니라 URL 등을 이용한 경로 패턴의 일부라는 얘기. 전부 오탐이라는 뜻이다.
 

'패턴 전' 열을 '끝 문자' 기준으로 텍스트 정규화를 한 번 더 진행하면 패턴 발생 분포에 대한 더 세부적인 확인도 가능하다.


 
연재하는 분석 사례들이 다 그렇지만 이번 사례 역시 데이터만 잘 정리하면 분석은 그다지 어렵지 않다는 사실을 알려주고 있다. 다음 시간에는 확인된 패턴 발생 분포를 근거로 해당 룰의 오탐을 줄일 수 있는 방법을 찾아볼까 한다.
 
[글. 강명훈 <빅데이터 분석으로 살펴본 IDS와 보안관제의 완성> 저자 / kangmyounghun.blogspot.kr]
 
★정보보안 대표 미디어 데일리시큐!★
 
■ 보안 사건사고 제보 하기

▷ 이메일 : mkgil@dailysecu.com

▷ 제보 내용 : 보안 관련 어떤 내용이든 제보를 기다립니다!

▷ 광고문의 : jywoo@dailysecu.com

★정보보안 대표 미디어 데일리시큐 / Dailysecu, Korea's leading security media!★