일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 암호화
- idps
- signatrue
- Suricata
- 재조합
- dsize
- IDS
- sinature
- Reassembly
- 시그니처
- chromium 탐지
- 미탐
- snort
- SSL
- HTTP2
- 크롬 탐지
- rule
- slowloris
- 오탐
- stream_size
- 탐지
- TLS
- header dos
- stream buffer
- chrome 탐지
- flowbits
- IPS
- 수리카타
- isdataat
- DDOS
- Today
- Total
linefilt
isdataat 본문
아래 글은 suricata 기준에서의 isdataat에 대한 동작 설명이다.
isdataat은 특정 위치(커서)에 페이로드 값의 존재 여부를 검증하는데 사용된다.
isdataat의 옵션으로 제공되는 relative는 마지막으로 매치된(룰 상에서 바로 좌측에 위치한) content로 부터 기준 하기 때문에 부분적인 길이를 매치하는데에도 사용할 수 있고 negate "!"를 통해서 페이로드가 존재하지 않은 경우에 대하여도 사용가능하다.
1. 페이로드의 길이 보장
관리자는 100바이트 크기를 가지는 Cookie 필드에 "userID=sysadmin" 라는 값이 있는 요청에 대하여 통계 내려고 할 때,
(Cookie 헤더는 가장 마지막에 위치한다고 간주) "userID=sysadmin" 값은 Cookie 필드 내에서 정확히 어디에 위치하는지는 알 수 없다.
alert tcp $HOME_NET any -> $EXTERNAL_NET 80 (msg:"sysadmin cookie"; flow:to_server,established; content:"Cookie|3a 20|"; http_raw_header; fast_pattern; content:"sysadmin"; header_raw_header; wihtin:100; )
그림 1. 100바이트 Cookie 필드
위 룰을 적용하였을때 관리자의 의도처럼 마지막 쯤에 위치한 Cookie 필드내에 sysadmin이라는 값이 포함되어 있는 요청을 검출할 수 있다.
그림 2. 100바이트 미만의 Cookie 필드
하지만 그림 2와 같은 패킷이 발생하였을때도 탐지된다.
두 번째 패킷의 차이점은 oc2token이라는 값이 없으며, Cookie 필드의 길이가 100바이트가 되지 않는다.
결국 두 번째 패킷은 원래 매치하고자 하였던 Cookie의 값 100바이트라는 기준이 있지만, 단순히 within만 사용되어서 오탐된 경우이다.
within은 지정한 값만큼의 범위안에 있으면 매치를 수행하지만, 특정 길이를 보장해주지는 않는다.
isdataat은 이와 같이 특정 길이를 보장하고 싶은 경우 사용하게 된다.
alert tcp any any -> any 80 (msg:"sysadmin cookie"; flow:to_server,established; content:"Cookie|3a 20|"; fast_pattern; isdataat:99,relative; content:"sysadmin"; wihtin:100; )
룰을 이와 같이 변경하게 되면, 의도하고자 했던 패킷에 대해서만 탐지하도록 동작한다.
2. negated를 통한 정확한 매치
isdataat에서는 negated(!)지원하기 때문에 원래의 의미와 반대로 특정 위치에 페이로드가 존재하지 않음을 지정해줄 수 있으며, 매우 유용하게 사용 할 수 있다.
-
버퍼 내 특정 문자열에 대한 검증
예를들어, 관리자는 네이버에가 소유한 사이트는 신뢰할 수 있기 때문에 TLS Handshakce 과정에서 SNI(Server Name Indicator)가 naver로 탐지되었을때 엔진에서 바로 통과할 수 있도록 룰을 아래와 같이 작성할 수 있는데 네이버와 같은 사이트는 도메인에 대해서 *.naver.com 처럼 Wildcard 형태로 가지고 있는 경우가 많다.
pass tcp $HOME_NET any ->$EXTERNAL_NET 443 (msg:"Naver"; tls_sni; content:".naver.com"; )
위와 같은 경우에는 www.naver.com, mail.naver.com과 같이 어떠한 주소가 앞에 나오더라도 매치를 해서 빠르게 통과시킬 수 있다.
만약에 정상적인 naver.com이 아니라 위조된 naver.com.com 이라는 사이트가 있을 경우 위 룰은 위조된 사이트 또한 pass 시켜버리는 문제를 가지고 있습니다.
이러한 경우를 방지하기 위해서는 정확한 매치가 필요하며, isdataat에서 negated 매치를 사용하여 제어가 가능하다.
pass tcp $HOME_NET any -> $EXTERNAL_NET 443 (msg:"Naver"; tls_sni; content:".naver.com"; isdataat:!1,relative; sid:1; rev:1;)
그림 3. isdataat relative negated 매치
그림 4. Client Hello 메시지
relative negated 매치는 매치된 문자열로 이후 부터(또는 이후 특정 위치) 페이로드가 존재하지 않음을 검증한다.
그러나 위 예에서 사용된 SNI 값은 그림 4에서 확인할 수 있듯이 페이로드내 위치하고 있으며, 그 이후에도 수 많은 페이로드가 존재한다.
룰에서 content:"naver.com" 앞에 tls_sni라는 sticky buffer이 사용되었다. 그렇기 때문에 tls_sni는 HTTP 정규화 모듈에 의해서 정규화가 진행되었고 Detection Engine에 의해 탐지될때는 그림 3과 같은 상태에서 탐지가 되기 때문에 이와 같은 사용이 가능하다.
-
마지막 문자열 매치
그림 5. Slowloris
그림 5는 slowhttptest를 사용하여 발생시킨 slowloris 패킷으로 HTTP 요청 메시지 중에서 0d0a0d0a가 없는 패킷을 탐지해서 slowloris 공격을 찾아낼 수 있다.
HTTP 메시지에는 헤더별로 구분하기 위해서 0d0a(\r\n)이 사용됩니다. 수 많은 0d0a중에서 마지막 0d0a를 찾기 위해서 isdataat의 negated 매치를 활용할 수 있다.
물론 offset이나 distance 등을 통해서도 매치는 가능하지만 HTTP 메시지는 길이는 가변적이기 때문에 사이즈를 유추하기는 매우 어려운 일이다.
alert tcp $EXTERNAL_NET any -> $HOME_NET 80 (msg:"slowloris"; content:"|0d 0a|"; isdataat:!1,relative; byte_test:2,!=,0x0d0a,-4,relative; )
위 룰은 0d0a를 탐색하는데 그 중에서도 0d0a 이후에 페이로드가 없는 것을 탐지하며, 탐지된 마지막 0d0a로부터 -4바이트 위치로 커서를 옮긴 이후에 다시 2바이트가 0d0a가 아닐 경우를 탐지한다.
3. 주의사항
-
패킷 페이로드 사이즈 매치
isdataat은 주로 relative 매치에서 사용되지만 단순히 페이로드의 전체 사이즈를 매치하는데에도 사용할 수 있다.
isdataat에서 사용할 수 있는 최대 값은 65,536입니다.
snort에서의 isdataat은 Per Packet 단위로 동작한다. 그렇기 때문에 MTU가 1500인 일반적인 환경에서는 주로 1400정도 까지의 페이로드 길이를 매치할 수 있다. 그러나 Suricata에서의 isdataat의 기본 동작은 Stream이다. 동일하게 MTU 1500인 환경에서 isdataat을 사용하더라도 Stream 이 종료될때 까지(룰에서 isdataat의 입력값은 /etc/suricata/suricata.yaml 내 chunk 사이즈를 기준 잡음) 누적되어 측정하기 때문에 단일 패킷의 페이로드 사이즈 뛰어 넘는 사이즈를 측정하게 된다.
그림 6. Stream에 대한 isdataat의 누적 매치
만약 Suricata에서 단일 패킷의 페이로드 사이즈를 측정하려는 경우에는 아래와 같이 no_stream 을 통해서 개별 패킷 기준임을 명시해주어야 한다.
alert tcp $HOME_NET any -> $EXTERNAL_NET any (msg:"Per Packet isdataat"; flow:to_server,established,no_stream; isdataat:500; )
-
Snort, Suricata 차이점
- 100바이트의 페이로드 사이즈를 매치하는 경우
Snort
alert tcp any any -> any 80 (msg:"100byte"; isdataat:99; )
Suricata
alert tcp $HOME_NET any -> $EXTERNAL_NET 80 (msg:"100byte"; flow:no_stream; isdataat:99; )
- content:"payload"로 부터 100바이트의 페이로드 사이즈가 존재하는 경우
Snort
alert tcp any any -> any 80 (msg:"relative 100byte"; content:"payload"; isdataat:99,relaitve; )
Suricata
alert tcp $HOME_NET any -> $EXTERNAL_NET 80 (msg:"100byte"; flow:no_stream; content:"payload"; isdataat:100,relative; )
'Keyword(Option)' 카테고리의 다른 글
새로운 키워드(옵션)의 필요 (streambtis) (0) | 2019.05.25 |
---|---|
threshold (0) | 2018.10.19 |