שיטות עבודה מומלצות מתקדמות של שאילתת ציד
חל על:
- Microsoft Defender XDR
החל המלצות אלה כדי לקבל את התוצאות מהר יותר ולהימנע מסיום זמן קצוב בעת הפעלת שאילתות מורכבות. לקבלת הדרכה נוספת בנושא שיפור ביצועי השאילתה, קרא את שיטות העבודה המומלצות לשאילתת Kusto.
הכרת מיכסות משאבי CPU
בהתאם לגודלו, לכל דייר יש גישה לכמות מוגדרת של משאבי CPU המוקצים להפעלה של שאילתות ציד מתקדמות. לקבלת מידע מפורט אודות פרמטרים שונים של שימוש, קרא אודות מיכסות ציד מתקדמות פרמטרים שימוש.
לאחר הפעלת השאילתה, תוכל לראות את זמן הביצוע ואת השימוש במשאבים שלה (נמוכה, בינונית, גבוהה). ערך גבוה מציין שהשאילתה לקחה יותר משאבים להפעלה ו היתה אפשרות לשפר אותה כדי להחזיר תוצאות בצורה יעילה יותר.
לקוחות שפועלים באופן קבוע אחר שאילתות מרובות צריכים לעקוב אחר הצריכה ולהחיל את ההנחיות המיטוב במאמר זה כדי לצמצם את ההפרעות כתוצאה מחרגה ממיכסות או מפרמטרים של שימוש.
צפה באופטימיזציה של שאילתות KQL כדי לראות כמה מהדרכים הנפוצות ביותר לשיפור השאילתות שלך.
עצות מיטוב כלליות
שנה גודל של שאילתות חדשות — אם אתה חושד ששאילתה תחזיר ערכת תוצאות גדולה, להעריך אותה תחילה באמצעות אופרטור הספירה. השתמש ב- limit או במילה הנרדפת שלה כדי
take
להימנע מערכות תוצאות גדולות.החל מסננים מוקדם יותר - החל מסנני זמן ומסננים אחרים כדי להפחית את ערכת הנתונים, במיוחד לפני השימוש בפונקציות המרה בניתוח מבנה טקסט, כגון מחרוזת משנה (), החלפה(), trim(), toupper(), או parse_json(). בדוגמה שלהלן, הפונקציה parsing extractjson() משמשת לאחר שתופרטורים של סינון הפחיתו את מספר הרשומות.
DeviceEvents | where Timestamp > ago(1d) | where ActionType == "UsbDriveMount" | where DeviceName == "user-desktop.domain.com" | extend DriveLetter = extractjson("$.DriveLetter", AdditionalFields)
מכיל פעימות – כדי להימנע מחיפוש של מחרוזת משנה בתוך מילים שלא לצורך, השתמש באופרטור
has
במקום ב-contains
. למד אודות אופרטורים של מחרוזותחפש בעמודות ספציפיות - חפש בעמודה ספציפית במקום להפעיל חיפושי טקסט מלאים בכל העמודות. אל תשתמש כדי לבדוק
*
את כל העמודות.תלויי רישיות עבור מהירות - חיפושים תלויי רישיות הם ספציפיים יותר וב בדרך כלל מבצעים יותר. שמות של אופרטורים תלויי רישיות של מחרוזות, כגון
has_cs
וcontains_cs
- , מסתיים בדרך כלל ב-_cs
. באפשרותך גם להשתמש באופרטור תלוי רישיות שווה==
במקום ב-=~
.ניתוח מבנה טקסט, אל תחלץ — כאשר הדבר אפשרי, השתמש באופרטור הניתוח או בפונקציית ניתוח מבנה טקסט כגון parse_json(). הימנע משימוש
matches regex
באופרטור המחרוזת או מפונקציית התחלץ(), שניהם משתמשים בביטוי רגיל. שמור את השימוש בביטוי רגיל עבור תרחישים מורכבים יותר. קרא עוד אודות ניתוח פונקציותסנן טבלאות שאינן ביטויים — אל מסנן לפי עמודה מחושבת אם באפשרותך לסנן לפי עמודת טבלה.
אין מונחים של שלושה תווים - הימנע מהשוואה או סינון באמצעות מונחים עם שלושה תווים או פחות. מונחים אלה אינם סדורים באינדקס ומתאימים אותם ידרשו משאבים נוספים.
הקרן באופן סלקטיבי - הפוך את התוצאות שלך לקלות יותר להבנה על-ידי הקרנת העמודות הדרושות לך בלבד. הקרנת עמודות ספציפיות לפני הפעלת צירוף או פעולות דומות גם מסייעת בשיפור הביצועים.
מיטוב האופרטור join
אופרטור הצירוף ממזג שורות משתי טבלאות על-ידי התאמת ערכים בעמודות שצוינו. החל עצות אלה כדי למטב שאילתות המשתמשות באופרטור זה.
טבלה קטנה יותר משמאל — האופרטור
join
תואם רשומות בטבלה בצד הימני של משפט הצירוף לרשומות בצד ימין. אם הטבלה הקטנה יותר תהיה קטנה יותר בצד ימין, יהיה צורך להתאים פחות רשומות, ובכך להאיץ את השאילתה.בטבלה שלהלן, אנו מקטיןים
DeviceLogonEvents
IdentityLogonEvents
את הטבלה השמאלית כדי לכסות שלושה מכשירים ספציפיים בלבד לפני שאנו מצטרפים אליה באמצעות כרטיסי SIM של חשבון.DeviceLogonEvents | where DeviceName in ("device-1.domain.com", "device-2.domain.com", "device-3.domain.com") | where ActionType == "LogonFailed" | join (IdentityLogonEvents | where ActionType == "LogonFailed" | where Protocol == "Kerberos") on AccountSid
השתמש בטעם הצירוף הפנימי - טעם הצירוף המוגדר כברירת מחדל או הצירוף innerunique-join משכפל שורות בטבלה הימנית באמצעות מקש הצירוף לפני החזרת שורה עבור כל התאמה לטבלה הימנית. אם הטבלה הימנית
join
מכילה שורות מרובות עם אותו ערך עבור המפתח, שורות אלה יתכווגלו כך שיש להשאיר שורה אקראית אחת עבור כל ערך ייחודי.אופן פעולה זה המהווה ברירת מחדל יכול להוציא מהטבלה השמאלית מידע חשוב שעשוי לספק תובנות שימושיות. לדוגמה, השאילתה שלהלן תציג רק הודעת דואר אלקטרוני אחת המכילה קובץ מצורף מסוים, גם אם אותו קובץ מצורף נשלח באמצעות הודעות דואר אלקטרוני מרובות:
EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256
כדי לטפל במגבלות אלה, אנו מחילים את טעם הצירוף הפנימי על-ידי
kind=inner
ציון כל השורות בטבלה הימנית עם ערכים תואמים בצד ימין:EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256
צרף רשומות מחלון זמן - בעת חקירת אירועי אבטחה, אנליסטים מצפים לאירועים קשורים המתרחשים לאורך אותה פרק זמן. החלת אותה גישה בעת שימוש גם ביתרונות
join
הביצועים על-ידי הפחתת מספר הרשומות לבדיקתן.השאילתה שלהלן בודקת אם קיימים אירועי כניסה תוך 30 דקות מקבלת קובץ זדוני:
EmailEvents | where Timestamp > ago(7d) | where ThreatTypes has "Malware" | project EmailReceivedTime = Timestamp, Subject, SenderFromAddress, AccountName = tostring(split(RecipientEmailAddress, "@")[0]) | join ( DeviceLogonEvents | where Timestamp > ago(7d) | project LogonTime = Timestamp, AccountName, DeviceName ) on AccountName | where (LogonTime - EmailReceivedTime) between (0min .. 30min)
החל מסנני זמן משני הצדדים - גם אם אינך בודק חלון זמן ספציפי,
join
החלת מסנני זמן הן על הטבלאות השמאליות והן על הטבלאות הימניות עשויה להפחית את מספר הרשומות כדי לבדוק ולשפר את הביצועים. השאילתה שלהלןTimestamp > ago(1h)
חלה על שתי הטבלאות כך שהיא מצרפת רק רשומות מהשעה האחרונה:EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256
השתמש ברמזים לביצועים - השתמש ברמזים
join
עם האופרטור כדי להנחות את הקצה העורפי להפיץ עומס בעת הפעלת פעולות הצוחנות משאבים רבים. קבל מידע נוסף על רמזים להצטרפותלדוגמה, רמז ההפעלה בסדר אקראי עוזר לשפר את ביצועי השאילתה בעת צירוף טבלאות באמצעות מפתח בעל מספר מונה גבוה - מפתח עם ערכים ייחודיים רבים -
AccountObjectId
כגון בשאילתה שלהלן:IdentityInfo | where JobTitle == "CONSULTANT" | join hint.shufflekey = AccountObjectId (IdentityDirectoryEvents | where Application == "Active Directory" | where ActionType == "Private data retrieval") on AccountObjectId
רמז השידור עוזר כאשר הטבלה הימנית קטנה (עד 100,000 רשומות) והטבלה הימנית גדולה במיוחד. לדוגמה, השאילתה שלהלן מנסה לצרף כמה הודעות דואר אלקטרוני הכוללות נושאים ספציפיים עם כל ההודעות המכילות קישורים בטבלה
EmailUrlInfo
:EmailEvents | where Subject in ("Warning: Update your credentials now", "Action required: Update your credentials now") | join hint.strategy = broadcast EmailUrlInfo on NetworkMessageId
מיטוב האופרטור summarize
אופרטור הסיכום מצבור את התוכן של טבלה. החל עצות אלה כדי למטב שאילתות המשתמשות באופרטור זה.
חפש ערכים ייחודיים – באופן כללי,
summarize
השתמש כדי למצוא ערכים ייחודיים שניתן לבצע בהם שוב ושוב. ייתכן שלא יהיה צורך להשתמש בו כדי לצבור עמודות שאין בהן ערכים שחוזרים על עצמן.בעוד שהודעות דואר אלקטרוני בודדות יכולות להיות חלק מאירועים מרובים,
summarize
הדוגמה שלהלן אינה יעילה לשימוש מכיוון שמזהה הודעת רשת עבור הודעת דואר אלקטרוני בודדת מגיע תמיד עם כתובת שולח ייחודית.EmailEvents | where Timestamp > ago(1h) | summarize by NetworkMessageId, SenderFromAddress
ניתן
summarize
להחליף בקלות את האופרטור ב-project
, תוך הפקת אותן תוצאות תוך צורך של פחות משאבים:EmailEvents | where Timestamp > ago(1h) | project NetworkMessageId, SenderFromAddress
הדוגמה הבאה היא שימוש יעיל יותר מאחר
summarize
שקיימים מופעים ייחודיים מרובים של כתובת שולח שולח דואר אלקטרוני לאותה כתובת נמען. שילובים כאלה הם פחות ברורים ו להניח שהם כוללים כפילויות.EmailEvents | where Timestamp > ago(1h) | summarize by SenderFromAddress, RecipientEmailAddress
הפעל את השאילתה בסדר אקראי - בעוד
summarize
שייעשה שימוש מיטבי בעמודות עם ערכים שחוזרים על אותן עמודות, אותן עמודות יכולות לכלול גם מספר מונה גבוה או מספרים גדולים של ערכים ייחודיים. כמו האופרטורjoin
, באפשרותךsummarize
גם להחיל את רמז ההפעלה בסדר אקראי עם כדי להפיץ עומס עיבוד וייתכן לשפר את הביצועים בעת הפעלה בעמודות עם מספר מונה גבוה.השאילתה שלהלן משתמשת
summarize
בספירת כתובת דואר אלקטרוני ייחודית של נמען, שיכולה לפעול במאות אלפים בארגונים גדולים. כדי לשפר את הביצועים, הוא משלבhint.shufflekey
:EmailEvents | where Timestamp > ago(1h) | summarize hint.shufflekey = RecipientEmailAddress count() by Subject, RecipientEmailAddress
תרחישי שאילתה
זיהוי תהליכים ייחודיים באמצעות מזהי תהליכים
מזהי תהליכים (PID) ממוחזרים ב- Windows ומשימוש חוזר עבור תהליכים חדשים. בעצמם, הם אינם יכולים לשמש כמזהים ייחודיים עבור תהליכים ספציפיים.
כדי לקבל מזהה ייחודי עבור תהליך במחשב ספציפי, השתמש במזהה התהליך יחד עם זמן יצירת התהליך. בעת צירוף או סיכום של נתונים סביב תהליכים, כלול עמודות עבור מזהה המחשב (DeviceId
או ), מזהה התהליך ( InitiatingProcessId
ProcessId
או ) ותהליכי יצירת התהליך (ProcessCreationTime
או InitiatingProcessCreationTime
)DeviceName
שאילתת הדוגמה הבאה מוצאת תהליכים הלגשת ליותר מ- 10 כתובות IP דרך יציאה 445 (SMB), ואולי סורקים לאיתור מיקומים משותפים של קבצים.
שאילתה לדוגמה:
DeviceNetworkEvents
| where RemotePort == 445 and Timestamp > ago(12h) and InitiatingProcessId !in (0, 4)
| summarize RemoteIPCount=dcount(RemoteIP) by DeviceName, InitiatingProcessId, InitiatingProcessCreationTime, InitiatingProcessFileName
| where RemoteIPCount > 10
השאילתה מסכמת הן לפי InitiatingProcessId
InitiatingProcessCreationTime
והן כך שהיא בודקת תהליך יחיד, מבלי לערבב תהליכים מרובים עם אותו מזהה תהליך.
שורות פקודה של שאילתה
קיימות דרכים רבות לבניית שורת פקודה לביצוע משימה. לדוגמה, תוקף יכול להפנות לקובץ תמונה ללא נתיב, ללא סיומת קובץ, להשתמש במשתנה סביבה או במרכאות. התוקף יכול גם לשנות את סדר הפרמטרים או להוסיף מרכאות ורווחים מרובים.
כדי ליצור שאילתות עמידה יותר סביב שורות פקודה, החל את שיטות העבודה הבאות:
- זהה את התהליכים הידועים ( כגוןnet.exe או psexec.exe) על-ידי התאמתם לשדות שם הקובץ, במקום סינון בשורת הפקודה עצמה.
- ניתוח מקטעי שורת הפקודה באמצעות הפונקציה parse_command_line()
- בעת ביצוע שאילתה עבור ארגומנטים של שורת פקודה, אל תחפש התאמה מדויקת בארגומנטים מרובים שאינם קשורים זה לזו בסדר מסוים. במקום זאת, השתמש בביטויים רגילים או השתמש במספר אופרטורים נפרדים המכילים.
- התאמות לא תלויות רישיות. לדוגמה, השתמש ב
=~
- ,in~
,contains
וב במקום==
בin
- וב-contains_cs
. - כדי לצמצם טכניקות מעורפלות של שורת הפקודה, שקול להסיר מירכאות, להחליף פסיקים ברווחים ולהחליף רווחים רציפים מרובים ברווח בודד. קיימות טכניקות מעורפלות מורכבות יותר הדורשות גישות אחרות, אך שינויים אלה יכולים לעזור לטפל בשיטות נפוצות.
הדוגמאות הבאות מציגות דרכים שונות לבניית שאילתה המציגה את הקובץ net.exe להפסיק את שירות חומת האש "MpsSvc":
// Non-durable query - do not use
DeviceProcessEvents
| where ProcessCommandLine == "net stop MpsSvc"
| limit 10
// Better query - filters on file name, does case-insensitive matches
DeviceProcessEvents
| where Timestamp > ago(7d) and FileName in~ ("net.exe", "net1.exe") and ProcessCommandLine contains "stop" and ProcessCommandLine contains "MpsSvc"
// Best query also ignores quotes
DeviceProcessEvents
| where Timestamp > ago(7d) and FileName in~ ("net.exe", "net1.exe")
| extend CanonicalCommandLine=replace("\"", "", ProcessCommandLine)
| where CanonicalCommandLine contains "stop" and CanonicalCommandLine contains "MpsSvc"
אחסון נתונים ממקורות חיצוניים
כדי לשלב רשימות ארוכות או טבלאות גדולות בשאילתה, השתמש באופרטור externaldata כדי להוסיף נתונים מ- URI שצוין. באפשרותך לקבל נתונים מקבצים בתבניות TXT, CSV, JSON או תבניות אחרות. הדוגמה שלהלן מראה כיצד ניתן להשתמש ברשימה מקיפה של קוד Hash של תוכנות זדוניות SHA-256 שסופקו על-ידי MalwareBazaar (abuse.ch) כדי לבדוק קבצים מצורפים בהודעות דואר אלקטרוני:
let abuse_sha256 = (externaldata(sha256_hash: string)
[@"https://bazaar.abuse.ch/export/txt/sha256/recent/"]
with (format="txt"))
| where sha256_hash !startswith "#"
| project sha256_hash;
abuse_sha256
| join (EmailAttachmentInfo
| where Timestamp > ago(1d)
) on $left.sha256_hash == $right.SHA256
| project Timestamp,SenderFromAddress,RecipientEmailAddress,FileName,FileType,
SHA256,ThreatTypes,DetectionMethods
ניתוח מבנה טקסט של מחרוזות
קיימות פונקציות שונות שניתן להשתמש בהן כדי לטפל ביעילות במחרוזות הזונות לניתוח או להמרה.
מחרוזת | פונקציה | דוגמה לשימוש |
---|---|---|
שורות פקודה | parse_command_line() | חלץ את הפקודה ואת כל הארגומנטים. |
נתיבים | parse_path() | חילוץ המקטעים של נתיב קובץ או תיקיה. |
מספרי גירסאות | parse_version() | פענח מספר גירסה עם עד ארבעה מקטעים ושמונה תווים לכל מקטע. השתמש בנתונים שנותחו כדי להשוות בין גיל הגירסה. |
כתובות IPv4 | parse_ipv4() | המר כתובת IPv4 למספר שלם ארוך. כדי להשוות כתובות IPv4 מבלי להמיר אותן, השתמש ipv4_compare(). |
כתובות IPv6 | parse_ipv6() | המר כתובת IPv4 או IPv6 אל סימן IPv6 קנוני. כדי להשוות כתובות IPv6, השתמש ipv6_compare (). |
כדי ללמוד אודות כל פונקציות הניתוח הנתמכות, קרא אודות פונקציות מחרוזת Kusto.
הערה
ייתכן שטבלאות מסוימות במאמר זה לא יהיו זמינות Microsoft Defender עבור נקודת קצה. הפעל Microsoft Defender XDR לחפש איומים באמצעות מקורות נתונים נוספים. באפשרותך להעביר את זרימות העבודה המתקדמות שלך Microsoft Defender עבור נקודת קצה ל- Microsoft Defender XDR על-ידי ביצוע השלבים במאמר העברת שאילתות ציד מתקדמות Microsoft Defender עבור נקודת קצה.
נושאים קשורים
- תיעוד לשפת השאילתות של Kusto
- מכסות ופרמטרי שימוש
- טיפול בשגיאות ציד מתקדמות
- מבט כולל על ציד מתקדם
- למד את שפת השאילתה
עצה
האם ברצונך לקבל מידע נוסף? צור קשר עם קהילת האבטחה של Microsoft בקהילת הטכנולוגיה שלנו: קהילת האבטחה של Microsoft Defender XDR.