jq के साथ Hayabusa परिणामों का विश्लेषण¶
लेखक¶
Zach Mathis (@yamatosecurity) - 2023/03/22
परिचय¶
लॉग में महत्वपूर्ण फ़ील्ड्स की पहचान करना, उन्हें निकालना और उनके विरुद्ध मेट्रिक्स बनाना DFIR और थ्रेट हंटिंग विश्लेषकों के लिए एक आवश्यक कौशल है।
Hayabusa परिणाम आमतौर पर .csv फ़ाइलों में सहेजे जाते हैं ताकि उन्हें टाइमलाइन विश्लेषण के लिए Excel या Timeline Explorer जैसे प्रोग्राम में आयात किया जा सके।
हालाँकि, जब एक ही प्रकार की सैकड़ों या उससे अधिक घटनाएँ होती हैं, तो उन्हें मैन्युअल रूप से जाँचना अव्यावहारिक या असंभव हो जाता है।
ऐसी स्थितियों में, विश्लेषक आमतौर पर समान प्रकार के डेटा को क्रमबद्ध और गिनकर असामान्य मामलों (outliers) की तलाश करते हैं।
इसे long tail analysis, stack ranking, frequency analysis आदि के रूप में भी जाना जाता है।
इसे Hayabusa के साथ परिणामों को .json या .jsonl फ़ाइलों में आउटपुट करके और फिर jq के साथ विश्लेषण करके पूरा किया जा सकता है।
उदाहरण के लिए, एक विश्लेषक किसी संगठन के सभी वर्कस्टेशनों पर इंस्टॉल की गई सेवाओं की तुलना कर सकता है। हालाँकि यह संभव है कि कोई विशेष मैलवेयर हर वर्कस्टेशन पर इंस्टॉल हो जाए, लेकिन इसकी अधिक संभावना है कि यह केवल कुछ ही सिस्टमों पर मौजूद होगा। इस मामले में, जो सेवाएँ सभी सिस्टमों पर इंस्टॉल हैं वे सौम्य (benign) होने की अधिक संभावना रखती हैं, जबकि दुर्लभ सेवाएँ अधिक संदिग्ध होती हैं और इन्हें समय-समय पर जाँचा जाना चाहिए।
एक अन्य उपयोग का मामला यह है कि किसी चीज़ की संदिग्धता निर्धारित करने में मदद मिले।
उदाहरण के लिए, एक विश्लेषक 4625 विफल लॉगऑन लॉग का विश्लेषण कर सकता है ताकि यह निर्धारित किया जा सके कि किसी विशेष IP पते ने कितनी बार लॉगऑन करने में विफल रहा।
यदि केवल कुछ ही विफल लॉगऑन थे, तो यह संभावना है कि एक प्रशासक ने बस अपना पासवर्ड गलत टाइप कर दिया।
हालाँकि, यदि किसी विशेष IP पते द्वारा थोड़े समय में सैकड़ों या उससे अधिक विफल लॉगऑन थे, तो यह संभावना है कि वह IP पता दुर्भावनापूर्ण है।
jq का उपयोग करना सीखना आपको न केवल Windows इवेंट लॉग का विश्लेषण करने में, बल्कि सभी JSON स्वरूपित लॉग का विश्लेषण करने में महारत हासिल करने में मदद करेगा।
अब जब JSON एक बहुत लोकप्रिय लॉग प्रारूप बन गया है और अधिकांश क्लाउड प्रदाता अपने लॉग के लिए इसका उपयोग करते हैं, तो उन्हें jq के साथ पार्स करने में सक्षम होना आधुनिक सुरक्षा विश्लेषक के लिए एक आवश्यक कौशल बन गया है।
इस मार्गदर्शिका में, मैं पहले उन लोगों के लिए jq का उपयोग करना समझाऊँगा जिन्होंने इसे पहले कभी उपयोग नहीं किया है और फिर वास्तविक दुनिया के उदाहरणों के साथ अधिक जटिल उपयोगों को समझाऊँगा।
मैं jq को sort, uniq, grep, sed आदि जैसे अन्य उपयोगी कमांड के साथ संयोजित करने में सक्षम होने के लिए linux, macOS या Windows पर linux का उपयोग करने की अनुशंसा करता हूँ।
jq इंस्टॉल करना¶
कृपया https://stedolan.github.io/jq/ देखें और jq कमांड इंस्टॉल करें।
JSON प्रारूप के बारे में¶
JSON लॉग कर्ली ब्रैकेट्स { } में निहित ऑब्जेक्ट्स की एक सूची है।
इन ऑब्जेक्ट्स के अंदर कोलन द्वारा अलग किए गए key-value युग्म होते हैं।
keys स्ट्रिंग होनी चाहिए, लेकिन values निम्नलिखित में से एक हो सकते हैं:
* string (उदा.: "string")
* number (उदा.: 10)
* अन्य ऑब्जेक्ट (उदा.: { xxxx })
* array (उदा.: ["string", 10])
* boolean (उदा.: true, false)
* null
आप ऑब्जेक्ट्स के अंदर जितने चाहें उतने ऑब्जेक्ट नेस्ट कर सकते हैं।
इस उदाहरण में, Details एक रूट ऑब्जेक्ट के अंदर एक नेस्टेड ऑब्जेक्ट है:
{
"Timestamp": "2016-08-19 08:06:57.658 +09:00",
"Computer": "IE10Win7",
"Channel": "Sec",
"EventID": 4688,
"Level": "info",
"RecordID": 6845,
"RuleTitle": "Proc Exec",
"Details": {
"CmdLine": "C:\\Windows\\system32\\ipconfig /release",
"Path": "C:\\Windows\\System32\\ipconfig.exe",
"PID": "0xcf4",
"User": "IE10WIN7$",
"LID": "0x3e7"
}
}
Hayabusa के साथ JSON और JSONL प्रारूपों के बारे में¶
पुराने संस्करणों में, Hayabusa सभी { xxx } लॉग ऑब्जेक्ट्स को एक विशाल array में रखने के पारंपरिक JSON प्रारूप का उपयोग करता था।
उदाहरण:
[
{
"Timestamp": "2016-08-19 08:06:57.658 +09:00",
"Computer": "IE10Win7",
"Channel": "Sec",
"EventID": 4688,
"Level": "info",
"RecordID": 6845,
"RuleTitle": "Proc Exec",
"Details": {
"CmdLine": "C:\\Windows\\system32\\ipconfig /release",
"Path": "C:\\Windows\\System32\\ipconfig.exe",
"PID": "0xcf4",
"User": "IE10WIN7$",
"LID": "0x3e7"
}
},
{
"Timestamp": "2016-08-19 11:07:47.489 +09:00",
"Computer": "IE10Win7",
"Channel": "Sec",
"EventID": 4688,
"Level": "info",
"RecordID": 6847,
"RuleTitle": "Proc Exec",
"Details": {
"CmdLine": "taskhost.exe $(Arg0)",
"Path": "C:\\Windows\\System32\\taskhost.exe",
"PID": "0x228",
"User": "IE10WIN7$",
"LID": "0x3e7"
}
}
]
इसके साथ दो समस्याएँ हैं।
पहला मुद्दा यह है कि jq क्वेरीज़ अधिक बोझिल हो जाएँगी क्योंकि हर चीज़ को उस array में देखने के लिए एक अतिरिक्त .[] से शुरू होना होगा।
इससे बहुत बड़ा मुद्दा यह है कि ऐसे लॉग को पार्स करने के लिए, पहले array में सारा डेटा लोड करना आवश्यक होता है।
यह एक समस्या बन जाती है यदि आपके पास बहुत बड़ी JSON फ़ाइलें हैं और मेमोरी की प्रचुरता नहीं है।
आवश्यक CPU और मेमोरी उपयोग को कम करने के लिए, JSONL (JSON Lines) प्रारूप, जो हर चीज़ को एक विशाल array में नहीं रखता, अधिक लोकप्रिय हो गया है।
Hayabusa JSON और JSONL प्रारूपों में आउटपुट करता है, हालाँकि JSON प्रारूप अब किसी array के अंदर सहेजा नहीं जाता है।
एकमात्र अंतर यह है कि JSON प्रारूप टेक्स्ट एडिटर या कंसोल पर पढ़ने में आसान है, जबकि JSONL प्रारूप हर JSON ऑब्जेक्ट को एक ही पंक्ति में संग्रहीत करता है।
JSONL प्रारूप थोड़ा तेज़ और आकार में छोटा होगा इसलिए यह आदर्श है यदि आप केवल लॉग को SIEM आदि में आयात करने जा रहे हैं... लेकिन उन्हें देखने नहीं जा रहे हैं।
JSON प्रारूप आदर्श है यदि आप कुछ मैन्युअल जाँच भी करने जा रहे हैं।
JSON परिणाम फ़ाइलें बनाना¶
Hayabusa के वर्तमान 2.x संस्करण में, आप परिणामों को JSON में hayabusa json-timeline -d <directory> -o results.json के साथ या JSONL प्रारूप के लिए hayabusa json-timeline -d <directory> -J -o results.jsonl के साथ सहेज सकते हैं।
Hayabusa डिफ़ॉल्ट standard प्रोफ़ाइल का उपयोग करेगा और विश्लेषण के लिए केवल न्यूनतम मात्रा में डेटा Details ऑब्जेक्ट में सहेजेगा।
यदि आप .evtx लॉग में सभी मूल फ़ील्ड जानकारी सहेजना चाहते हैं, तो आप --profile all-field-info विकल्प के साथ all-field-info प्रोफ़ाइल का उपयोग कर सकते हैं।
यह सभी फ़ील्ड जानकारी को AllFieldInfo ऑब्जेक्ट में सहेजेगा।
यदि आप एहतियात के तौर पर Details और AllFieldInfo दोनों ऑब्जेक्ट सहेजना चाहते हैं, तो आप super-verbose प्रोफ़ाइल का उपयोग कर सकते हैं।
AllFieldInfo के बजाय Details का उपयोग करने के लाभ¶
AllFieldInfo के बजाय Details का उपयोग करने का पहला लाभ यह है कि केवल महत्वपूर्ण फ़ील्ड सहेजे जाते हैं, और फ़ाइल स्थान बचाने के लिए फ़ील्ड नामों को छोटा कर दिया गया है।
नकारात्मक पक्ष यह है कि ऐसे डेटा के छूटने की संभावना है जिसकी आपको वास्तव में परवाह थी लेकिन वह छूट गया।
दूसरा लाभ यह है कि Hayabusa फ़ील्ड नामों को सामान्यीकृत करके फ़ील्ड को अधिक एकसमान तरीके से सहेजेगा।
उदाहरण के लिए, मूल Windows लॉग में, उपयोगकर्ता नाम आमतौर पर SubjectUserName या TargetUserName फ़ील्ड में होता है।
हालाँकि, कभी-कभी उपयोगकर्ता नाम AccountName फ़ील्ड में होगा, कभी-कभी लक्ष्य उपयोगकर्ता वास्तव में SubjectUserName फ़ील्ड में होगा, आदि...
दुर्भाग्य से, Windows इवेंट लॉग में कई असंगत फ़ील्ड नाम हैं।
Hayabusa इन फ़ील्ड्स को सामान्यीकृत करने की कोशिश करता है, ताकि एक विश्लेषक को केवल एक सामान्य नाम पार्स करना पड़े बजाय Windows में इवेंट ID के बीच की अनंत मात्रा में विशिष्टताओं और विसंगतियों को समझने के।
यहाँ उपयोगकर्ता फ़ील्ड का एक उदाहरण है।
Hayabusa SubjectUserName, TargetUserName, AccountName आदि को निम्नलिखित तरीके से सामान्यीकृत करेगा:
* SrcUser (Source User): जब कोई क्रिया किसी उपयोगकर्ता से होती है। (आमतौर पर एक दूरस्थ उपयोगकर्ता।)
* TgtUser (Target User): जब कोई क्रिया किसी उपयोगकर्ता पर होती है। (उदाहरण के लिए, किसी उपयोगकर्ता पर लॉगऑन।)
* User: जब कोई क्रिया वर्तमान में लॉग इन उपयोगकर्ता द्वारा होती है। (क्रिया में कोई विशेष दिशा नहीं होती।)
एक अन्य उदाहरण प्रक्रियाओं का है।
मूल Windows इवेंट लॉग में, प्रक्रिया फ़ील्ड को कई नामकरण परंपराओं के साथ संदर्भित किया जाता है: ProcessName, Image, processPath, Application, WindowsDefenderProcessName, आदि...
फ़ील्ड सामान्यीकरण के बिना, एक विश्लेषक को पहले सभी विभिन्न फ़ील्ड नामों के बारे में जानकार होना होगा, फिर इन फ़ील्ड नामों के साथ सभी लॉग निकालने होंगे, फिर उन्हें एक साथ संयोजित करना होगा।
एक विश्लेषक केवल सामान्यीकृत एकल Proc फ़ील्ड का उपयोग करके बहुत समय और परेशानी बचा सकता है जिसे Hayabusa Details ऑब्जेक्ट में प्रदान करता है।
jq पाठ/रेसिपी¶
अब मैं व्यावहारिक उदाहरणों के कई पाठ/रेसिपी सूचीबद्ध करूँगा जो आपके काम में आपकी मदद कर सकते हैं।
1. jq और रंग में Less के साथ मैन्युअल जाँच¶
यह समझने के लिए कि लॉग में कौन से फ़ील्ड हैं, सबसे पहले की जाने वाली चीज़ों में से एक है।
आप बस less results.json कर सकते हैं लेकिन एक बेहतर तरीका निम्नलिखित है:
cat results.json | jq -C | less -R
jq को पास करने से, यह सभी फ़ील्ड्स को आपके लिए साफ़ सुथरे ढंग से प्रारूपित करेगा यदि वे शुरू से साफ़ सुथरे ढंग से प्रारूपित नहीं थे।
jq के साथ -C (color) विकल्प और less के साथ -R (raw output) विकल्प का उपयोग करके, आप रंग में ऊपर और नीचे स्क्रॉल कर सकते हैं।
2. मेट्रिक्स¶
Hayabusa में पहले से ही इवेंट ID के आधार पर घटनाओं की संख्या और प्रतिशत प्रिंट करने की कार्यक्षमता है, हालाँकि, यह जानना भी अच्छा है कि इसे jq के साथ कैसे किया जाए।
यह आपको उस डेटा को अनुकूलित करने देगा जिसके लिए आप मेट्रिक्स बनाना चाहते हैं।
आइए पहले निम्नलिखित कमांड के साथ Event ID की एक सूची निकालें:
cat results.json | jq '.EventID'
यह प्रत्येक लॉग से केवल Event ID संख्या निकालेगा।
jq के बाद, एकल उद्धरण चिह्नों में, बस एक . और वह फ़ील्ड नाम टाइप करें जिसे आप निकालना चाहते हैं।
आपको इस तरह की एक लंबी सूची दिखनी चाहिए:
अब, यह गिनने के लिए कि इवेंट ID कितनी बार आए, परिणामों को sort और uniq -c कमांड में पाइप करें:
cat results.json | jq '.EventID' | sort | uniq -c
uniq के लिए -c विकल्प यह गिनेगा कि एक अद्वितीय इवेंट ID कितनी बार आया।
आपको कुछ इस तरह दिखना चाहिए:
बाईं ओर गिनती है, और दाईं ओर Event ID है। जैसा कि आप देख सकते हैं यह क्रमबद्ध नहीं है, इसलिए यह बताना मुश्किल है कि कौन से इवेंट ID सबसे अधिक आए।
आप इसे ठीक करने के लिए अंत में एक sort -n जोड़ सकते हैं:
cat results.json | jq '.EventID' | sort | uniq -c | sort -n
-n विकल्प sort को संख्या के अनुसार क्रमबद्ध करने के लिए कहता है।
आपको कुछ इस तरह दिखना चाहिए:
हम देख सकते हैं कि 4688 (Process creation) घटनाएँ सबसे अधिक दर्ज की गईं।
दूसरी सबसे अधिक दर्ज की गई घटना 4625 (Failed Logon) थी।
यदि आप शीर्ष पर सबसे अधिक दर्ज की गई घटनाओं को प्रिंट करना चाहते हैं, तो आप sort -n -r या sort -nr के साथ क्रम को उलट सकते हैं।
आप परिणामों को head -n 10 में पाइप करके केवल शीर्ष 10 सबसे अधिक दर्ज की गई घटनाओं को भी प्रिंट कर सकते हैं।
cat results.json | jq '.EventID' | sort | uniq -c | sort -nr | head -n 10
यह आपको देगा:
यह विचार करना महत्वपूर्ण है कि EID (Event ID) अद्वितीय नहीं होते, इसलिए आपके पास एक ही Event ID के साथ पूरी तरह से अलग घटनाएँ हो सकती हैं।
इसलिए, Channel को भी जाँचना महत्वपूर्ण है।
हम इस फ़ील्ड जानकारी को इस तरह जोड़ सकते हैं:
cat results.json | jq -j ' .Channel , " " , .EventID , "\n" ' | sort | uniq -c | sort -nr | head -n 10
हम सभी फ़ील्ड्स को कॉमा द्वारा सीमांकित करके और एक \n नई पंक्ति वर्ण के साथ समाप्त करके एक साथ जोड़ने के लिए jq में -j (join) विकल्प जोड़ते हैं।
यह हमें देगा:
12277 Sec 4688
7135 Sec 4625
2584 Sec 5145
2321 Sysmon 1
1382 Sys 7045
1131 PwSh 4104
682 PwSh 4103
433 Sec 5140
400 Sec 4624
391 Sysmon 8
नोट: Security को Sec, System को Sys, और PowerShell को PwSh में संक्षिप्त किया गया है।
हम नियम शीर्षक को इस प्रकार जोड़ सकते हैं:
cat results.json | jq -j ' .Channel , " " , .EventID , " " , .RuleTitle , "\n" ' | sort | uniq -c | sort -nr | head -n 10
यह हमें देगा:
9714 Sec 4688 Proc Exec
3564 Sec 4625 Logon Failure (Wrong Password)
3561 Sec 4625 Metasploit SMB Authentication
2564 Sec 5145 NetShare File Access
1459 Sysmon 1 Proc Exec
1418 Sec 4688 Susp CmdLine (Possible LOLBIN)
789 PwSh 4104 PwSh Scriptblock
680 PwSh 4103 PwSh Pipeline Exec
433 Sec 5140 NetShare Access
342 Sec 4648 Explicit Logon
अब आप लॉग से कोई भी डेटा स्वतंत्र रूप से निकाल सकते हैं और घटनाओं की गिनती कर सकते हैं।
3. कुछ विशेष डेटा पर फ़िल्टर करना¶
कई बार आप कुछ विशेष Event ID, उपयोगकर्ताओं, प्रक्रियाओं, LID (Logon ID) आदि पर फ़िल्टर करना चाहेंगे...
आप यह jq क्वेरी के अंदर select के साथ कर सकते हैं।
उदाहरण के लिए, आइए सभी 4624 सफल लॉगऑन घटनाओं को निकालें:
cat results.json | jq 'select ( .EventID == 4624 ) '
यह EID 4624 के लिए सभी JSON ऑब्जेक्ट्स लौटाएगा:
{
"Timestamp": "2021-12-12 16:16:04.237 +09:00",
"Computer": "fs03vuln.offsec.lan",
"Channel": "Sec",
"Provider": "Microsoft-Windows-Security-Auditing",
"EventID": 4624,
"Level": "info",
"RecordID": 1160369,
"RuleTitle": "Logon (Network)",
"RuleAuthor": "Zach Mathis",
"RuleCreationDate": "2020/11/08",
"RuleModifiedDate": "2022/12/16",
"Status": "stable",
"Details": {
"Type": 3,
"TgtUser": "admmig",
"SrcComp": "",
"SrcIP": "10.23.123.11",
"LID": "0x87249a8"
},
"RuleFile": "Sec_4624_Info_Logon-Type-3-Network.yml",
"EvtxFile": "../hayabusa-sample-evtx/EVTX-to-MITRE-Attack/TA0007-Discovery/T1046-Network Service Scanning/ID4624-Anonymous login with domain specified (DonPapi).evtx",
"AllFieldInfo": {
"AuthenticationPackageName": "NTLM",
"ImpersonationLevel": "%%1833",
"IpAddress": "10.23.123.11",
"IpPort": 60174,
"KeyLength": 0,
"LmPackageName": "NTLM V2",
"LogonGuid": "00000000-0000-0000-0000-000000000000",
"LogonProcessName": "NtLmSsp",
"LogonType": 3,
"ProcessId": "0x0",
"ProcessName": "-",
"SubjectDomainName": "-",
"SubjectLogonId": "0x0",
"SubjectUserName": "-",
"SubjectUserSid": "S-1-0-0",
"TargetDomainName": "OFFSEC",
"TargetLogonId": "0x87249a8",
"TargetUserName": "admmig",
"TargetUserSid": "S-1-5-21-4230534742-2542757381-3142984815-1111",
"TransmittedServices": "-",
"WorkstationName": ""
}
यदि आप कई शर्तों पर फ़िल्टर करना चाहते हैं, तो आप and, or और not जैसे कीवर्ड का उपयोग कर सकते हैं।
उदाहरण के लिए, आइए 4624 घटनाओं की खोज करें जहाँ प्रकार 3 (Network logon) है।
cat results.json | jq 'select ( ( .EventID == 4624 ) and ( .Details.Type == 3 ) ) '
यह सभी ऑब्जेक्ट्स लौटाएगा जहाँ EventID 4624 है और नेस्टेड "Details": { "Type" } फ़ील्ड 3 है।
हालाँकि एक समस्या है।
आप jq: error (at <stdin>:10636): Cannot index string with string "Type" कहने वाली त्रुटियाँ देख सकते हैं।
जब भी आप त्रुटि Cannot index string with string देखते हैं, तो इसका अर्थ है कि आप jq को ऐसा फ़ील्ड आउटपुट करने के लिए कह रहे हैं जो मौजूद नहीं है या गलत प्रकार का है।
आप फ़ील्ड के अंत में एक ? जोड़कर इन त्रुटियों से छुटकारा पा सकते हैं।
यह jq को त्रुटियों को अनदेखा करने के लिए कहता है।
उदाहरण: cat results.json | jq 'select ( ( .EventID == 4624 ) and ( .Details.Type? == 3 ) ) '
अब, कुछ विशेष मानदंडों पर फ़िल्टर करने के बाद, हम रुचि के कुछ विशेष फ़ील्ड्स का चयन करने के लिए अब jq क्वेरी के अंदर एक | का उपयोग कर सकते हैं।
उदाहरण के लिए, आइए लक्ष्य उपयोगकर्ता नाम TgtUser और स्रोत IP पता SrcIP निकालें:
cat results.json | jq -j 'select ( ( .EventID == 4624 ) and ( .Details.Type? == 3 ) ) | .Details.TgtUser , " " , .Details.SrcIP , "\n" '
फिर से, हम कई फ़ील्ड्स को आउटपुट करने के लिए चुनने के लिए jq में -j (join) विकल्प जोड़ते हैं।
फिर आप पिछले उदाहरणों की तरह sort, uniq -c आदि चला सकते हैं... यह जानने के लिए कि किसी विशेष IP पते ने टाइप 3 नेटवर्क लॉगऑन के माध्यम से किसी उपयोगकर्ता में कितनी बार लॉग इन किया।
4. आउटपुट को CSV प्रारूप में सहेजना¶
दुर्भाग्य से, Windows इवेंट लॉग में फ़ील्ड घटना के प्रकार के अनुसार पूरी तरह से भिन्न होंगे, इसलिए सैकड़ों कॉलम के बिना फ़ील्ड के अनुसार कॉमा से अलग की गई टाइमलाइन बनाना आसानी से संभव नहीं है।
हालाँकि, एकल प्रकार की घटनाओं के लिए फ़ील्ड से अलग की गई टाइमलाइन बनाना संभव है।
दो सामान्य उदाहरण हैं Security 4624 (Successful Logons) और 4625 (Failed Logons) lateral movement और पासवर्ड अनुमान/स्प्रेइंग की जाँच के लिए।
इस उदाहरण में, हम केवल Security 4624 लॉग निकाल रहे हैं और टाइमस्टैम्प, कंप्यूटर नाम और सभी Details जानकारी आउटपुट कर रहे हैं।
हम इसे | @csv का उपयोग करके एक CSV फ़ाइल में सहेजते हैं, हालाँकि, हमें डेटा को एक array के रूप में पास करना होगा।
हम यह उन फ़ील्ड्स का चयन करके कर सकते हैं जिन्हें हम आउटपुट करना चाहते हैं जैसा कि हमने पहले किया था और उन्हें [ ] वर्ग ब्रैकेट्स के साथ संलग्न करके array में बदल सकते हैं।
उदाहरण: cat results.json | jq 'select ( (.Channel == "Sec" ) and ( .EventID == 4624 ) ) | [ .Timestamp , .Computer , .Details[]? ] | @csv ' -r
नोट्स:
* Details ऑब्जेक्ट में सभी फ़ील्ड्स का चयन करने के लिए हम [] जोड़ते हैं।
* ऐसे मामले हैं जहाँ Details एक array नहीं बल्कि एक स्ट्रिंग है और Cannot iterate over string त्रुटियाँ देगा इसलिए आपको एक ? जोड़ना होगा।
* हम डबल उद्धरण चिह्नों को बैकस्लैश से एस्केप न करने के लिए jq में -r (Raw output) विकल्प जोड़ते हैं।
परिणाम:
"2019-03-19 08:23:52.491 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"user01","","10.0.2.17","0x15e1a7"
"2019-03-19 08:23:57.397 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"WIN-77LTAPHIQ1R$","","fe80::79bf:8ee2:433c:2567","0x15e25f"
"2019-03-19 09:02:04.179 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"ANONYMOUS LOGON","NULL","10.0.2.17","0x17e29a"
"2019-03-19 09:02:04.210 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"Administrator","","10.0.2.17","0x17e2aa"
"2019-03-19 09:02:04.226 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"Administrator","","10.0.2.17","0x17e2c0"
"2019-03-19 09:02:21.929 +09:00","WIN-77LTAPHIQ1R.example.corp",3,"WIN-77LTAPHIQ1R$","","fe80::79bf:8ee2:433c:2567","0x18423d"
"2019-05-12 02:10:10.889 +09:00","IEWIN7",9,"IEUser","","::1","0x1bbdce"
यदि हम केवल जाँच कर रहे हैं कि किसने सफल लॉगऑन किए, तो हमें अंतिम LID (Logon ID) फ़ील्ड की आवश्यकता नहीं हो सकती है।
आप del फ़ंक्शन के साथ किसी भी अनावश्यक कॉलम को हटा सकते हैं।
उदाहरण: cat results.json | jq 'select ( ( .Channel == "Sec" ) and ( .EventID == 4624 ) ) | [ .Timestamp , .Computer , .Details[]? ] | del( .[6] ) | @csv ' -r
array 0 से गिनती करता है इसलिए 7वें फ़ील्ड को हटाने के लिए, हम 6 का उपयोग करते हैं।
अब आप > 4624-logs.csv जोड़कर CSV फ़ाइल सहेज सकते हैं और फिर इसे आगे के विश्लेषण के लिए Excel या Timeline Explorer में आयात कर सकते हैं।
ध्यान दें कि फ़िल्टरिंग करने के लिए आपको एक हेडर जोड़ना होगा।
हालाँकि jq क्वेरी के अंदर एक हेडिंग जोड़ना संभव है, लेकिन आमतौर पर फ़ाइल सहेजने के बाद बस मैन्युअल रूप से एक शीर्ष पंक्ति जोड़ना सबसे आसान होता है।
5. सबसे अधिक अलर्ट वाली तिथियाँ खोजना¶
Hayabusa, डिफ़ॉल्ट रूप से, आपको गंभीरता स्तरों के अनुसार सबसे अधिक अलर्ट वाली तिथियाँ बताएगा। हालाँकि, आप दूसरी, तीसरी, आदि सबसे अधिक अलर्ट वाली तिथियाँ भी खोजना चाह सकते हैं। हम यह आपकी आवश्यकताओं के आधार पर वर्ष, माह या तिथि के अनुसार समूहित करने के लिए टाइमस्टैम्प को स्ट्रिंग स्लाइसिंग करके कर सकते हैं।
उदाहरण: cat results.json | jq ' .Timestamp | .[:10] ' -r | sort | uniq -c | sort
.[:10] jq को Timestamp से केवल पहले 10 बाइट्स निकालने के लिए कहता है।
यह हमें सबसे अधिक घटनाओं वाली तिथियाँ देगा:
1066 2021-12-12
1093 2016-09-02
1571 2021-04-22
1750 2016-09-03
2271 2016-08-19
2932 2021-11-03
8095 2016-09-20
यदि आप सबसे अधिक घटनाओं वाला माह जानना चाहते हैं, तो आप बस पहले 7 बाइट्स निकालने के लिए .[:10] को .[:7] में बदल सकते हैं।
यदि आप सबसे अधिक high अलर्ट वाली तिथियाँ सूचीबद्ध करना चाहते हैं, तो आप यह कर सकते हैं:
cat results.json | jq 'select ( .Level == "high" ) | .Timestamp | .[:10] ' -r | sort | uniq -c | sort
आप अपनी आवश्यकताओं के आधार पर कंप्यूटर नाम, इवेंट ID आदि के अनुसार select फ़ंक्शन में फ़िल्टर शर्तें जोड़ते रह सकते हैं।
6. PowerShell लॉग का पुनर्निर्माण¶
PowerShell लॉग के बारे में एक दुर्भाग्यपूर्ण बात यह है कि लॉग अक्सर कई लॉग में टूट जाएँगे जिससे उन्हें पढ़ना मुश्किल हो जाता है। हम केवल हमलावर द्वारा चलाए गए कमांड को निकालकर लॉग को पढ़ने में बहुत आसान बना सकते हैं।
उदाहरण के लिए, यदि आपके पास EID 4104 ScriptBlock लॉग हैं, तो आप पढ़ने में आसान टाइमलाइन बनाने के लिए केवल उस फ़ील्ड को निकाल सकते हैं।
cat results.json | jq 'select ( .EventID == 4104) | .Timestamp[:16] , " " , .Details.ScriptBlock , "\n" ' -jr
इसका परिणाम निम्नलिखित टाइमलाइन में होगा:
2022-12-24 10:56 ipconfig
2022-12-24 10:56 prompt
2022-12-24 10:56 pwd
2022-12-24 10:56 prompt
2022-12-24 10:56 whoami
2022-12-24 10:56 prompt
2022-12-24 10:57 cd..
2022-12-24 10:57 prompt
2022-12-24 10:57 ls
7. संदिग्ध नेटवर्क कनेक्शन खोजना¶
आप पहले निम्नलिखित कमांड के साथ सभी लक्ष्य IP पतों की एक सूची प्राप्त कर सकते हैं:
cat results.json | jq 'select ( .Details.TgtIP? ) | .Details.TgtIP ' -r | sort | uniq
यदि आपके पास थ्रेट इंटेलिजेंस है, तो आप यह जाँच सकते हैं कि क्या कोई IP पता दुर्भावनापूर्ण होने के लिए जाना जाता है।
आप निम्नलिखित के साथ यह गिन सकते हैं कि किसी विशेष लक्ष्य IP पते से कितनी बार कनेक्ट किया गया:
cat results.json | jq 'select ( .Details.TgtIP? ) | .Details.TgtIP ' -r | sort | uniq -c | sort -n
TgtIP को SrcIP में बदलकर, आप स्रोत IP पतों के आधार पर दुर्भावनापूर्ण IP पतों के लिए वही थ्रेट इंटेलिजेंस जाँच कर सकते हैं।
मान लीजिए कि आपको पता चला कि आपके वातावरण से 93.184.220.29 के दुर्भावनापूर्ण IP पते से कनेक्ट किया जा रहा था।
आप निम्नलिखित क्वेरी के साथ उन घटनाओं का विवरण प्राप्त कर सकते हैं:
cat results.json | jq 'select ( .Details.TgtIP? == "93.184.220.29" ) '
यह आपको इस तरह के JSON परिणाम देगा:
{
"Timestamp": "2019-07-30 06:33:20.711 +09:00",
"Computer": "MSEDGEWIN10",
"Channel": "Sysmon",
"EventID": 3,
"Level": "med",
"RecordID": 4908,
"RuleTitle": "Net Conn (Sysmon Alert)",
"Details": {
"Proto": "tcp",
"SrcIP": "10.0.2.15",
"SrcPort": 49827,
"SrcHost": "MSEDGEWIN10.home",
"TgtIP": "93.184.220.29",
"TgtPort": 80,
"TgtHost": "",
"User": "MSEDGEWIN10\\IEUser",
"Proc": "C:\\Windows\\System32\\mshta.exe",
"PID": 3164,
"PGUID": "747F3D96-661E-5D3F-0000-00107F248700"
}
}
यदि आप संपर्क किए गए डोमेन सूचीबद्ध करना चाहते हैं, तो आप निम्नलिखित कमांड का उपयोग कर सकते हैं:
cat results.json | jq 'select ( .Details.TgtHost ) ? | .Details.TgtHost ' -r | sort | uniq | grep "\."
नोट: मैंने NETBIOS होस्टनामों को हटाने के लिए
.के लिए एक grep फ़िल्टर जोड़ा।
8. एक्ज़ीक्यूटेबल बाइनरी हैश निकालना¶
Sysmon EID 1 Process Creation लॉग में, sysmon को बाइनरी के हैश की गणना करने के लिए कॉन्फ़िगर किया जा सकता है।
सुरक्षा विश्लेषक इन हैश की तुलना थ्रेट इंटेलिजेंस के साथ ज्ञात दुर्भावनापूर्ण हैश से कर सकते हैं।
आप निम्नलिखित के साथ Hashes फ़ील्ड निकाल सकते हैं:
cat results.json | jq 'select ( .Details.Hashes? ) | .Details.Hashes ' -r
यह आपको इस तरह की हैश की एक सूची देगा:
MD5=E112A827FAB9F8378C76040187A6F336,SHA256=ED369187681A62247E38D930320F1CD771756D0B7B67072D8EC655EF99E14AEB,IMPHASH=8EEAA9499666119D13B3F44ECD77A729
MD5=E112A827FAB9F8378C76040187A6F336,SHA256=ED369187681A62247E38D930320F1CD771756D0B7B67072D8EC655EF99E14AEB,IMPHASH=8EEAA9499666119D13B3F44ECD77A729
MD5=E112A827FAB9F8378C76040187A6F336,SHA256=ED369187681A62247E38D930320F1CD771756D0B7B67072D8EC655EF99E14AEB,IMPHASH=8EEAA9499666119D13B3F44ECD77A729
MD5=E112A827FAB9F8378C76040187A6F336,SHA256=ED369187681A62247E38D930320F1CD771756D0B7B67072D8EC655EF99E14AEB,IMPHASH=8EEAA9499666119D13B3F44ECD77A729
Sysmon आमतौर पर कई हैश की गणना करेगा जैसे MD5, SHA1 और IMPHASH।
आप jq में रेगुलर एक्सप्रेशन के साथ इन हैश को निकाल सकते हैं या बेहतर प्रदर्शन के लिए बस स्ट्रिंग स्प्लाइसिंग का उपयोग कर सकते हैं।
उदाहरण के लिए, आप निम्नलिखित के साथ MD5 हैश निकाल सकते हैं और डुप्लिकेट हटा सकते हैं:
cat results.json | jq 'select ( .Details.Hashes? ) | .Details.Hashes | .[4:36] ' -r | sort | uniq
9. PowerShell लॉग निकालना¶
PowerShell Scriptblock लॉग (EID: 4104) आमतौर पर कई लॉग में टूट जाते हैं और CSV प्रारूप में आउटपुट करते समय, Hayabusa आउटपुट को अधिक संक्षिप्त बनाने के लिए टैब और रिटर्न वर्णों को हटा देगा।
हालाँकि, मूल टैब और रिटर्न वर्ण स्वरूपण के साथ और लॉग को एक साथ संयोजित करके PowerShell लॉग का विश्लेषण करना सबसे आसान होता है।
यहाँ COMPUTER-A से PowerShell EID 4104 लॉग निकालने और उन्हें VSCode आदि में खोलने और विश्लेषण करने के लिए एक .ps1 फ़ाइल में सहेजने का एक उदाहरण है।
ScriptBlock फ़ील्ड निकालने के बाद, हम \r\n और \n को रिटर्न वर्णों से और \t को टैब से बदलने के लिए awk का उपयोग करते हैं।
cat results.json | jq 'select ( .EventID == 4104 and .Details.ScriptBlock? != "n/a" and .Computer == "COMPUTER-A.domain.local" ) | .Details.ScriptBlock , "\r\n"' -j | awk '{ gsub(/\\r\\n/,"\r\n"); print; }' | awk '{ gsub(/\\t/, "\t"); print; }' | awk '{ gsub(/\\n/, "\r\n"); print; }' > 4104-PowerShell-Logs.ps1
विश्लेषक द्वारा दुर्भावनापूर्ण PowerShell कमांड के लिए लॉग का विश्लेषण करने के बाद, उन्हें आमतौर पर यह देखने की आवश्यकता होगी कि वे कमांड कब चलाए गए थे। यहाँ Timestamp और PowerShell लॉग को CSV फ़ाइल में आउटपुट करने का एक उदाहरण है ताकि यह देखा जा सके कि कोई कमांड कब चलाया गया था:
cat results.json | jq ' select (.EventID == 4104 and .Details.ScriptBlock? != "n/a" and .Computer == "COMPUTER-A.domain.local") | .Timestamp, ",¦", .Details.ScriptBlock?, "¦\r\n" ' -j | awk '{ gsub(/\\r\\n/,"\r\n"); print; }' | awk '{ gsub(/\\t/,"\t"); print; }' | awk '{ gsub(/\\n/,"\r\n"); print; }' > 4104-PowerShell-Logs.csv
नोट: उपयोग किया गया स्ट्रिंग सीमांकक ¦ है क्योंकि एकल और डबल उद्धरण चिह्न अक्सर PowerShell लॉग में पाए जाते हैं और CSV आउटपुट को दूषित कर देंगे।
जब आप CSV फ़ाइल आयात करते हैं, तो आपको एप्लिकेशन को ¦ स्ट्रिंग सीमांकक निर्दिष्ट करना होगा।