CEF 로그 포맷

CEF는 공통 이벤트 포맷 (Common Event Format)의 약어로, 아크사이트 등 ESM이나 SIEM 시스템과 연동할 목적으로 흔히 사용되는 규격입니다. 이 문서에서는 CEF 포맷의 세부사항을 다룹니다.

CEF 헤더 규격

CEF 포맷은 아래와 같이 구성됩니다.

Jan 18 11:07:53 호스트 CEF:버전|제조사|제품모델|제품버전|이벤트 클래스 ID|이벤트 이름|위험도|[확장]
  • 버전: CEF 포맷 자체의 버전을 의미합니다. 현재 유효한 값은 0 입니다.
  • 제조사: 로그를 전송하는 장치의 제조사를 의미합니다.
  • 제품모델: 로그를 전송하는 장치의 제품모델을 의미합니다. 제조사와 제품모델의 쌍으로 유일하게 해당 제품을 식별할 수 있어야 합니다.
  • 제품버전: 로그를 전송하는 장치의 버전을 의미합니다.
  • 이벤트 클래스 ID: 이벤트 유형별로 유일한 식별자입니다. 숫자일 수도 있고, 문자열일 수도 있습니다. 일반적으로 IPS의 시그니처 ID가 기입됩니다.
  • 이벤트 이름: 사람이 읽을 수 있는 형태의 이벤트 설명이 기록됩니다. 이 항목에는 IP나 포트처럼 특정한 정보는 포함하지 않고 이벤트 클래스 ID와 연결된 설명을 기록합니다.
  • 위험도: 이벤트 중요도를 문자열이나 숫자로 표현합니다. 문자열인 경우 유효한 값은 Unknown, Low, Medium, High, Veri-High 입니다. 숫자인 경우 유효한 값은 0~3 (Low), 4~6 (Medium), 7~8 (High), 9~10 (Very-High) 입니다.

CEF 확장

CEF 헤더 뒷부분은 키=값 쌍으로 기술됩니다. 각각의 키=값 쌍은 공백으로 구분되며, 순서에는 제약이 없습니다. CEF 확장 필드는 값의 타입에 따라 커스텀 필드의 이름이 결정됩니다. 예를 들면 다음과 같습니다.

  • cn1 (custom number 1): 정수 필드, cn3까지 지정 가능
  • cfp1 (custom floating point 1): 실수 필드, cfp4까지 지정 가능
  • cs1 (custom string 1): 문자열 필드, cs6까지 지정 가능
  • c6a1 (custom ipv6 address 1): IPv6 주소 필드, c6a4까지 지정 가능

각각의 커스텀 필드 값에 해당되는 필드 이름은 Label 접미사가 붙은 필드로 지정됩니다. 예를 들어, cn1 필드 값에 대한 필드 이름은 cn1Label 필드에 기록됩니다.

주로 사용되는 표준화된 확장 필드는 다음과 같습니다:

CEF 키전체 이름타입최대길이설명
externalIdexternalId문자열40원본 데이터 식별자 (Primary Key 등)
rtdeviceReceiptTime타임스탬프 이벤트를 수신한 시각, MMM dd yyyy HH:mm:ss 포맷이거나 1970년 1월 1일에서 시작하는 UNIX 타임스탬프 값
dvcdeviceAddressIPv4 주소 이벤트와 관련된 장치의 IPv4 주소
dvchostdeviceHostName문자열100이벤트와 관련된 장치의 호스트 이름
srcsourceAddressIPv4 주소 출발지 IPv4 주소
sptsourcePort정수0~65535 사이의 출발지 포트 번호
shostsourceHostName문자열1023출발지 호스트 이름
smacsourceMacAddressMAC 콜론으로 구분된 출발지 MAC 주소
dstdestinationAddressIPv4 주소 목적지 IPv4 주소
dptdestinationPort정수 0~65535 사이의 목적지 포트 번호
dhostdestinationHostName문자열1023목적지 호스트 이름
dmacdestinationMacAddressMAC 콜론으로 구분된 목적지 MAC 주소
msgmessage문자열1023멀티라인을 포함할 수 있는 상세 메시지

메세지 인코딩 규칙

메세지는 아래의 규칙으로 인코딩합니다.

  • 문자집합: 전체 메세지는 UTF-8로 인코딩합니다.
  • 파이프: 파이프(|) 문자는 헤더의 각 구성요소를 구분하는데 사용하므로, 값에 파이프 자체를 표현해야 하는 경우 백슬래시를 앞에 붙여서 이스케이프해야 합니다.
  • 백슬래시: 백슬래시() 문자는 이스케이프로 사용하므로, 값에 백슬래시 자체를 표현해야 하는 경우 백슬래시()를 앞에 하나 더 붙여야 합니다.
  • 등호: 등호(=) 문자는 CEF 메세지 확장 부분에서 키와 값을 구분하는 용도로 사용하므로, 값에 등호 자체를 표현해야 하는 경우 백슬래시()를 앞에 하나 더 붙여야 합니다. 단, 헤더 부분에서는 등호를 이스케이프하지 않습니다.
  • 개행: 멀티라인으로 구성된 필드는 개행을 \r이나 \n으로 표현합니다. 단, 개행은 확장의 값 표현에만 허용됩니다.

CEF 로그 예제

CEF를 사용하는 파이어아이 NX 시리즈의 로그 예시는 아래와 같습니다.

fenotify-20252856.warning: CEF:0|FireEye|CMS|7.8.1.468932|DM|domain-match|1|rt=Oct 19 2016 01:04:40 UTC src=172.20.1.23 
cn3Label=cncPort cn3=53 cn2Label=sid cn2=80448589 shost=dns.example.com proto=udp spt=23619 cs5Label=cncHost 
cs5=acme.com dvchost=EXAMPLE-NX2 dvc=192.168.10.11 smac=e4:c7:22:2a:c7:d2 cn1Label=vlan cn1=0 externalId=10352856 
cs4Label=link cs4=https://example.com/event_stream/events_for_bot?ev_id\=10352856 act=notified dmac=00:09:0f:09:1e:03 
cs1Label=sname cs1=Trojan.Gen.C.DNS 

참고 문헌

아래의 경로에서 원문 (영문)을 확인할 수 있습니다.

둘러보기

더보기

레지스트리 포렌식

레지스트리는 윈도우즈 운영체제와 응용프로그램에 관련된 방대한 설정과 운영 정보가 기록된 데이터베이스입니다. 윈도우즈 운영체제 초창기에는 INI 파일을 사용했으나, 레지스트리가 도입되면서 표준화된 계층적 데이터 구조, 다중 사용자 환경 지원, 접근 권한 제어, 바이너리 포맷 파일 기반의 효율적 I/O, 타입 시스템, 트랜잭션 등을 제공하게 되었습니다. 레지스트리를 분석하면 어떤 프로그램이나 서비스가 부팅 시 자동으로 실행되는지, 어떤 프로그램을 최근에 실행했는지, 어떤 프로그램을 얼마나 오래 사용했는지, 최근 어떤 파일을 검색했는지, 어떤 파일을 열어봤는지, 어느 서버에 접속했는지, 어떤 파일을 압축했는지 등 무수히 많은 정보를 추출할 수 있습니다. 따라서 레지스트리 분석은 사고 조사 초기에 수행해야 할 중요한 단계이며, 여기에서 확인된 정보에 따라 후속 조사의 진행이 결정될 수 있습니다. ## 레지스트리 하이브 파일 레지스트리 편집기(regedit)를 통해 하나로 보이는 레지스트리의 계층적 구조는 물리적으로 여러 개의 레지스트리 하이브 파일에 분산되어 있습니다. ![](/media/ko/2020-11-01-registry-forensic/reg-hive-files.png) `%SystemRoot%\System32\config` 디렉터리에는 아래와 같은 레지스트리 하이브 파일이 존재합니다. * SAM: HKEY_LOCAL_MACHINE\SAM * SECURITY: HKEY_LOCAL_MACHINE\Security * SOFTWARE: HKEY_LOCAL_MACHINE\Software * SYSTEM: HKEY_LOCAL_MACHINE\System 또한 각 사용자 계정의 디렉터리에는 NTUSER.DAT 레지스트리 하이브 파일이 존재합니다. ## HIVE 파일 구조 레지스트리 하이브 파일은 아래와 같이 구성되어 있습니다. ![](/media/ko/2020-11-01-registry-forensic/hive-structure.png) BASE 블록 구조 ![](/media/ko/2020-11-01-registry-forensic/hive-base-block.png) HIVE BIN 헤더 구조 ![](/media/ko/2020-11-01-registry-forensic/hive-bin-header.png) 로그프레소 포렌식의 hive-file 커맨드는 아래와 같은 필드를 출력합니다. ![](/media/ko/2020-11-01-registry-forensic/hive-file-command.png) * key: 키 * type: 타입 (문자열, 이진값, DWORD, QWORD 등) * name: 값 * value: 데이터 * last_written: 마지막 기록 시각 ## 코드게이트 포렌식 문제 연습 로그프레소 포렌식 솔루션은 쿼리를 기반으로 다양한 포렌식 아티팩트를 연관 분석하는 강력한 기능을 지원합니다. 아래에서는 이전 코드게이트 2011 컨퍼런스에서 레지스트리와 관련하여 출제된 문제를 어떻게 분석하는지 설명합니다. > we are investigating the military secret's leaking. we found traffic with leaking secrets while monitoring the network. Security team was sent to investigate, immediately. But, there was no one present. > It was found by forensics team that all the leaked secrets were completely deleted by wiping tool. And the team has found a leaked trace using potable device. Before long, the suspect was detained. But he denies allegations. > Now, the investigation is focused on potable device. The given files are acquired registry files from system. The estimated time of the incident is Mon, 21 February 2011 15:24:28(KST). > Find a trace of portable device used for the incident. > The Key : "Vendor name" + "volume name" + "serial number" (please write in capitals) * Codegate 2011 Forensic 300 문제 파일 제시된 파일의 압축을 풀면 6개의 레지스트리 하이브 파일을 확인할 수 있습니다. 먼저 시스템에 마운트된 장치 정보를 추출하기 위해 SYSTEM 하이브 파일에서 MountedDevices 키를 검색하면 아래와 같이 이진값으로 된 레지스트리 데이터를 확인할 수 있습니다. ```query hive-file codegate2011\system.bak | search key == "*MountedDevices" and name == "\\DosDevices*" ``` ![](/media/ko/2020-11-01-registry-forensic/codegate-step1.png) 이 데이터를 UTF-16으로 디코드하면 아래와 같은 문자열을 확인할 수 있습니다. ```query hive-file codegate2011\system.bak | search key == "*MountedDevices" and name == "\\DosDevices*" | eval value = substr(decode(value, "UTF-16LE"), 4) ``` ![](/media/ko/2020-11-01-registry-forensic/codegate-step2.png) USB 값만 필터링해서 정규식으로 파싱하면 제조사, 모델명, 버전, 시리얼을 추출할 수 있습니다. ```query hive-file codegate2011\system.bak | search key == "*MountedDevices" and name == "\\DosDevices*" | eval value = substr(decode(value, "UTF-16LE"), 4) | search value == "*USB*" | rex field=value "Ven_(?<vendor>[^&]+)&Prod_(?<product>[^&]+)&Rev_(?<version>[^#]+)#(?<serial>[^&]+)" | eval serial = lower(serial) | fields vendor, product, version, serial, value ``` ![](/media/ko/2020-11-01-registry-forensic/codegate-step3.png) 그러나 아직 볼륨 이름과 장치를 연결한 시간을 확인하지 못한 상태입니다. 장치를 연결한 시간은 HKLM\SYSTEM\ControlSet00X\Enum\USB\VID_####&PID_#### 키의 마지막 수정 시간을 확인하면 됩니다. 아래와 같이 쿼리하면 66개의 키를 확인할 수 있습니다. ```query hive-file codegate2011\system.bak | search key == "*USB\\VID_*" | eval serial = lower(valueof(split(key, "\\"), 5)) | stats max(last_written) as last_connect by serial ``` ![](/media/ko/2020-11-01-registry-forensic/codegate-step4.png) 볼륨 이름은 HKLM\SOFTWARE\Microsoft\Windows Portable Devices\Devices 키에서 확인할 수 있습니다. 아래와 같이 쿼리하면 40개의 키를 확인할 수 있습니다. ```query hive-file codegate2011\software.bak | search key == "*Windows Portable Devices*" and name == "FriendlyName" | rex field=key "&REV_[^#]+#(?<serial>[^&]+)" | eval serial = lower(serial) | stats first(value) as volume_name by serial ``` ![](/media/ko/2020-11-01-registry-forensic/codegate-step5.png) 이 3종의 쿼리 결과를 시리얼 번호로 조인하면 원하는 결과를 한 번에 추출할 수 있습니다. ```query hive-file codegate2011\system.bak | search key == "*MountedDevices*" | eval value = substr(decode(value, "UTF-16LE"), 4) | search value == "*USB*" | rex field=value "Ven_(?<vendor>[^&]+)&Prod_(?<product>[^&]+)&Rev_(?<version>[^#]+)#(?<serial>[^&]+)" | eval serial = lower(serial) | stats count by vendor, product, version, serial, value | join serial [ hive-file codegate2011\system.bak | search key == "*USB\\VID_*" | eval serial = lower(valueof(split(key, "\\"), 5)) | stats max(last_written) as last_connect by serial ] | join serial [ hive-file codegate2011\software.bak | search key == "*Windows Portable Devices*" and name == "FriendlyName" | rex field=key "&REV_[^#]+#(?<serial>[^&]+)" | eval serial = lower(serial) | stats first(value) as volume_name by serial ] | search last_connect >= date("2011-02-21", "yyyy-MM-dd") and last_connect <= date("2011-02-22", "yyyy-MM-dd") | order volume_name, vendor, product, version, serial, last_connect ``` ![](/media/ko/2020-11-01-registry-forensic/codegate-step6.png) 이처럼 로그프레소 쿼리를 이용하여 레지스트리 포렌식 데이터를 손쉽게 분석하고 가공할 수 있으며, 재사용 가능한 라이브러리로 구축할 수 있습니다.

2020-11-01

의사결정나무를 이용한 이상탐지

기계학습 분야에는 이상치(outlier)를 탐지하는 다양한 알고리즘이 제안되어 있지만, 알고리즘마다 특성이 있기 때문에 이를 잘 알아두어야 문제 풀이에 적합한 기계학습 알고리즘을 선택할 수 있습니다. 이번 절에서는 데이터 기반 의사결정에 광범위하게 사용되는 의사결정나무(Decision tree)를 이용하여 이상탐지를 수행하는 방법을 설명합니다. 이상치는 정상치에 비해 매우 다른 특징을 가진 데이터를 의미합니다. 일반적으로는 이상치를 찾기 위해 정상치를 학습하고, 정상치와 달라보이는 이상치를 추출합니다. 가장 쉽고 간단하게 생각할 수 있는 방법은 통계적으로 평균과 표준편차를 구해서, 이와 크게 벗어나는 값을 이상치로 취급하는 방법입니다. 여기서 더 나아가 다차원 데이터를 취급할 때는 군집 기반의 방법론을 주로 사용합니다. 아래의 도표는 LOF (Local Outlier Factor) 알고리즘이 군집에서 멀리 떨어진 값을 이상치로 계산한 예시입니다. ![](/media/ko/2017-08-22-anomaly-detection/lof.png) 이러한 기존 방법론의 가장 큰 문제는 1) 정상치를 모두 고려해야 하므로 계산 부하가 크다는 점, 2) 매번 정상치를 프로파일링해서 이상치를 계산하므로 모델을 생성하고 재활용하기 어렵다는 점입니다. Isolation Forest 기계학습 알고리즘은 기존 방법론과 다르게, 이상치 기준을 모델로 생성하는 방법론을 제시합니다. ## 공간분할 기반 이상탐지 아래의 그림은 2차원 데이터를 대상으로 Isolation Forest의 동작을 시각적으로 보여줍니다. ![](/media/ko/2017-08-22-anomaly-detection/isolation-forest.png) Isolation Forest 알고리즘은 랜덤하게 차원을 선택해서 임의의 기준으로 공간을 분할합니다. 군집 내부에 있는 정상치 Xi의 경우 공간 내에 한 점만 남기고 완전히 고립시키려면 많은 횟수의 공간 분할을 수행해야 하지만, 군집에서 멀리 떨어진 이상치 Xo는 적은 횟수의 공간 분할만으로 고립시킬 수 있습니다. 공간분할은 차원과 기준 값으로 표현할 수 있으므로, 여러 번의 공간분할은 의사결정나무 (Decision Tree) 형태로 표현할 수 있습니다. 정상치일수록 완전히 고립시킬 수 있을 때까지 의사결정나무를 깊숙하게 타고 내려가야 합니다. 반대로 이상치의 경우, 의사결정나무의 상단부만 타더라도 고립될 가능성이 높습니다. 이런 특성을 이용하면 의사결정나무를 몇 회 타고 내려가야 고립되는가를 기준으로 정상치와 이상치를 분리할 수 있습니다. ![](/media/ko/2017-08-22-anomaly-detection/isolation-forest-score-map.png) 이런 의사결정나무를 여러 개 모아서 앙상블 모델을 만들면 왼쪽 그래프처럼 안정적인 이상지수(score)를 산출할 수 있습니다. 논문에서는 약 50개에서 100개 정도의 의사결정나무를 이용하면 이상지수가 안정화된다는 점을 언급하고 있습니다. 오른쪽 그래프는 등고선 형태로 군집의 경계에 해당하는 점들은 0.5의 이상지수를 가진다는 사실을 보여주고 있습니다. 이상지수는 0~1 범위로 정규화되므로, 일반적으로 0.5보다 크고 1에 가까울수록 이상치로 정의할 수 있습니다. ## 이상탐지 수행 성능 Isolation Forest는 군집기반 이상탐지 알고리즘에 비해 월등한 실행 성능을 보입니다. 군집기반 이상탐지 알고리즘의 경우, 자기 자신을 제외한 나머지 모든 인스턴스에 대한 유클리디안 거리를 계산해야 하므로 O(N2)의 수행시간이 필요합니다. 반면, Isolation Forest는 일부 데이터를 샘플링하여 의사결정나무 모델을 생성하고 이를 이용하여 이상탐지를 수행하므로 O(logN)의 수행시간이면 충분합니다. 또 하나는 정확성에 대한 부분인데, 이상탐지 분야에서 해결하기 어려운 문제는 Swamping과 Masking이라 불리는 현상입니다. Swamping은 정상치가 이상치에 가까운 경우 이상치로 잘못 분류하게 되는 현상이고, Masking은 이상치가 군집화되어 있으면 정상치로 잘못 분류하게 되는 현상입니다. ![](/media/ko/2017-08-22-anomaly-detection/isolation-forest-sample.png) Isolation Forest는 전수 데이터를 이용하지 않고 일부 데이터만 샘플링해서 모델을 생성하기 때문에, 상대적으로 이런 오류에 강건한 특성을 가지게 됩니다. 위의 도표는 이상치 군집과 정상치 군집이 가까이 있을 때, 샘플링이 어떻게 이러한 문제를 극복하는지 시각적으로 보여주고 있습니다. ## 로그프레소의 활용 로그프레소에서는 기계학습을 쿼리로 수행할 수 있을 뿐 아니라, 스트림 쿼리에 이미 생성된 기계학습 모델을 배포(Deploy)하여 밀리초 이내의 실시간 이상탐지를 수행할 수 있도록 지원합니다. 예를 들어, 이상금융거래시스템(FDS)은 고객정보, 거래정보, 단말정보 등 다차원 데이터를 이용하여 이상탐지 모델을 생성하고 이를 기반으로 0.1초 이내에 실시간 탐지를 수행합니다. 아래는 실제 환경과 유사한 거래 데이터를 가상으로 생성하여 만든 모델링 데모입니다. 이 중에서 거래시각, 고객연령, 연속이체횟수 특성의 분포를 살펴보면 다음과 같습니다. ![](/media/ko/2017-08-22-anomaly-detection/fds-histogram.png) 거래시각은 0-86400초 범위의 값, 연령은 0-100 범위의 값, 연속이체횟수는 0-16 범위의 값을 가지고 있습니다. anomalies 쿼리를 사용하면 서브쿼리 결과를 이용하여 Isolation Forest 모델을 즉시 생성하고 이를 이용하여 스코어링을 실행할 수 있습니다. ```query table transaction | anomalies _time, age, cnt [ table transaction ] | eval category = if(_score >= 0.7, "outlier", "normal") ``` 3차원으로 시각화하면 아래와 같이 색상으로 분리된 정상 거래와 이상 거래를 확인할 수 있습니다. ![](/media/ko/2017-08-22-anomaly-detection/fds-3d-histogram.png) 위의 예시는 설명을 위해 극단적으로 단순화한 모델이며, 실제로는 수집 데이터 원본 뿐 아니라 CEP (Complex Event Processing) 기술을 통해 생성된 다양한 특성 값의 분포와 영향력을 비교하고 가공하는 과정을 거치게 됩니다. 기존의 룰/시나리오 기반 탐지 모델은 각각의 차원에 대해 임계치를 정의하고 조합했지만, 기계학습을 이용한 이상탐지는 다차원으로 데이터를 분석하고 경계면을 자동 생성함으로써 더 정교한 탐지를 수행할 수 있습니다. ## 레퍼런스 * Liu, Fei Tony, Ting, Kai Ming and Zhou, Zhi-Hua. "Isolation forest." Data Mining, 2008. ICDM'08. Eighth IEEE International Conference on Data Mining. * Liu, Fei Tony, Ting, Kai Ming and Zhou, Zhi-Hua. "Isolation-based anomaly detection." ACM Transactions on Knowledge Discovery from Data (TKDD) 6.1 (2012)

2017-08-22

Sysmon을 이용한 엔드포인트 포렌식

우리는 많은 비용과 노력을 들여 보안체계를 구축하지만, 임직원의 피싱 메일 첨부파일 실행과 같은 작은 부주의로도 공격자가 쉽게 내부로 침투할 수 있습니다. 방화벽이나 침입방지시스템 로그는 트래픽의 흐름과 알려진 네트워크 위협들을 가시적으로 보여주지만, 단지 방화벽 로그에 남아있는 IP와 포트만을 근거로 단말에서 어떤 프로세스가 어떻게 실행되어서 어떤 경로로 전파된 것인지 사후 추적하는 것은 불가능에 가깝습니다. 최근 몇 년 사이에 안티바이러스를 보완하는 EDR (Endpoint Detection & Response)이 빠르게 도입되고 있습니다. EDR은 단말에서 발생하는 모든 행위들을 중앙 서버에 기록하고 분석함으로써, 악성코드의 감염과 확산 경로를 효율적으로 탐지하고 추적할 수 있도록 지원합니다. 예전에는 수천 대의 단말마다 발생하는 수많은 프로세스의 실행, 네트워크 연결 기록들을 DB에서 관리하는게 불가능하다고 여겨졌지만, 발전된 빅데이터 기술이 이 모든 것을 가능하게 한 것입니다. EDR 솔루션을 도입할 수 있는 여건이라면 좋겠지만, 그렇지 않은 경우에도 마이크로소프트에서 배포하는 Sysmon을 이용해서 엔드포인트 보안 체계를 강화할 수 있습니다. Sysmon은 아래와 같은 시스템 행위들을 윈도우 이벤트 로그로 기록합니다. * 프로세스의 생성 및 종료 * 드라이버 로드 * 실행 이미지 로드 * 파일 생성 시각 변조 * 네트워크 연결 * CreateRemoteThread API 사용 * RawAccessRead API 사용 * Sysmon 서비스 상태 변경 아래에서는 로그프레소 센트리를 통해 Sysmon 이벤트를 수집한 예제를 하나씩 살펴보고, 이를 어떻게 외부의 위협 인텔리전스와 연동하여 탐지 및 분석할 수 있는지 알아봅니다. ## 프로세스 실행 분석 ```query table sysmon | fields _time, event_id, level, line ``` ![](/media/ko/2017-01-19-sysmon/sysmon-process-log.png) ``` Process Create: UtcTime: 2017-01-19 14:26:38.692 ProcessGuid: {9D15E6DA-CC9E-5880-0000-0010ECBA5E33} ProcessId: 12644 Image: C:\Program Files\Git\mingw64\bin\git.exe CommandLine: git.exe status -z -u CurrentDirectory: 작업디렉터리 User: 사용자이름 LogonGuid: {9D15E6DA-****-****-****-************} LogonId: 0xA2**** TerminalSessionId: 2 IntegrityLevel: Medium Hashes: SHA256=B388344FEB34B1CB4E7566D846C85587B843181999C05BA00C82FE208CA4909B ParentProcessGuid: {9D15E6DA-CC9E-5880-0000-001080B85E33} ParentProcessId: 19180 ParentImage: C:\Program Files\Git\cmd\git.exe ParentCommandLine: "C:\Program Files\Git\cmd\git.exe" status -z -u ``` 위의 스크린샷은 프로세스 생성 및 종료 시 남겨진 이벤트 로그의 예시입니다. 아래와 같이 쿼리를 사용해서 간단히 이벤트 메시지를 파싱할 수 있습니다. ```query table sysmon | search line == "*Process Create*" | eval line = substr(line, indexof(line, ":") + 3), line = replace(line, "\n", "`") | parsekv overlay=t pairdelim="`" kvdelim=": " | eval Hashes = substr(Hashes, indexof(Hashes, "SHA256=") + 7) ``` ![](/media/ko/2017-01-19-sysmon/sysmon-process-hash.png) 많은 프로세스 실행 기록이 남아있지만, SHA256 해시를 기준으로 통계내면 400개의 실행 이미지로 요약됩니다. ```query table sysmon | search line == "*Process Create*" | eval line = substr(line, indexof(line, ":") + 3), line = replace(line, "\n", "`") | parsekv overlay=t pairdelim="`" kvdelim=": " | eval Hashes = substr(Hashes, indexof(Hashes, "SHA256=") + 7) | stats count by Image, Hashes | sort -count ``` ![](/media/ko/2017-01-19-sysmon/sysmon-process-hash-stats.png) 초기 화이트리스팅 작업을 통해 정상 이미지는 배제하고, 바이러스토탈 등 외부 인텔리전스 서비스를 연동하면 효율적으로 악성코드를 진단할 수 있습니다. 만약 특정 바이너리가 악성코드로 진단된 경우, 원본 이벤트 로그에 아래와 같이 부모 프로세스에 대한 정보가 남아있으므로 충분히 감염 경로를 역추적 할 수 있습니다. ``` ParentProcessGuid: {9D15E6DA-CC9E-5880-0000-001080B85E33} ParentProcessId: 19180 ParentImage: C:\Program Files\Git\cmd\git.exe ParentCommandLine: "C:\Program Files\Git\cmd\git.exe" status -z -u ``` 같은 악성코드 해시가 여러 대의 시스템에서 발견된다면, 이벤트 로그를 시간순으로 정렬하여 어느 호스트로부터 악성코드가 전파되기 시작했는지 분석할 수 있습니다. ## 네트워크 연결 분석 네트워크 연결 이벤트는 프로세스 ID와 이미지 경로를 포함하여 정확하게 어느 프로세스가 어떤 호스트와 통신했는지 보여줍니다. ![](/media/ko/2017-01-19-sysmon/sysmon-connection-log.png) ``` Network connection detected: UtcTime: 2017-01-19 14:54:26.027 ProcessGuid: {9D15E6DA-483F-5876-0000-00105E39B000} ProcessId: 10336 Image: C:\Program Files (x86)\Google\Chrome\Application\chrome.exe User: 사용자명 Protocol: tcp Initiated: true SourceIsIpv6: false SourceIp: 172.20.XXX.XXX SourceHostname: 출발지호스트명 SourcePort: 53563 SourcePortName: DestinationIsIpv6: false DestinationIp: XXX.XXX.XXX.XXX DestinationHostname: DestinationPort: 80 DestinationPortName: http ``` 마찬가지로 아래와 같이 쿼리를 사용해서 간단히 이벤트 메시지를 파싱할 수 있습니다. ```query table sysmon | search line == "*Network connection detected*" | eval line = substr(line, indexof(line, ":") + 3), line = replace(line, "\n", "`") | parsekv overlay=t pairdelim="`" kvdelim=": " | fields _time, ProcessId, Image, Protocol, SourceIp, SourcePort, SourcePortName, DestinationIp, DestinationPort ``` ![](/media/ko/2017-01-19-sysmon/sysmon-connection-log-parsing.png) 이번에는 [맬웨어도메인리스트](https://www.malwaredomainlist.com/)와 연계하여 분석해보도록 하겠습니다. 데모를 위해 맬웨어도메인리스트에 등록된 악성 IP 중 하나에 일부러 접속해서 이벤트를 발생시켰습니다. ```query table sysmon | search line == "*Network connection detected*" | eval line = substr(line, indexof(line, ":") + 3), line = replace(line, "\n", "`") | parsekv overlay=t pairdelim="`" kvdelim=": " | join DestinationIp [ wget url="http://www.malwaredomainlist.com/hostslist/ip.txt" | eval ip = split(line, "\r\n") | fields ip | explode ip | rename ip as DestinationIp ] | fields _time, ProcessId, Image, Protocol, SourceIp, SourcePort, DestinationIp, DestinationPort ``` ![](/media/ko/2017-01-19-sysmon/sysmon-mdl-join.png) 위의 쿼리는 wget 커맨드를 사용해서 맬웨어도메인리스트의 IP 목록을 다운로드한 후 개행문자로 분리하여 즉석에서 IP 블랙리스트 데이터셋을 생성하고 이를 로컬의 윈도우 이벤트와 조인합니다. 위의 쿼리를 로그프레소의 스트림 쿼리로 설정하면, 외부 위협 인텔리전스를 이용하여 밀리초 단위의 실시간으로 탐지 및 경보할 수 있습니다. 위에 설명한 항목들 외에도 Sysmon은 유용한 이벤트 로그들을 생성하므로, 엔드포인트에 일괄 배포하여 이벤트 로그를 실시간으로 수집하고 탐지하면 엔터프라이즈 보안 및 분석 역량을 한단계 끌어올릴 수 있습니다.

2017-01-19