EF Core'da Sıfır Güven, Kurcalama Belirgin Denetim İzi Oluşturma (Ve Standart Günlükler Neden Başarısız?)
Çoğumuz bir noktada bir denetim kayıt sistemi kurmuşuzdur. Standart oyun kitabı tahmin edilebilir: Entity Framework Core'un SaveChanges önleyicisine bağlanırsınız veya bir veritabanı tetikleyicisi yazarsınız, OldValues ve NewValues'u JSON olarak yakalar, bunu bir Kullanıcı Kimliği ve Zaman Damgası ile damgalar ve bir AuditLogs tablosuna kaydedersiniz.
Yönetim mutlu. Uyumluluk kontrol listesi işaretlenir.
Ancak bu mimaride çok büyük bir kör nokta var: Verilere müdahale eden kişi Veritabanı Yöneticisi (DBA) veya doğrudan üretim erişimine sahip bir geliştirici ise ne olur?
Geleneksel denetim günlükleri kanıt değil geçmiş sağlar. Bir saldırgan (veya güvenliği ihlal edilmiş bir yönetici hesabı) bir mali kaydı değiştirirse, izlerini kapatmak için AuditLogs tablosunda kolayca GÜNCELLEME veya SİLME işlemi gerçekleştirebilir.
Bunu çözmek için "Bana Güvenin" günlük kaydından Sıfır Güven, Kurcalama Belirgin günlük kaydına geçmemiz gerekiyor.
Tam olarak bu soruna açık kaynaklı bir mimari çözüm olan EfCore.TamperEvident'i nasıl oluşturduğumu ve bu süreçte üstesinden gelmek zorunda kaldığım mühendislik engellerini burada anlatacağım.
Temel Konsept: Kriptografik Karma Zincirleme
Bir veritabanının kurcalanmasını açık hale getirmek için blockchain'in temel konseptini ödünç alıyoruz: Kriptografik Hash Zincirleri.
Satırları bağımsız olarak kaydetmek yerine, her bir denetim günlüğü, kendisinden hemen önce gelen günlüğe matematiksel olarak bağlanır.
Bir kayıt güncellendiğinde sistem, yükü (Tablo, Eylem, JSON değerleri, Zaman Damgası) ARTI önceki işlemin karmasını içeren bir SHA-256 karması oluşturur.
CurrentHash = SHA256(PreviousHash + TableName + RecordId + Action + Payload + Timestamp)
Birisi geçmiş bir kaydı manuel olarak değiştirirse veya bir satırı silerse, o satırın CurrentHash değeri değişir. Bir sonraki satır eski hash'e dayandığından zincir anında kırılır. Bir doğrulama motoru tabloyu tarayabilir ve manipülasyonun gerçekleştiği tam kimliği gösterebilir.
3 Büyük Mühendislik Engeli
Bunu yüksek trafikli bir CRM veya ERP'ye uygulamak, dizeleri karma haline getirmek kadar basit değildir. Üç kritik sorunu çözmem gerekiyordu:
- "Karma Yeniden Hesaplama" Saldırısı (DBA Kaçağı)
Sorun: Hash zincirleri normal kullanıcılara karşı koruma sağlıyor. Ancak tam erişime sahip bir DBA, 3 ay önceki bir kaydı değiştirebilir, o noktadan günümüze kadar olan tüm karmaları yeniden hesaplamak için hızlı bir komut dosyası yazabilir ve tüm AuditLogs tablosunu sessizce güncelleyebilir. Zincir tamamen geçerli görünecektir.
Çözüm (SMTP Bağlantısı): Veritabanının kendisini doğrulayacağına güvenilemez. Periyodik olarak (örneğin her 500 kayıtta bir), önleyici bir "Kök Karması" oluşturur ve bunu güvenli, harici bir uyumluluk gelen kutusuna e-postayla gönderir. Bir DBA geçmişi yeniden yazarsa, veritabanındaki yeni karmalar hiçbir zaman o harici gelen kutusunda depolanan bağlantılarla eşleşmeyecektir.
- Otomatik Artış (KİMLİK) Kabusu
Sorun: EF Core'a yeni bir varlık eklerken, Birincil Anahtar genellikle veritabanına kaydedilene kadar 0'dır. Hash'inizi kaydetmeden önce oluşturursanız hash'iniz kimlik olarak 0'ı kullanır. Doğrulama motoru daha sonra çalıştığında gerçek kimliği okur (örneğin, 45), karmayı yeniden hesaplar ve başarısız olur.
Çözüm: İki Fazlı Kesinti Önleyiciyi uygulamak zorunda kaldım. SavingChangesAsync'de (Aşama 1) orijinal JSON durumlarını yakalar, veritabanının kimliği oluşturmasına izin verir ve ardından karma değerini güvenli bir şekilde hesaplar ve günlüğü SavedChangesAsync'e (Aşama 2) kaydeder; tüm bunları yaparken, bellek sızıntılarını önlemek için ConditionalWeakTable'ı kullanarak her şeyi tek bir atomik veritabanı işleminde tutar.
- Eşzamanlılık ve Yarış Koşulları
Sorun: Eğer 50 kullanıcı Siparişler tablosunu tam olarak aynı milisaniyede güncellerse, hepsi aynı Önceki Hash'ı okur. Bu, denetim izinin bütünlüğünü tamamen yok eden bir zincir çatalı yaratır.
Çözüm: Yerel satır düzeyinde kilitleme. Karmayı hesaplamadan önce, önleyici bir durum tablosuna deterministik bir kilit (SQL Server'da UPDLOCK, PostgreSQL/MySQL'de FOR UPDATE) uygular. Bu, tüm veritabanını kilitlemeden eşzamanlı işlemleri katı, milisaniye düzeyinde bir kuyruğa zorlar.
EfCore.TamperEvident ile tanışın
Her proje için tekerleği yeniden icat etmek yerine, tüm bu mimariyi tak ve çalıştır bir NuGet kitaplığında paketledim: EfCore.TamperEvident.
Kutudan çıktığı haliyle SQL Server, PostgreSQL ve MySQL'i destekler. İş mantığınızı değiştirmenize gerek yok. Tabloları DbContext'inize eklemeniz ve önleyiciyi kaydetmeniz yeterlidir:
C#
inşaatçı.Hizmetler.AddDbContext<MyDbContext>(seçenekler =>
{
seçenekler.SQLServer'ı kullanın("...");
seçenekler.KullanımTamperEvidentAudit(denetim =>
{
denetim.Db Sağlayıcı = Veritabanı Sağlayıcısı.SqlServer;
denetim.Takip Edilenİşlemler = Denetimİşlemi.Tüm;
// DBA Karşıtı Sabitleme
denetim.ÇapaEşik = 500;
denetim.SmtpHost = "smtp.company.com";
// ... SMTP kimlik bilgileri ...
});
});
_context.SaveChangesAsync() işlevini her çağırdığınızda, kitaplık arka planda güvenli bir şekilde karma zinciri oluşturur.
Kötü niyetli bir oyun olduğundan şüpheleniyorsanız, tabloyu anında denetlemek için doğrulama motorunu (e-postanızdaki bağlantı anahtarlarını ileterek) çalıştırabilirsiniz:
C#
var doğrulayıcı = yeni Denetim Doğrulayıcı(_bağlam);
var sonuç = beklemek doğrulayıcı.VerifyTableIntegrityAsync("Emirler", sağlananÇapalar);
// Çıktı: "GÜVENLİK UYARISI: MANİPÜLASYON! Kayıt ID'si: 847'nin yükü harici olarak değiştirildi."
Kapanış
Kendi veritabanı yöneticilerinin düşmanca olabileceğini varsayan bir sistem oluşturmak, yazılım tasarlama şeklinizi temelden değiştirir. FinTech, Sağlık Hizmeti (HIPAA) veya uyumluluk ağırlıklı kurumsal sistemler oluşturuyorsanız, standart denetim günlükleri yalnızca yanlış bir güvenlik duygusudur.
Projenin tamamını açık kaynaklı hale getirdim. Kaynak kodunu kontrol edebilir, iki aşamalı taahhüt mantığını inceleyebilir veya buradaki depoya bir yıldız bırakabilirsiniz:
🔗 [GitHub Depo Bağlantısı - https://github.com/furkiak/EfCore.TamperEvident]
📦 [NuGet Paket Bağlantısı - https://www.nuget.org/packages/EfCore.TamperEvident/]
Bu mimari hakkındaki düşüncelerinizi duymak isterim. Şu anda sistemlerinizde yüksek düzeyde bütünlüklü denetim kayıtlarını nasıl yönetiyorsunuz? Yorumlarda tartışalım!