작은 메모장

28. SQL, Snort 결과 최적화 본문

실더스 루키즈 교육

28. SQL, Snort 결과 최적화

으앙내눈 2024. 1. 24. 16:46

기초 설정

최적화를 해보자

최적화를 위해 SQLyog로 새 테이블을 만든다.

 

만들었던 테이블에 기존에 만들었던 CSV 파일을 불러올 것이다.

불러올 파일은 기본적으로 제공받은 notPattern.log 파일을 사용할 것이다.

물론 log 파일을 불러올 것이지만, CSV 파일처럼 ,로 데이터가 구분되어있다.

때문에 필드 구분자를 ,로 다시 설정해줘야한다.

Fields terminated by 의 입력값을 ,로 바꾸고 데이터를 불러온다.

데이터를 정상적으로 불러온 모습을 볼 수 있다.


SQL 결과 최적화

Count

선택된 필드의 갯수를 세는 함수다. 정말 많이 쓰이는 함수.

이 캡처 데이터에서 Source IP의 갯수를 세어달라고 했다.

그 결과로 25840이라는 결과가 나왔다.

즉, 이 캡처 데이터에는 25840개의 패킷 캡쳐가 있다는 것이다.

 

Avg

선택된 필드의 평균을 계산하는 함수다. 보통 count 등과 연계하여 쓰는 편.

이 캡처 데이터에서 출발지 포트의 평균을 내어달라고 한 모습.

 

Distinct

선택된 필드의 중복을 제거하는 함수다. 정말 많이 쓰이는 함수.

이 캡처 데이터에서 Source IP의 중복을 제거해달라고 했다.

그 결과 ip의 중복이 제거된 모습

 

발생량 기반 룰

발생량 기반 룰이란, 서버와 클라이언트를 구분할 때 트래픽을 주고/받은 발생량을 기준으로 나누는 룰이다.

통상적으로 서버의 입장에서는 사용하는 IP와 포트가 제한되어 있다.

한 IP가 흔하게 사용하는 특정 포트만 집중적으로 사용한다면, 그것은 그 포트에 맞는 서비스를 사용하는 것이다.

그러나 여러 IP가 여러 포트를 규칙없이 사용한다면, 그것은 스캐닝 공격이라고 판단할 수 있을 것이다.

이런 식으로 들어온 트래픽의 발생량을 기반으로 룰을 짜는 것이 발생량 기반 룰이다.

 

다음 SQL 문을 보자.

select 문에 여러가지 조건이 case 문으로 붙었다.

조건은 간단하다. 포트가 1024가 넘어가는 포트는 대부분 랜덤 포트이므로, 이에 해당하는 포트는 그냥 랜덤포트임을 표시하는 조건이다.

이렇게 설정하고 SQL 문을 실행시키면, 어지러운 난수의 포트 번호가 아닌 하나로 통일된 깔끔한 포트 번호로 볼 수 있다.

이에 분석도 더 빨라질 수 있다는 것.

 

이 경우에는 각 포트로 들어온 트래픽의 양을 확인할 수 있다.

이 상태에서 뭔가 잘 안쓰이는 포트로 트래픽이 오고갔으면 이를 한번에 파악하기 쉽다.

 


Snort 결과 최적화

SQL Injection 탐지룰

SQL Injection은 SQL 문을 삽입하여 SQL 조건을 항상 참으로 만든 후, 원하는 SQL 데이터를 빼내는 공격이다.

결론적으로 공격자가 SQL 삽입 공격을 성공시키기 위해서는 2가지가 필요한데, and문과 항상 참인 조건문을 써야한다.

항상 참인 조건문은 입맛대로 바꿀 수 있기 때문에, SQL Injection을 막기 위해서는 and문을 막아야한다.

 

따라서 다음과 같은 Snort룰을 사용한다.

alert tcp any any -> any 80 (msg:”sql-injection-and”; content:”%20and%20”; nocase;)

여기서 눈여겨 볼 곳은 %20으로 되어 있는 부분이다.

and문을 사용하기 위해서는 반드시 띄어쓰기를 and 앞 뒤로 써야한다. SQL문 규칙이기 때문.

통상적으로 and문이 들어가는 곳은 where문으로, 비밀번호 필드의 검사 자체를 회피하려는 것이 목표다.

실제로 이 Snort룰이 동작하는지 확인해볼 것이다.

 


기본적으로 제공된 환경은 웹 서버가 동작하도록 제공된 os 환경이다.

때문에 이렇게 가상환경의 접근 주소로 진입하면 로그인 페이지가 나오는 것을 확인할 수 있다.

여길 통해서 SQL Injection을 시도할 것이다.

 

Snort 룰을 수정한다.

vim /etc/snort/rules/local.rules

또한, barnyard2 룰 또한 수정한다.

vim /etc/snort/sid-msg.map

 

그 후, barnyard와 Snort를 실행할 것이다. Snort는 제공받은 pcap 파일을 사용할 것이다.

 

Snort 결과를 확인한다.

룰 파일이 여러가지로 잡힌 모습을 확인했다. 이 정보는 DB에도 저장되었을테니, SQL을 사용하여 탐색해보자

select a.cid, a.timestamp, b.sig_name, inet_ntoa(c.ip_src), inet_ntoa(c.ip_dst), unhex(d.data_payload)
from event a, signature b, iphdr c, data d
where a.signature = b.sig_id
and a.sid = c.sid
and a.cid = c.cid

80개의 로그가 찍혀있는 것을 확인할 수 있다.

하지만 보기가 너무 불편하다. 최적화를 통해서 필요한 정보만 가져오자.

select unhex(replace(d.data_payload, '0D0A', '20'))
from event a, signature b, iphdr c, data d
where a.signature = b.sig_id
and a.sid = c.sid and a.cid = c.cid
and a.sid = d.sid and a.cid = d.cid
and b.sig_name = 'sql-injection-and'

원하는 데이터만 나온 듯 하다.

이제 이 모든 내용을 복사하여 편집기에서 확인해보자.

 

일단 우리가 원했던 %20and%20 패턴부터 찾아보자.

해당 패턴 앞뒤를 찾아보면, 1=1 같이 확실하게 SQL 삽입 공격을 한 것을 확인할 수 있다.

 

우리가 원하는 정보는 패킷의 태그값은 필요없고, URL 값만 필요하다.

따라서 패킷 인포 정보를 전부 삭제한다.

/http\/.*
:%s///

 

보기 편해지긴 했는데 아직도 패턴이 어디있는지는 모르겠다.

따라서 룰에 있는 %20and%20을 기준으로 나눌 것이다.

/%20and%20/
:%s//ㅎ&ㅎ/

이제 문자열 구분을 확실하게 할 수 있다.

이걸 기준으로 엑셀에서 표를 만들어 한눈에 파악한다.

데이터 > 텍스트 나누기를 통해 텍스트를 나눈다.

그럼 이렇게 데이터가 나뉜것을 확인할 수 있다.

 

여기서 또, 데이터 > 필터 기능을 사용하면 중복되는 데이터를 모아서 한눈에 볼 수 있다.

그럼 공격의 종류가 7가지임을 확인할 수 있다.

 

더 나아가서, 패턴 이후의 데이터를 바꿔보자.

%20은 띄어쓰기 " "이다.

이와같이 바꾸면 된다.

그럼 이렇게 패턴이 이쁘게 바뀐것을 확인할 수 있고

필터를 사용하여 쓸모없는 값을 제외하고 나머지 항목의 갯수를 세면 총 7개가 검증된 것을 확인할 수 있다.

즉, 80개 중에 7개만 정탐이고 나머지는 오탐이라는 것.

시그니처 기반 탐지가 이런 이유로 오탐이 생긴 것이다.

 

이에 룰 수정을 위해 정규표현식을 사용하여 7개의 룰만 탐지하도록 설정할 것이다.

/%20and%20((%27)?\w(%27)?%3d(%27)?\w|if%28)/

이렇게 설정하면 더욱 정교한 탐지 룰이 될 것이다.

이를 기반으로 룰을 수정하였다. %20and%20은 기존 룰에서 content로 이미 검사했으니,

끝에 R 옵션을 사용하여 검사가 끝난 시점에서 prce 적용을 하라고 설정한다.

또, 대소문자 구분을 하지 않는 i 옵션 또한 사용한다.

Snort를 다시 동작시키면 원하는 7개의 패킷만 탐지한 것을 확인할 수 있다.


이와는 반대로, 일반 사용자임이 확실한 경우의 패턴을 집어넣어 화이트리스트를 만드는 경우도 있다.

아래 경우를 보자.

필터를 node: 또는 task:로 시작하는 필터를 걸었다.

그랬더니 1992개의 레코드가 검출되었다.

대부분의 일반적인 사용자의 특징을 찾은 것이다.

 

그렇다면 Snort 룰은 어떻게 탐지할까?

... content:"+and+"; pcre:!"/(node|task):/i"; nocase;

이런식으로 !를 가장 앞에 두게 되면 조건이 반전이 되는 효과를 준다.

이걸 이용하여 화이트리스트 방식을 구현할 수 있다.


PCRE 룰 탐지

ASP 웹쉘을 탐지하는 것을 목표로 한다.

기본적으로 ASP 웹쉘을 탐지하는 문자열은 정해져있다.

이걸 기반으로 Snort 룰을 작성하면 다음과 같을 것이다.

alert tcp any any -> any 80 (content:"?Action="; nocase; pcre:"/\?Action\=(MainMenu|Show|Course|getTerminalInfo|ServerInfo|Cmd1?Shell| EditFile|Servu|sql|Search|UpFile|DbManager|proxy|toMdb)/i";)

이렇게 작성하면 완성된 룰일까? 조금 더 스마트한 방법으로 진행해보자.


제공받은 ASP 트래픽을 사용할 것이다.

 

ASP를 사용하고 있는 부분은 바로 저 부분으로, asp 뒤에 붙어 명령을 주는 것을 확인할 수 있다.

하지만 이렇게 asp가 없는 명령또한 존재하고 있으므로, 이에 유의하여 문자열을 필터링해본다.

 

/\.asp?action
:v//d

이렇게 하면 asp가 들어간 줄만 남기게 된다.

 

다음은 ASP 파일만 포함된 변수 영역을 추출해야한다.

/\v[^/.]+\.asp\?action\=\w+
:%s//ㅎ&ㅎ/

그럼 이렇게 구분자가 생긴다.

 

엑셀에 옮긴 후, 구분자를 통해 데이터를 나누었다.

우리가 필요한 것은 패턴이므로, 패턴을 제외한 나머지 부분을 없애준다.

또, 더욱 직관적이게 보기 위해서 ?를 기준으로 패턴을 다시 나눈다.

변수 앞의 Action또한 거슬리므로, 이 또한 지워준다.

그럼 이렇게 데이터가 깔끔하게 나온다.

 

하지만 아직까지도 한눈에 데이터가 보여지지 않는다.

남을 데이터를 더욱 보기 쉽게 만들고 싶다.

따라서 해당 테이블을 피벗 테이블로 만들 것이다.

필드 설정을 이렇게 하면 다음과 같은 결과가 나온다.

다른 asp는 사용하는 변수가 1~2개로 제한되어있는 반면,

shell.asp라는 ASP가 사용하는 변수가 상당히 많다.

즉, 특정 ASP에 이상하게만치 다양한 변수로 트래픽을 전송하고 있는 것.

따라서 shell.asp의 파일을 의심해볼 수 있다.

이 분석 결과에 맞게, 실제 shell.asp라는 파일이 실행되었던 화면이다.

 

그럼 어떻게 snort룰을 고쳤는가? 고친 룰은 아래와 같다.

alert tcp any any -> any 80 (content:“asp?Action="; nocase; http_uri; pcre:"/asp\?Action\=(MainMenu|Show|Course|getTerminalInfo|ServerInfo|Cmd1?Shell|EditFile|Servu|sql|Search|UpFile|DbManager|proxy|toMdb)/Ui";)

처음에 봤던 Snort 룰에 asp와 여러가지 옵션을 넣어 더욱 세부적인 룰을 구성한 것을 확인할 수 있다.

 

 

'실더스 루키즈 교육' 카테고리의 다른 글

30. Elastic  (0) 2024.01.30
29. Splunk  (0) 2024.01.25
27. PCRE  (0) 2024.01.23
26. Snort 룰  (0) 2024.01.23
25. Snort 기초 설정  (0) 2024.01.22