שיטות עבודה מומלצות מתקדמות של שאילתת ציד

הערה

רוצה להתנסות ב- Microsoft Defender XDR? קבל מידע נוסף על האופן שבו ניתן להעריך ולבצע פריסת ניסיון Microsoft Defender XDR.

חל על:

  • Microsoft Defender XDR

החל המלצות אלה כדי לקבל את התוצאות מהר יותר ולהימנע מסיום זמן קצוב בעת הפעלת שאילתות מורכבות. לקבלת הדרכה נוספת בנושא שיפור ביצועי השאילתה, קרא את שיטות העבודה המומלצות לשאילתת Kusto.

הכרת מיכסות משאבי CPU

בהתאם לגודלו, לכל דייר יש גישה לכמות מוגדרת של משאבי CPU המוקצים להפעלה של שאילתות ציד מתקדמות. לקבלת מידע מפורט אודות פרמטרים שונים של שימוש, קרא אודות מיכסות ציד מתקדמות פרמטרים שימוש.

לאחר הפעלת השאילתה, תוכל לראות את זמן הביצוע ואת השימוש במשאבים שלה (נמוכה, בינונית, גבוהה). ערך גבוה מציין שהשאילתה לקחה יותר משאבים להפעלה ו היתה אפשרות לשפר אותה כדי להחזיר תוצאות בצורה יעילה יותר.

פרטי השאילתה תחת **תוצאות** בכרטיסיה 'Microsoft Defender'

לקוחות שפועלים באופן קבוע אחר שאילתות מרובות צריכים לעקוב אחר הצריכה ולהחיל את ההנחיות המיטוב במאמר זה כדי לצמצם את ההפרעות כתוצאה מחרגה ממיכסות או מפרמטרים של שימוש.

צפה באופטימיזציה של שאילתות 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 תואם רשומות בטבלה בצד הימני של משפט הצירוף לרשומות בצד ימין. אם הטבלה הקטנה יותר תהיה קטנה יותר בצד ימין, יהיה צורך להתאים פחות רשומות, ובכך להאיץ את השאילתה.

    בטבלה שלהלן, אנו מקטיןים DeviceLogonEventsIdentityLogonEvents את הטבלה השמאלית כדי לכסות שלושה מכשירים ספציפיים בלבד לפני שאנו מצטרפים אליה באמצעות כרטיסי 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או ), מזהה התהליך ( InitiatingProcessIdProcessId או ) ותהליכי יצירת התהליך (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

השאילתה מסכמת הן לפי InitiatingProcessIdInitiatingProcessCreationTime והן כך שהיא בודקת תהליך יחיד, מבלי לערבב תהליכים מרובים עם אותו מזהה תהליך.

שורות פקודה של שאילתה

קיימות דרכים רבות לבניית שורת פקודה לביצוע משימה. לדוגמה, תוקף יכול להפנות לקובץ תמונה ללא נתיב, ללא סיומת קובץ, להשתמש במשתנה סביבה או במרכאות. התוקף יכול גם לשנות את סדר הפרמטרים או להוסיף מרכאות ורווחים מרובים.

כדי ליצור שאילתות עמידה יותר סביב שורות פקודה, החל את שיטות העבודה הבאות:

  • זהה את התהליכים הידועים ( כגון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 עבור נקודת קצה.

עצה

האם ברצונך לקבל מידע נוסף? צור קשר עם קהילת האבטחה של Microsoft בקהילת הטכנולוגיה שלנו: קהילת האבטחה של Microsoft Defender XDR.