أفضل ممارسات استعلام التتبع المتقدمة

ينطبق على:

  • Microsoft Defender XDR

طبق هذه التوصيات للحصول على النتائج بشكل أسرع وتجنب المهلات أثناء تشغيل الاستعلامات المعقدة. لمزيد من الإرشادات حول تحسين أداء الاستعلام، اقرأ أفضل ممارسات استعلام Kusto.

فهم حصص موارد وحدة المعالجة المركزية

اعتمادا على حجمه، لكل مستأجر حق الوصول إلى كمية محددة من موارد وحدة المعالجة المركزية المخصصة لتشغيل استعلامات التتبع المتقدمة. للحصول على معلومات مفصلة حول معلمات الاستخدام المختلفة، اقرأ عن حصص التتبع المتقدمة ومعلمات الاستخدام.

بعد تشغيل الاستعلام، يمكنك مشاهدة وقت التنفيذ واستخدام الموارد الخاصة به (منخفض، متوسط، مرتفع). يشير High إلى أن الاستعلام استغرق المزيد من الموارد لتشغيله ويمكن تحسينه لإرجاع النتائج بشكل أكثر كفاءة.

تفاصيل الاستعلام ضمن علامة التبويب **Results** في مدخل Microsoft Defender

يجب على العملاء الذين يقومون بتشغيل استعلامات متعددة بانتظام تعقب الاستهلاك وتطبيق إرشادات التحسين في هذه المقالة لتقليل التعطيل الناتج عن تجاوز الحصص النسبية أو معلمات الاستخدام.

شاهد تحسين استعلامات KQL لمشاهدة بعض الطرق الأكثر شيوعا لتحسين استعلاماتك.

نصائح التحسين العامة

  • حجم الاستعلامات الجديدة — إذا كنت تشك في أن الاستعلام سيرجع مجموعة نتائج كبيرة، فقم بتقييمها أولا باستخدام عامل تشغيل العد. استخدم الحد أو مرادفاته take لتجنب مجموعات النتائج الكبيرة.

  • تطبيق عوامل التصفية مبكرا — تطبيق عوامل تصفية الوقت وعوامل التصفية الأخرى لتقليل مجموعة البيانات، خاصة قبل استخدام دالات التحويل وتحليلها، مثل substring()أو replace()أو trim()أو toupper()أو parse_json(). في المثال أدناه، يتم استخدام دالة التحليل 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 تجنب عامل تشغيل السلسلة أو دالة extract() ، وكلاهما يستخدم التعبير العادي. احجز استخدام التعبير العادي لسيناريوهات أكثر تعقيدا. اقرأ المزيد حول تحليل الوظائف

  • تصفية الجداول وليس التعبيرات — لا تقم بالتصفية على عمود محسوب إذا كان بإمكانك التصفية على عمود جدول.

  • لا توجد مصطلحات مكونة من ثلاثة أحرف — تجنب المقارنة أو التصفية باستخدام مصطلحات ذات ثلاثة أحرف أو أقل. لا تتم فهرسة هذه الشروط وستتطلب مطابقتها المزيد من الموارد.

  • العرض بشكل انتقائي — اجعل نتائجك أسهل في الفهم من خلال عرض الأعمدة التي تحتاج إليها فقط. يساعد عرض أعمدة معينة قبل تشغيل الانضمام أو عمليات مماثلة أيضا على تحسين الأداء.

join تحسين عامل التشغيل

يدمج عامل تشغيل الربط صفوفا من جدولين عن طريق مطابقة القيم في أعمدة محددة. تطبيق هذه التلميحات لتحسين الاستعلامات التي تستخدم عامل التشغيل هذا.

  • جدول أصغر إلى اليسار — يطابق join عامل التشغيل السجلات الموجودة في الجدول على الجانب الأيسر من عبارة الصلة بالسجلات الموجودة على اليمين. من خلال وجود الجدول الأصغر على اليسار، ستحتاج إلى مطابقة عدد أقل من السجلات، وبالتالي تسريع الاستعلام.

    في الجدول أدناه، نقوم بتقليل الجدول DeviceLogonEvents الأيسر لتغطية ثلاثة أجهزة محددة فقط قبل الانضمام إليه IdentityLogonEvents بواسطة معرفات الأمان الخاصة بالحساب.

    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 ، فسيتم إلغاء تكرار هذه الصفوف لترك صف عشوائي واحد لكل قيمة فريدة.

    يمكن أن يترك هذا السلوك الافتراضي معلومات مهمة من الجدول الأيسر يمكن أن توفر رؤى مفيدة. على سبيل المثال، سيعرض الاستعلام أدناه رسالة بريد إلكتروني واحدة فقط تحتوي على مرفق معين، حتى إذا تم إرسال نفس المرفق باستخدام رسائل بريد إلكتروني متعددة:

    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
    

    يساعد تلميح البث عندما يكون الجدول الأيسر صغيرا (حتى 100000 سجل) والجدول الأيمن كبير للغاية. على سبيل المثال، يحاول الاستعلام أدناه الانضمام إلى بعض رسائل البريد الإلكتروني التي تحتوي على مواضيع محددة مع جميع الرسائل التي تحتوي على ارتباطات في 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
    

سيناريوهات الاستعلام

تحديد العمليات الفريدة باستخدام معرفات العملية

تتم إعادة تدوير معرفات العمليات (PIDs) في Windows وإعادة استخدامها للعمليات الجديدة. من تلقاء نفسها، لا يمكن أن تعمل كمعرفات فريدة لعمليات محددة.

للحصول على معرف فريد لعملية على جهاز معين، استخدم معرف العملية مع وقت إنشاء العملية. عند ضم البيانات أو تلخيصها حول العمليات، قم بتضمين أعمدة لمعرف الجهاز (إما DeviceId أو DeviceName)، ومعرف العملية (ProcessId أو InitiatingProcessId)، ووقت إنشاء العملية (ProcessCreationTime أو InitiatingProcessCreationTime)

يبحث الاستعلام المثال التالي عن العمليات التي تصل إلى أكثر من 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"

استيعاب البيانات من مصادر خارجية

لدمج القوائم الطويلة أو الجداول الكبيرة في الاستعلام الخاص بك، استخدم عامل تشغيل البيانات الخارجية لاستيعاب البيانات من URI محدد. يمكنك الحصول على البيانات من الملفات بتنسيقات TXT أو CSV أو JSON أو تنسيقات أخرى. يوضح المثال أدناه كيف يمكنك استخدام قائمة شاملة من تجزئات 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 Tech Community.