[SK shieldus Rookies 16기] 클라우드 기반 스마트 융합보안 과정
클라우드기반 시스템 운영 구축 실무 #07-08
[ Web 구조 이해 ] 포스팅 삽입
HTTP 네트워크 현황분석과 이상징후 분석
1) HTTP Log 실습환경 구성
2) HTTP 네트워크 현황분석
3) HTTP 이상징후
1) HTTP Log 실습환경 구성
❶ Index 만들기
❷ SourceType 지정
❸ 데이터 추가
# 검색 시작 초기 검색어
source="http.zip:*" host="ZeekHTTP" index="httplog" sourcetype="httplog"
2) HTTP 네트워크 현황 분석
• 내부 인트라넷 서비스/ 인터넷 기반 서비스도 대부분 HTTP로 동작
• HTTP를 분석 시 목적지가 인터넷인지 인트라넷 서비스인지 구분 필요
• 공격자가 내부망에 침투했다면 중요 데이터의 외부유출을 시도함
- 따라서 목적지가 인터넷으로 향하는 HTTP인지 아니면 기업 내부망으로 향하는지가 중요한 기준이 될 수 있음
< 분석 항목 >
❶ Top 10 접속 도메인 & 국가
❷ HTTP 메소드
❸ Top 10 클라이언트 오류
❹ Top 10 서버 오류
❺ HTTP 상태 코드
❶ Top 10 접속 도메인 & 국가
⦁ 사용자들이 가장 많이 접속하는 도메인을 추출해서 접속현황 분석
⦁ 특정 도메인과 국가로 많은 데이터가 전송되거나 낯선 국가명 등을 모니터링
⦁ 접속 국가 정보를 이상징후의 주요 항목으로 사용
index=httplog sourcetype=httplog domain!="(empty)"
| iplocation dst
| where NOT cidrmatch("0.0.0.0/0", domain)
| stats sum(request_body_len) as "Outbound", sum(response_body_len) as "Inbound" by domain, Country
| eval Outbound=round(Outbound/(1024*1024),2)
| eval Inbound=round(Inbound/(1024*1024),2)
| sort Outbound desc
| head 10
index=httplog sourcetype=httplog domain!="(empty)"
- httplog 중 도메인이 없는 것 제외
| iplocation dst
- 국가(Country) 정보를 iplocation 명령어로 검색
| where NOT cidrmatch("0.0.0.0/0", domain)
- 도메인이 IP 주소가 아닌 이벤트 검색 (IP이면 False)
| stats sum(request_body_len) as "Outbound", sum(response_body_len) as "Inbound" by domain, Country
- 외부로의 전송량을 더해 Outbound 필드에, 내부로의 전송량을 더해 Inbound 필드에 저장 (byte 단위)
- (회사 입장에서 요청은 outbound / 응답은 inbound이다)
| eval Outbound=round(Outbound/(1024*1024),2)
| eval Inbound=round(Inbound/(1024*1024),2)
- MB 단위로 변환, 소수점 2자리까지 표시
| sort Outbound desc
| head 10
- Outbound 역순으로, 10개 정렬
가장 많이 방문한 사이트 > 이벤트 보기
두 번째로 많이 방문한 사이트 > 이벤트 보기
희귀 방문 국가나 사이트도 관제 대상이 된다
❷ HTTP 메소드
⦁ 클라이언트가 서버에 자원을 요청하는 방식
⦁ 클라이언트는 서버에서 Get 또는 Post를 이용해서 자원 요청
⦁ HTTP 표준에서는 많은 메소드를 지원하지만 사용자가 많이 사용하지 않는 메소드는 공격자의 정보 수집 행위 등 정상적인 사용 범위가 아닐 수 있음
index=httplog sourcetype=httplog uri!="-"
| top method limit=10 showperc=f
- uri 필드 값이 없는 이벤트 제외
- 상위 10개의 메소드, 퍼센트 표기 x 검색
❸ Top 10 클라이언트 오류
⦁ 작업하는 도중 클라이언트 측 오류가 난 경우
index=httplog sourcetype=httplog uri!="-" uri!="/"
(status_code >=400 AND status_code < 500)
| top domain, status_code limit=10 showperc=f
- uri가 없거나 "/"인 경우 제외
* HTTP status code: 클라이언트가 요청한 내용을 서버에서 처리한 결과
- status_code가 400 이상, 500 미만인 이벤트 검색
- 도메인, 상태 코드 필드 기준 가장 많은 이벤트 Top 10 출력
❹ Top 10 서버 오류
index=httplog sourcetype=httplog uri!="-" status_code >= 500
| top domain, status_code limit=10 showperc=f
* 500:
* 502: proxy 자체의 문제
* 503: 리소스 문제
(상태코드 어느 포스팅 or pdf에 있는지 확인)
❺ HTTP 상태 코드
index=httplog sourcetype=httplog domain!="(empty)" status_code!="-"
| top limit=10 showperc=f status_code
3) HTTP 이상징후
❶ 비정상 메소드 사용
❷ 외부행 데이터 전송
❸ Mime-type과 파일 확장자 불일치
❹ 사이트 이동 후 실행파일 다운로드
❺ 프록시 서버 접속
❶ 비정상 메소드 사용
• Head, Delete, Trace, Option 과 같은 메소드가 네트워크에서 지속적으로 보인다는 것은 정상적인 사용자의 활동이라 보기 어렵다
• 송신지 IP를 기준으로 접속에 사용한 메소드의 종류별 사용 횟수 검색
index=httplog sourcetype=httplog
| stats count(method) by src
• 송신지 IP를 기준으로 options 메소드를 사용한 횟수 검색
index=httplog sourcetype=httplog
| stats count(eval(method=“OPTIONS”)) AS option_count by src
| where option_count > 10
| sort option_count desc
| stats count(eval(method=“OPTIONS”)) AS option_count by src
- OPTIONS: 열어놓은 메소드 체크
- OPTIONS 메소드 이벤트를 송신지 IP를 기준으로 개수를 세고 options_count 필드에 할당
| where option_count > 10
- option_count가 10개 이상인 송신지 IP를
| sort option_count desc
- option_count 기준 내림차순 정렬
•
index=httplog sourcetype=httplog
| where NOT match(method, "(GET|POST|-)")
| stats count(src) as src_count by method
| sort - src_count
❷ 외부행 데이터 전송
index=httplog sourcetype=httplog (request_body_len!=0 OR response_body_len!="0") domain!="-"
| stats sum(request_body_len) as outTotal sum(response_body_len) as inTotal by src, dst
| eval oMB=round(outTotal/(1024*1024),2)
| eval iMB=round(inTotal/(1024*1024),2)
| search oMB!=0 AND iMB!=0
| iplocation dst
| eval isUp=if((oMB/iMB)>1, "Yes","No")
| where isUp="Yes"
| table src,dst, iMB, oMB, Country, City
(request_body_len!=0 OR response_body_len!="0") domain!="-"
- 요청 본문이 있는 경우(POST, PUT) 검색
- 응답 본문이 있는 경우(200 OK) 검색
- 도메인이 없는 비정상 경우 제외
| stats sum(request_body_len) as outTotal sum(response_body_len) as inTotal by src, dst
- 송신지, 수신지 주소를 기준으로
- 요청 본문 길이 총량을 outTotal 필드
- 응답 본문 길이 총량을 inTotal 필드에 할당
| eval oMB=round(outTotal/(1024*1024),2)
| eval iMB=round(inTotal/(1024*1024),2)
- byte를 MB 단위로 변경하고 소수점 둘째자리까지 표기
- outTotal ➞ oMB / inTotal ➞ iMB 필드에 할당
| search oMB!=0 AND iMB!=0
-
| iplocation dst
-
| eval isUp=if((oMB/iMB)>1, "Yes","No")
-
| where isUp="Yes"
-
| table src,dst, iMB, oMB, Country, City
-
파일 업로드 데이터를 검색한다고 볼 수 있다?
❸ Mime-type과 파일 확장자 불일치
• 첨부된 파일의 내용과 확장자가 다른 것을 검색한다
index=httplog sourcetype=httplog resp_mime_types="application/x-dosexec" uri!="-"
| eval filename1=mvindex(split(uri,"/"),-1)
| eval filename=if(like(filename1,"%?%"), mvindex(split(filename1,"?"),0),filename1)
| eval filetype=if(match(filename,"(.exe|.bat|.ps1|.dll|.ocx)$"), "PE", "Not_PE")
| table domain, uri, filename, filetype, resp_mime_types
| where filetype=="Not_PE"
| dedup filename
resp_mime_types="application/x-dosexec" uri!="-"
- mime type(content type)이 dos 실행파일인 이벤트를 검색한다
- uri가 없는 경우 제외
| eval filename1=mvindex(split(uri,"/"),-1)
- uri를 "/"로 분할하고 마지막 요소를 새 filename1 필드에 할당
| eval filename=if(like(filename1,"%?%"), mvindex(split(filename1,"?"),0),filename1)
- filename1 필드가 "?"를 포함하면 filename1을 "?"로 분할해 첫 번째 요소를 filename 필드에 할당
- "?"를 포함하지 않으면 그대로 filename1에 할당한다
| eval filetype=if(match(filename,"(.exe|.bat|.ps1|.dll|.ocx)$"), "PE", "Not_PE")
- filename 필드가 “.exe”, “.bat”, “.ps1”, “.dll”, “.ocx” 중 하나로 끝나는지 확인하고
- 그렇다면 filetype 필드를 "PE"로 / 그렇지 않으면 "Not_PE"로 설정한다
| table domain, uri, filename, filetype, resp_mime_types
- domain, uri, filename, filetype, resp_mime_types 필드를 테이블로 표시한다
| where filetype=="Not_PE"
- filetype이 "Not_PE"인 이벤트만 필터링
| dedup filename
- filename 필드를 기준으로 중복 제거
mime type(≒content type): 브라우저가 body를 보고 인식한 type
filetype: 클라이언트가 파일 첨부 시 지정한 파일 확장자
➞ mime type이 x-dosexec(.exe)인데 확장자명은 다른 경우를 검색한다
❹ 사이트 이동 후 실행파일 다운로드
• 방문한 사이트에서 실행파일을 다운받았는지 확인
index=httplog sourcetype=httplog referrer!="-" status_code=200
| eval filename1=mvindex(split(uri,"/"),-1)
| eval filename=if(like(filename1,"%?%"), mvindex(split(filename1,"?"),0),filename1)
| where cidrmatch("0.0.0.0/0",domain)
| where match(resp_mime_types,"application/x-dosexec") OR match(filename,"(exe|dll|com|src)$")
| eval URL=domain+" :: " + filename
| stats count by src, URL
| stats list(URL) as Target list(count) as Source by src
referrer!="-" status_code=200
- 유입 경로(이전 페이지 URL)가 비어있지 않은 것
- 상태코드가 200인 = 성공한 응답 이벤트 검색
| eval filename1=mvindex(split(uri,"/"),-1)
- uri를 "/"로 분할하고 마지막 요소를 새 filename1 필드에 할당
* uri: 경유지를 통해 들어온 현재 사이트
| eval filename=if(like(filename1,"%?%"), mvindex(split(filename1,"?"),0),filename1)
- filename1 필드가 "?"를 포함하면 filename1을 "?"로 분할해 첫 번째 요소를 filename 필드에 할당
- "?"를 포함하지 않으면 그대로 filename1에 할당한다
| where cidrmatch("0.0.0.0/0",domain)
- 도메인이 IP주소 체계인 이벤트 검색
| where match(resp_mime_types,"application/x-dosexec") OR match(filename,"(exe|dll|com|src)$")
- mime type(content type)이 dos 실행파일이거나,
- filename이 “.exe”, “.dll”, “.com”, “.src” 중 하나로 끝나는 이벤트 검색
| eval URL=domain+" :: " + filename
- 새로운 필드 URL에 "domain :: filename" 형식의 내용 할당
| stats count by src, URL
- src와 URL 필드를 기준으로 이벤트 수 계산
| stats list(URL) as Target list(count) as Source by src
- 송신지 IP를 기준으로
- URL을 Target 필드에, 이벤트 수를 Source 필드에 리스트 형태로 할당
(필드명을 바꾸고 테이블로 출력하기 위함)
* DBD (Drive by Download) 공격
공격자는 유포지에 웹 쉘과 같은 악성 스크립트 파일을 삽입
보안이 취약한 사이트를 경유지로 설정, 중계지로 Redirect 되도록 걸어 놓는다
중계지가 없을수도, 여러 개일 수도 있다.
중계지가 많을수록 유포지(공격자)를 찾기 어렵다
이 공격에서 유포지와 중계지(경유지)가 존재하고,
uri는 유포지, referrer는 바로 이전 중계지(경유지)가 된다.
유포지: 기존 사이트를 이용하거나 공격자가 만든다(domain=ip주소)
* 도메인명을 등록하려면 자신을 드러내야 하므로, 공격자 자체 제작의 경우 ip주소가 도메인이다.
❺ 프록시 서버 접속
• Proxy Server
(ppt로 채우기)
다이렉트로 가는데 웹 Client에 proxy를 설치하는 경우
- 서버의 취약점이나 구조를 파악
•
index=httplog sourcetype=httplog (uri="http://*" OR method="connect")
| table src, domain, uri
- Client 자체 proxy를 통해 접속한 경우 또는 connect 메소드를 사용한 이벤트 검색
- 송신지IP, 접속한 도메인, uri 필드를 테이블로 출력
'SK shieldus Rookies > 클라우드 기반 시스템 운영ㆍ구축 실무' 카테고리의 다른 글
Splunk, Sysmon 실습 - End Point 로그 분석 (미완) (0) | 2024.01.12 |
---|---|
[SK shieldus Rookies 16기] Splunk 실습 - DNS Log 분석 (0) | 2024.01.11 |
SIEM - Splunk 실습(Splunk Enterprise) & 검색 명령어 (미완) (0) | 2024.01.10 |
[SK shieldus Rookies 16기] Zeek 환경 구성 (0) | 2024.01.09 |
Web 구조, HTTP 메시지 구조 (미완) (0) | 2024.01.09 |