Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Sorgularınızı iyileştirerek karmaşık sorgular çalıştırırken sonuçları daha hızlı alın ve zaman aşımlarından kaçının. Sorgu performansını geliştirme yönergeleri için:
- Genel iyileştirme ipuçları - bu makalede
-
İşleci iyileştirme
join- bu makalede -
İşleci iyileştirme
summarize- bu makalede - Sorgu senaryoları - bu makalede
- Kusto sorgu en iyi yöntemleri - sorgunuzu daha verimli hale getirmek için çeşitli senaryolar içerir
- Azure İzleyici'de günlük sorgularını iyileştirme - sorgu iyileştirme için ek yönergeler içerir
- KQL sorgularını iyileştirme (video) - sorgunuzu geliştirmenin en yaygın yolları
CPU kaynak kotalarını anlama
Boyutuna bağlı olarak, her kiracının gelişmiş tehdit avcılığı sorguları çalıştırmak için ayrılmış belirli miktarda CPU kaynağına erişimi vardır. Çeşitli kullanım parametreleri hakkında ayrıntılı bilgi için gelişmiş tehdit avcılığı kotaları ve kullanım parametreleri hakkında bilgi edinin.
Sorgunuzu çalıştırdıktan sonra yürütme süresini ve kaynak kullanımını (Düşük, Orta, Yüksek) görebilirsiniz. Yüksek, sorgunun çalıştırılması için daha fazla kaynak aldığını ve sonuçları daha verimli döndürmek için iyileştirilebileceğini gösterir.
Düzenli olarak birden çok sorgu çalıştıran müşterilerin tüketimi izlemesi ve kotaların veya kullanım parametrelerinin aşılmasından kaynaklanan kesintiyi en aza indirmek için bu makaledeki iyileştirme kılavuzunu uygulaması gerekir.
Genel iyileştirme ipuçları
Yeni sorguları boyutlandır—Bir sorgunun büyük bir sonuç kümesi döndüreceğinden şüpheleniyorsanız, önce count işlecini kullanarak sorguyu değerlendirin. Büyük sonuç kümelerini önlemek için limit veya eş anlamlısını
takekullanın.Filtreleri erken uygulama—Özellikle alt dize(), replace(), trim(), toupper()veya parse_json() gibi dönüştürme ve ayrıştırma işlevlerini kullanmadan önce veri kümesini azaltmak için zaman filtrelerini ve diğer filtreleri uygulayın. Aşağıdaki örnekte, filtreleme işleçleri kayıt sayısını azalttığı için extractjson() ayrıştırma işlevi kullanılmıştır.
DeviceEvents | where Timestamp > ago(1d) | where ActionType == "UsbDriveMount" | where DeviceName == "user-desktop.domain.com" | extend DriveLetter = extractjson("$.DriveLetter", AdditionalFields)Has beats contains—Sözcüklerin içindeki alt dizelerin gereksiz yere aranmasını önlemek için yerine işlecini
hascontainskullanın. Dize işleçleri hakkında bilgi edininBelirli sütunlara bakın— Tüm sütunlarda tam metin aramaları çalıştırmak yerine belirli bir sütuna bakın. Tüm sütunları denetlemek için kullanmayın
*.Hız için büyük/küçük harfe duyarlı— Büyük/küçük harfe duyarlı aramalar daha belirgindir ve genellikle daha yüksek performanslıdır. ve
contains_csgibihas_csbüyük/küçük harfe duyarlı dize işleçlerinin adları genellikle ile_csbiter. Yerine büyük/küçük harfe duyarlı eşittir işlecini===~de kullanabilirsiniz.Ayrıştırma, ayıklama—Mümkün olduğunda ayrıştırma işlecini veya parse_json() gibi bir ayrıştırma işlevini kullanın.
matches regexHer ikisi de normal ifade kullanan dize işlecinden veya extract() işlevinden kaçının. Daha karmaşık senaryolar için normal ifade kullanımını ayırın. İşlevleri ayrıştırma hakkında daha fazla bilgi edininTabloları ifadelere değil filtrele—Tablo sütununa göre filtre uygulanabiliyorsa hesaplanan sütuna filtre uygulamayın.
Üç karakterli terim yok— Üç veya daha az karakterle terimleri karşılaştırmaktan veya filtrelemekten kaçının. Bu terimler dizine alınmaz ve bunlar eşleştirildiğinde daha fazla kaynak gerekir.
Seçmeli olarak proje oluşturma—Yalnızca ihtiyacınız olan sütunları yansıtarak sonuçlarınızın daha kolay anlaşılmasını sağlayın. Birleştirme veya benzer işlemleri çalıştırmadan önce belirli sütunları yansıtmak da performansı artırmaya yardımcı olur.
İşleci iyileştirme join
Birleştirme işleci, belirtilen sütunlardaki değerleri eşleştirerek iki tablodaki satırları birleştirir. Bu işleci kullanan sorguları iyileştirmek için bu ipuçlarını uygulayın.
Sol tarafınızda daha küçük bir tablo—
joinİşleç, birleştirme deyiminizin sol tarafındaki tablodaki kayıtları sağdaki kayıtlara eşler. Sol tarafta daha küçük bir tablonun olması nedeniyle daha az kaydın eşleşmesi gerekir ve böylece sorgu hızlandırılır.Aşağıdaki tabloda, hesap SID'leri ile
IdentityLogonEventsbirleştirmeden önce sol tabloyuDeviceLogonEventsyalnızca üç belirli cihazı kapsayacak şekilde azaltıyoruz.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İç birleşim aromasını kullanın— Varsayılan birleşim aroması veya innerunique-join , her eşleşme için sağ tabloya bir satır döndürmeden önce sol tablodaki satırları birleştirme anahtarıyla yinelenenleri kaldırıyor. Sol tabloda anahtar için
joinaynı değere sahip birden çok satır varsa, bu satırlar her benzersiz değer için tek bir rastgele satır bırakmak üzere yinelenenleri kaldırılacaktır.Bu varsayılan davranış, sol tablodan yararlı içgörüler sağlayabilecek önemli bilgiler bırakabilir. Örneğin, aynı ek birden çok e-posta iletisi kullanılarak gönderilmiş olsa bile aşağıdaki sorguda belirli bir eki içeren yalnızca bir e-posta gösterilir:
EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256Bu sınırlamayı gidermek için, sol tablodaki tüm satırların sağda eşleşen değerlerle gösterilmesini belirterek
kind=inneriç birleşim aromasını uygularız:EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256Bir zaman penceresinden kayıtları birleştirme—Analistler güvenlik olaylarını araştırırken, aynı zaman aralığında gerçekleşen ilgili olayları arar. Kullanırken
joinaynı yaklaşımın uygulanması, denetlenecek kayıt sayısını azaltarak performansa da avantaj sağlar.Aşağıdaki sorgu, kötü amaçlı bir dosya aldıktan sonra 30 dakika içinde oturum açma olaylarını denetler:
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)Her iki tarafa da zaman filtreleri uygulayın: Belirli bir zaman penceresini araştırmasanız bile, hem sol hem de sağ tablolara zaman filtreleri uygulamak, performansı denetlemek ve iyileştirmek
joiniçin kayıt sayısını azaltabilir. Aşağıdaki sorgu her iki tablo için de geçerlidirTimestamp > ago(1h), böylece yalnızca son bir saat içindeki kayıtları birleştirir:EmailAttachmentInfo | where Timestamp > ago(1h) | where Subject == "Document Attachment" and FileName == "Document.pdf" | join kind=inner (DeviceFileEvents | where Timestamp > ago(1h)) on SHA256Performans için ipuçları kullanın— Arka uca yoğun kaynak kullanan işlemleri çalıştırırken yükü dağıtmasını bildirmek için işleçle ipuçlarını
joinkullanın. Birleştirme ipuçları hakkında daha fazla bilgi edinin.Örneğin karıştırma ipucu , aşağıdaki sorguda olduğu gibi çok sayıda benzersiz değere sahip bir anahtar olan yüksek kardinaliteye sahip bir anahtar kullanarak tabloları birleştirirken sorgu performansını artırmaya
AccountObjectIdyardımcı olur:IdentityInfo | where JobTitle == "CONSULTANT" | join hint.shufflekey = AccountObjectId (IdentityDirectoryEvents | where Application == "Active Directory" | where ActionType == "Private data retrieval") on AccountObjectIdYayın ipucu, sol tablonun küçük olması (en fazla 100.000 kayıt) ve sağ tablonun son derece büyük olması için yardımcı olur. Örneğin, aşağıdaki sorgu, tablodaki bağlantıları içeren tüm iletilere belirli konuları olan birkaç e-postayı birleştirmeye
EmailUrlInfoçalışıyor:EmailEvents | where Subject in ("Warning: Update your credentials now", "Action required: Update your credentials now") | join hint.strategy = broadcast EmailUrlInfo on NetworkMessageId
İşleci iyileştirme summarize
Summarize işleci bir tablonun içeriğini toplar. Bu işleci kullanan sorguları iyileştirmek için bu ipuçlarını uygulayın.
Ayrı değerleri bulma—Genel olarak, tekrarlanabilir ayrı değerleri bulmak için kullanın
summarize. Yinelenen değerleri olmayan sütunları toplamak için kullanmak gereksiz olabilir.Tek bir e-posta birden çok olayın parçası olabilir ancak tek bir e-postanın ağ iletisi kimliği her zaman benzersiz bir gönderen adresiyle birlikte geldiğinden
summarizeaşağıdaki örnek verimli bir kullanım değildir.EmailEvents | where Timestamp > ago(1h) | summarize by NetworkMessageId, SenderFromAddressişleci
summarizekolayca ileprojectdeğiştirilebilir ve bu da daha az kaynak tüketirken aynı sonuçları verebilir:EmailEvents | where Timestamp > ago(1h) | project NetworkMessageId, SenderFromAddressAşağıdaki örnek, aynı alıcı adresine e-posta gönderen bir gönderen adresinin birden çok farklı örneği olabileceğinden daha verimli bir kullanımıdır
summarize. Bu tür birleşimler daha az farklıdır ve yinelemeleri olabilir.EmailEvents | where Timestamp > ago(1h) | summarize by SenderFromAddress, RecipientEmailAddressSorguyu karıştırma—Yinelenen değerlere sahip sütunlarda en iyi şekilde kullanılırken
summarize, aynı sütunlar da yüksek kardinaliteye veya çok sayıda benzersiz değere sahip olabilir.joinişleci gibi, işleme yükünü dağıtmak ve yüksek kardinaliteye sahip sütunlarda çalışırken performansı artırmak için karıştırma ipucunu ilesummarizede uygulayabilirsiniz.Aşağıdaki sorgu, büyük kuruluşlarda yüz binlerde çalıştırabilen ayrı alıcı e-posta adresini saymak için kullanır
summarize. Performansı geliştirmek için şunları içerirhint.shufflekey:EmailEvents | where Timestamp > ago(1h) | summarize hint.shufflekey = RecipientEmailAddress count() by Subject, RecipientEmailAddress
Sorgu senaryoları
İşlem kimlikleriyle benzersiz işlemleri tanımlama
İşlem kimlikleri (PID) Windows'ta geri dönüştürülür ve yeni işlemler için yeniden kullanılır. Kendi başlarına, belirli işlemler için benzersiz tanımlayıcılar olarak görev yapamazlar.
Genellikle, belirli bir cihazdaki bir işlemi benzersiz olarak tanımlamanın tek yolu, işlem kimliğini işlem oluşturma zamanıyla ve cihaz tanımlayıcısıyla ( DeviceId veya DeviceName) birleştirmektir. Örneğin, aşağıdaki örnek sorgu, 445 numaralı bağlantı noktası (SMB) üzerinden 10'dan fazla IP adresine erişen işlemleri bulur ve muhtemelen dosya paylaşımlarını tarar.
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
Yukarıdaki sorgu, birden çok işlemi aynı işlem kimliğiyle karıştırmadan tek bir işleme bakması için ve her ikisine InitiatingProcessIdInitiatingProcessCreationTime göre özetler.
Bu yaklaşım, özellikle Windows dışı sistemler için hala geçerlidir. Ancak Windows'ta alanını kullanan ProcessUniqueId daha doğrudan bir yöntem vardır. Hem önceki yöntem hem de aşağıda açıklanan yöntem benzersiz işlem örnekleri sağlarken, sorguları basitleştirdiğinden ve PID yeniden kullanım senaryolarını işleme gereksinimini ortadan kaldırabileceğinden, kullanılabilir olduğunda kullanmanızı ProcessUniqueId öneririz.
Bu sorgu, belirli bir üst işlemi alt işlemlerine bağlamak için ve InitiatingProcessUniqueId alanlarının nasıl kullanılacağını ProcessUniqueId gösterir. Her alt InitiatingProcessUniqueId öğeyi üst ProcessUniqueIdöğeyle eşleştirerek, işlem kimlikleri zaman içinde yeniden kullanılıp yeniden kullanılmıyor olsa bile yalnızca tam üst örnek tarafından başlatılan alt işlemleri yalıtıyor.
Örnek sorgu:
// Step 1: Select a specific parent process instance (for instance, powershell.exe).
let parentProcess =
DeviceProcessEvents
| where FileName =~ "powershell.exe" // For your specific use case, consider modifying the FileName and adding more identifying properties to specify your query.
| where isnotempty(ProcessUniqueId)
| top 1 by Timestamp asc
| project DeviceId, DeviceName, ParentProcessUniqueId = ProcessUniqueId, ParentFileName = FileName;
// Step 2: Find all child processes started by this unique parent.
DeviceProcessEvents
| where isnotempty(InitiatingProcessUniqueId)
| join kind=inner (
parentProcess
) on DeviceId
| where InitiatingProcessUniqueId == ParentProcessUniqueId
| project
DeviceName,
ParentProcessUniqueId,
ParentFileName,
ChildProcessName = FileName,
ChildProcessId = ProcessId,
ChildProcessUniqueId = ProcessUniqueId,
Timestamp
Benzer şekilde sorgu, aynı işlem kimliğiyle birden çok işlemi karıştırmadan tek bir işleme bakması için ve her ikisine InitiatingProcessIdInitiatingProcessCreationTime göre özetler.
Sorgu komut satırları
Bir görevi gerçekleştirmek için komut satırı oluşturmanın birçok yolu vardır. Örneğin, bir saldırgan yol olmadan, dosya uzantısı olmadan, ortam değişkenlerini kullanarak veya tırnak işaretleri kullanarak bir görüntü dosyasına başvurabilir. Saldırgan ayrıca parametrelerin sırasını değiştirebilir veya birden çok tırnak işareti ve boşluk ekleyebilir.
Komut satırları çevresinde daha dayanıklı sorgular oluşturmak için aşağıdaki uygulamaları uygulayın:
- Komut satırının kendisini filtrelemek yerine dosya adı alanlarıyla eşleşerek bilinen işlemleri ( net.exeveyapsexec.exegibi) tanımlayın.
- parse_command_line() işlevini kullanarak komut satırı bölümlerini ayrıştırma
- Komut satırı bağımsız değişkenlerini sorgularken, belirli bir sırada birden çok ilişkisiz bağımsız değişkende tam eşleşme arayın. Bunun yerine normal ifadeler kullanın veya birden çok ayrı içeren işleç kullanın.
- Büyük/küçük harfe duyarsız eşleşmeler kullanın. Örneğin, ,
in~vecontainsyerine==,invecontains_cskullanın=~. - Komut satırı gizleme tekniklerini azaltmak için tırnak işaretleri kaldırmayı, virgülleri boşluklarla değiştirmeyi ve ardışık birden çok boşluğu tek bir boşlukla değiştirmeyi göz önünde bulundurun. Başka yaklaşımlar gerektiren daha karmaşık karartma teknikleri vardır, ancak bu ince ayarlar yaygın olanları gidermeye yardımcı olabilir.
Aşağıdaki örneklerde, "MpsSvc" güvenlik duvarı hizmetini durdurmak için dosya net.exe arayabilen bir sorgu oluşturmanın çeşitli yolları gösterilir:
// 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"
Dış kaynaklardan veri alma
Uzun listeleri veya büyük tabloları sorgunuza eklemek için externaldata işlecini kullanarak belirtilen URI'den veri alın. TXT, CSV, JSON veya diğer biçimlerdeki dosyalardan veri alabilirsiniz. Aşağıdaki örnekte, e-postalardaki ekleri denetlemek için MalwareBazaar (abuse.ch) tarafından sağlanan kapsamlı kötü amaçlı yazılım SHA-256 karmalarını nasıl kullanabileceğiniz gösterilmektedir:
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
Dizeleri ayrıştırma
Ayrıştırma veya dönüştürme gerektiren dizeleri verimli bir şekilde işlemek için kullanabileceğiniz çeşitli işlevler vardır.
| Dize | İşlev | Kullanım örneği |
|---|---|---|
| Komut satırları | parse_command_line() | Komutu ve tüm bağımsız değişkenleri ayıklayın. |
| Yol | parse_path() | Dosya veya klasör yolunun bölümlerini ayıklayın. |
| Sürüm numaraları | parse_version() | En fazla dört bölüm ve bölüm başına en fazla sekiz karakter içeren bir sürüm numarasının yapısı kaldırılır. Sürüm yaşını karşılaştırmak için ayrıştırılmış verileri kullanın. |
| IPv4 adresleri | parse_ipv4() | IPv4 adresini uzun bir tamsayıya dönüştürün. IPv4 adreslerini dönüştürmeden karşılaştırmak için ipv4_compare() kullanın. |
| IPv6 adresleri | parse_ipv6() | IPv4 veya IPv6 adresini kurallı IPv6 gösterimine dönüştürün. IPv6 adreslerini karşılaştırmak için ipv6_compare() kullanın. |
Desteklenen tüm ayrıştırma işlevleri hakkında bilgi edinmek için Kusto dize işlevleri hakkında bilgi edinin.
Not
Bu makaledeki bazı tablolar Uç Nokta için Microsoft Defender'de kullanılamayabilir. Daha fazla veri kaynağı kullanarak tehditleri avlamak için Microsoft Defender XDR açın. Gelişmiş tehdit avcılığı sorgularını Uç Nokta için Microsoft Defender'den geçirme bölümünde yer alan adımları izleyerek gelişmiş avcılık iş akışlarınızı Uç Nokta için Microsoft Defender'den Microsoft Defender XDR taşıyabilirsiniz.
İlgili konular
- Kusto sorgu dili belgeleri
- Kotalar ve kullanım parametreleri
- Gelişmiş tehdit avcılığı hatalarını işleme
- Gelişmiş avcılığa genel bakış
- Sorgu dilini öğrenin
İpucu
Daha fazla bilgi edinmek mi istiyorsunuz? Teknoloji Topluluğumuzdaki Microsoft Güvenlik topluluğuyla etkileşime geçin: Microsoft Defender XDR Teknoloji Topluluğu.