Bu rehberde osquery'yi tek uç noktada kullanmaktan başlayıp, Fleet ile yüzlerce makineyi merkezî olarak yönetmeye, zamanlanmış sorgularla sürekli tespit üretmeye ve sonuçları SIEM'e akıtmaya kadar uçtan uca bir kurulum kuruyoruz.
1. osquery nedir, ne değildir?
osquery; Linux, macOS, Windows ve FreeBSD üzerinde çalışan açık kaynaklı bir uç nokta görünürlüğü aracıdır. İki temel bileşeni vardır:
- osqueryi — etkileşimli kabuk. Elle sorgu çalıştırmak, keşif ve geliştirme için kullanılır.
- osqueryd — arka plan servisi. Zamanlanmış sorguları periyodik çalıştırır, sonuçların farkını (diff) alır ve günlüğe yazar.
Kritik ayrım şudur: osquery bir EDR değildir. Süreç sonlandırmaz, dosya karantinaya almaz, saldırıyı engellemez. Yaptığı iş görünürlük ve tespit sinyali üretmektir. Engelleme katmanı için eBPF tabanlı çalışma zamanı araçları ya da klasik EDR ürünleri gerekir; osquery bunların yanında envanter ve tehdit avcılığı katmanı olarak konumlanır.
Bir diğer ayrım da gerçek zamanlılıktır. Varsayılan çalışma modeli anlık görüntü (snapshot) tabanlıdır: sorgu her interval saniyede bir çalışır ve iki çalışma arasında doğup ölen kısa ömürlü bir süreç kaçabilir. Süreç ve soket olaylarını kaçırmadan yakalamak için olay tabanlı tablolara geçmek gerekir; buna aşağıda değiniyoruz.
2. Kurulum ve ilk sorgular
Debian/Ubuntu üzerinde resmî depodan kurulum:
CODE TERMINAL
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://pkg.osquery.io/deb/pubkey.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/osquery.gpg
echo "deb [arch=amd64 signed-by=/etc/apt/keyrings/osquery.gpg] https://pkg.osquery.io/deb deb main" | sudo tee /etc/apt/sources.list.d/osquery.list
sudo apt update && sudo apt install -y osqueryEtkileşimli kabuğu açıp tabloları keşfedin:
CODE TERMINAL
sudo osqueryi
osquery> .tables
osquery> .schema listening_ports
osquery> SELECT version FROM osquery_info;Klasik ilk sorgu — internete açık dinleyen servisleri süreç bilgisiyle birleştirmek:
CODE TERMINAL
SELECT DISTINCT
p.name AS surec,
p.path AS yol,
l.port AS port,
l.protocol AS protokol,
l.address AS adres,
u.username AS kullanici
FROM listening_ports l
JOIN processes p ON l.pid = p.pid
LEFT JOIN users u ON p.uid = u.uid
WHERE l.address NOT IN ('127.0.0.1', '::1')
ORDER BY l.port;Bu tek sorgu, "hangi servis hangi portu tüm arayüzlerde dinliyor ve hangi kullanıcı olarak çalışıyor" sorusunu bir SSH oturumu kadar hızlı yanıtlar.
3. Tehdit avcılığı için işe yarayan sorgular
3.1 Kalıcılık: şüpheli systemd birimleri ve cron girdileri
CODE TERMINAL
SELECT name, description, fragment_path, user
FROM systemd_units
WHERE fragment_path NOT LIKE '/lib/systemd/%'
AND fragment_path NOT LIKE '/usr/lib/systemd/%'
AND fragment_path != '';
SELECT command, path, minute, hour, day_of_month
FROM crontab
WHERE command LIKE '%curl%'
OR command LIKE '%wget%'
OR command LIKE '%base64%'
OR command LIKE '%/tmp/%';3.2 Diskte olmayan ikililer (silinmiş süreç dosyaları)
Zararlı yazılımların klasik davranışı, çalıştıktan sonra kendi ikilisini silmektir. osquery bunu doğrudan görür:
CODE TERMINAL
SELECT p.pid, p.name, p.path, p.cmdline, p.start_time
FROM processes p
LEFT JOIN file f ON p.path = f.path
WHERE p.path != '' AND f.path IS NULL;3.3 Yazılabilir dizinlerden çalışan süreçler
CODE TERMINAL
SELECT pid, name, path, cmdline, uid
FROM processes
WHERE path LIKE '/tmp/%'
OR path LIKE '/dev/shm/%'
OR path LIKE '/var/tmp/%';3.4 SUID ikili denetimi
CODE TERMINAL
SELECT path, permissions, uid, gid
FROM suid_bin
WHERE path NOT LIKE '/usr/bin/%'
AND path NOT LIKE '/bin/%'
AND path NOT LIKE '/usr/sbin/%';3.5 SSH sunucu sertleştirme doğrulaması
Tek bir sorguyla tüm filodaki zayıf SSH yapılandırmalarını bulabilirsiniz:
CODE TERMINAL
SELECT key, value
FROM augeas
WHERE path = '/etc/ssh/sshd_config'
AND key IN ('PermitRootLogin', 'PasswordAuthentication', 'PermitEmptyPasswords');3.6 Windows tarafında hızlı kazanımlar
CODE TERMINAL
SELECT name, path, source, status
FROM autoexec;
SELECT name, action, enabled, local_port, remote_address
FROM windows_firewall_rules
WHERE action = 'Allow' AND enabled = 1 AND remote_address = '*';4. Zamanlanmış sorgular ve fark (diff) mantığı
Asıl güç, sorguların osqueryd ile zamanlanmasında ortaya çıkar. /etc/osquery/osquery.conf içinde:
CODE TERMINAL
{
"options": {
"logger_path": "/var/log/osquery",
"schedule_splay_percent": 10,
"disable_events": false,
"enable_bpf_events": true,
"events_expiry": 3600,
"host_identifier": "hostname"
},
"schedule": {
"dinleyen_portlar": {
"query": "SELECT DISTINCT p.name, p.path, l.port, l.protocol FROM listening_ports l JOIN processes p ON l.pid = p.pid WHERE l.address NOT IN ('127.0.0.1','::1');",
"interval": 600,
"description": "Acik portlarda degisiklik takibi"
},
"yeni_kullanicilar": {
"query": "SELECT uid, gid, username, shell, directory FROM users;",
"interval": 3600,
"removed": true
},
"suid_degisiklikleri": {
"query": "SELECT path, permissions, uid FROM suid_bin;",
"interval": 86400
},
"kernel_modulleri": {
"query": "SELECT name, size, status FROM kernel_modules;",
"interval": 1800
}
}
}Burada anlaşılması gereken iki ayar var:
- removed — varsayılanı true'dur ve bir satır kaybolduğunda da olay üretir. Sürekli değişen tablolarda gürültüyü azaltmak için false yapın; kullanıcı ve port gibi tablolarda ise silinme olayı kıymetlidir, açık bırakın.
- snapshot — true yapıldığında fark alınmaz, her çalışmada tam tablo yazılır. Envanter raporlaması için uygundur ama günlük hacmini ciddi biçimde büyütür.
schedule_splay_percent ayarını atlamayın: yüzlerce uç noktanın aynı saniyede ağır bir sorguyu çalıştırmasını önler.
5. Anlık görüntü yetmediğinde: olay tabanlı tablolar
Kısa ömürlü süreçleri yakalamak için olay tabloları gerekir. Modern çekirdeklerde önerilen yol eBPF tabanlı yayımcıdır:
CODE TERMINAL
{
"options": {
"disable_events": false,
"enable_bpf_events": true
},
"schedule": {
"surec_olaylari": {
"query": "SELECT pid, parent, path, cmdline, uid, time FROM bpf_process_events;",
"interval": 60,
"removed": false
}
}
}Eski sistemlerde enable_bpf_events yerine auditd tabanlı process_events tablosu kullanılır; bu durumda disable_audit kapalı olmalı ve osquery'nin audit netlink soketini ele almasına izin verilmelidir. Aynı makinede hem auditd hem osquery'nin audit kuyruğuna talip olması klasik bir çakışma kaynağıdır; birini seçin.
Uyarı: Olay tabloları disk ve CPU maliyetini belirgin biçimde artırır. events_expiry değerini düşük tutun ve olay sorgularını yalnızca gerçekten ihtiyaç duyulan sunucu gruplarında etkinleştirin.
6. Fleet ile merkezî yönetim
Tek makinede osquery güçlüdür; 500 makinede yapılandırma dosyasını elle dağıtmak sürdürülemez. Fleet, osquery ajanlarını merkezden yöneten açık kaynaklı sunucudur: canlı sorgu (live query) çalıştırır, zamanlanmış sorgu paketlerini dağıtır, envanter tutar ve sonuçları bir günlük hedefine iletir.
Değerlendirme amaçlı hızlı bir kurulum:
CODE TERMINAL
fleet prepare db --mysql_address=127.0.0.1:3306 --mysql_database=fleet --mysql_username=fleet
fleet serve \
--mysql_address=127.0.0.1:3306 \
--mysql_database=fleet \
--redis_address=127.0.0.1:6379 \
--server_cert=/etc/fleet/fleet.crt \
--server_key=/etc/fleet/fleet.key \
--logging_jsonUç noktalara ajan dağıtımı fleetctl ile üretilen paketler üzerinden yapılır:
CODE TERMINAL
fleetctl package --type=deb --fleet-url=https://fleet.example.org --enroll-secret=KAYIT_SIRRI
fleetctl package --type=msi --fleet-url=https://fleet.example.org --enroll-secret=KAYIT_SIRRIFleet'in en değerli tarafı, yapılandırmayı sürüm kontrollü YAML olarak tutabilmenizdir:
CODE TERMINAL
apiVersion: v1
kind: query
spec:
name: diskte-olmayan-ikililer
description: Calisan ama diskte bulunmayan surecler
query: >
SELECT p.pid, p.name, p.path, p.cmdline
FROM processes p LEFT JOIN file f ON p.path = f.path
WHERE p.path != '' AND f.path IS NULL;
interval: 900
platform: linux
observer_can_run: trueCODE TERMINAL
fleetctl apply -f sorgular/diskte-olmayan-ikililer.ymlBöylece tespit mantığınız kod olarak incelenebilir, gözden geçirilebilir ve geri alınabilir hâle gelir.
7. Güvenlik: osquery'nin kendisi bir saldırı yüzeyidir
Filodaki her makinede yüksek yetkiyle çalışan ve uzaktan sorgu alan bir ajan kurduğunuzu unutmayın. Asgari önlemler:
- Kayıt sırrını (enroll secret) döndürün. Sızan bir sır, sahte uç noktaların filoya katılmasına izin verir. Fleet üzerinde birden fazla sır tanımlayıp kademeli olarak döndürün.
- TLS sertifikasını sabitleyin. Ajan tarafında tls_server_certs ile beklenen CA'yı belirtin; araya girme denemelerini kırar.
- Rol ayrımı uygulayın. Fleet'teki observer rolü yalnızca işaretlenmiş sorguları çalıştırabilir; canlı sorgu yetkisini herkese vermeyin.
- Dosya taşıma (carve) özelliğini kapalı tutun. Açıldığında, sorgu yetkisi olan biri uç noktalardan dosya çekebilir. Yalnızca gerektiğinde ve denetim kaydıyla açın.
- Uzantı (extension) soketini koruyun. osquery.em soketi üzerinde yazma yetkisi olan bir kullanıcı, osquery sürecinde kod çalıştırabilir; izinler 0600 ve sahibi root olmalıdır.
- Yapılandırma dosyasını yazmaya kapatın. osquery.conf üzerinde yazma yetkisi, planlanmış sorgular üzerinden kalıcılık anlamına gelir.
- Canlı sorguları denetleyin. Fleet'in etkinlik (activity) günlüğünü SIEM'e gönderin; "kim, hangi makinede, ne sordu" kaydı olay sonrası inceleme için kritiktir.
8. Performans: filoyu yere sermeden izlemek
osquery'nin en sık şikâyet edilen tarafı, kötü yazılmış bir sorgunun üretim sunucusunu yormasıdır. Pratik kurallar:
- Yeni sorgunun maliyetini önce ölçün; CPU ve bellek etkisini bilmeden zamanlamaya eklemeyin.
- watchdog_level ve watchdog_memory_limit ayarlarını üretim profiline göre belirleyin; osquery kendi bekçisiyle sınırı aşan işçi sürecini sonlandırır.
- SELECT * kullanmayın. Özellikle file, hash ve yara tablolarında sütun seçimi doğrudan maliyettir.
- file ve hash tablolarını mutlaka WHERE path LIKE ... ile sınırlayın; kısıtsız sorgu tüm dosya sistemini gezer.
- Ağır envanter sorgularını uzun aralıklara (86400) yayın, tespit sorgularını kısa aralıkta tutun.
- interval değerlerinin ortak katlarından kaçının; aksi hâlde sorgular aynı anda tetiklenir.
9. Sonuçları SIEM'e taşımak
osquery sonuçları satır başına bir JSON nesnesi olarak yazar. action alanı added veya removed değerini taşır; columns altında sorgu sonucu, name altında zamanlanmış sorgunun adı bulunur. Bu yapı Filebeat, Fluent Bit veya Vector ile doğrudan toplanabilir:
CODE TERMINAL
[INPUT]
Name tail
Path /var/log/osquery/osqueryd.results.log
Parser json
Tag osquery.results
[OUTPUT]
Name opensearch
Match osquery.*
Host siem.example.org
Port 9200
Index osquery-results
tls OnTespit kurallarınızı name alanına göre yazın: örneğin name = "diskte-olmayan-ikililer" ve action = "added" eşleşmesi doğrudan bir uyarıya bağlanabilir. Fleet kullanıyorsanız aynı akışı Fleet'in günlük hedefi üzerinden merkezden yönlendirebilir, uç noktalarda ayrı bir toplayıcı çalıştırmaktan kurtulursunuz.
10. Aşamalı devreye alma planı
| Aşama | Kapsam | Hedef |
|---|---|---|
| 1. Hafta | 10-20 makinelik pilot, yalnızca envanter sorguları | Temel çizgiyi (baseline) çıkarmak ve maliyeti ölçmek |
| 2-3. Hafta | Pilotta tespit sorguları ve fark günlükleri | Yanlış pozitifleri ayıklamak, aralıkları ayarlamak |
| 4. Hafta | Fleet kurulumu, YAML ile sorguların sürümlenmesi | Yapılandırmayı merkezîleştirmek |
| 5-6. Hafta | Kademeli filo dağıtımı (yüzde 10, 50, 100) | Performans gerilemesini erken yakalamak |
| 7. Hafta | SIEM entegrasyonu ve uyarı kuralları | Tespitleri müdahale sürecine bağlamak |
| Sürekli | Olay tablolarını seçili kritik sunucularda açmak | Kısa ömürlü süreç görünürlüğü |
Sonuç
osquery, uç nokta güvenliğinde "elimizde ne var, ne değişti" sorusunu ucuz ve tekrarlanabilir biçimde yanıtlayan bir araçtır. Fleet eklendiğinde bu yetenek tek makineden filoya ölçeklenir ve tespit mantığı sürüm kontrollü koda dönüşür. Engelleme katmanının yerini almaz; ancak Sysmon, Zeek, Suricata ve Wazuh gibi araçlarla birlikte kurulduğunda, olay müdahalesinde en çok ihtiyaç duyulan şeyi sağlar: sorulabilir bir uç nokta envanteri.
TR Siber Ekibi