Güvenlik

Bir Veritabanı Sunucusuna Brute Force ile Saldırmak ve Sunucuyu Savunmak

Siber güvenlik denilince aklımıza hep web üzerinden yapılan saldırılar geliyor. Yani dışarıdan yapılan saldırılar. Hadi biraz kafanızı karıştırayım.
“Düşman ya içerideyse?”
Yani sizin her gün çay kahve içtiğiniz kişi aslında sizin verilerinizin peşindeyse?
Her gün bu paranoya ile geçer mi? İnsan psikolojisini bozacak derecede büyük bir şüphecilik durumu.
Tabi ki herkesten şüphelenmeyeceğiz. Ama bu durum önlem almamıza da engel değil tabiki.
Şimdi düşünün. Bir veritabanınız var diyelim MSSQL Server. Burada şirketinizin finans, muhasebe, arge, ürün tasarımı gibi çok önemli verileriniz var. Bu verilerin güvenliği 3 türlü tehlikede.
1.Veriler silinebilir
2.Değiştirilebilir
3.Rakip firmanın eline geçebilir

Hangisi daha tehlikeli, hangisi daha riskli firmaya göre kişiye göre değişir tabi. Ama risk risktir.
Veritabanlarına saldırılar bir çok yöntemle yapılabilir. Ama ben burada rastgele şifre deneme yöntemi olan Brute Force saldırılarından bahsedeceğim.
Normalde bir veritabanı sisteminde sistemin sürekli yanlış şifre girildiğinde bir saldırı olduğunu tespit etmesini bekleriz.
Aşağıdaki sahneyi hepimiz biliriz. Kemal Sunal’ın Şabanoğlu Şaban filminden parola sorma sahnesi.

İkili arasında şu diyalog geçer.
-3’e kadar sayacağım çabuk parolayı söyle! 1!
-Parolaaaa “Şey”
-Parola “Şey” değil 2!
-Parolaaaa “Dur bulucam”
-Parola “Dur bulacam” da değil 3!
-Hah! Buldum. “Başak”
-Bilemedin “Şafak”!

Olması gereken bir durumun örneğidir aslında bu dialog. 3 kez şifreyi yanlış giriyorsa girmek isteyen kişi bloklanmalıdır.
Gerçekte durum nasıl bir de ona bakalım.
Bir MSSQL veritabanı sisteminde sistem size istediğiniz kadar yanlış şifre girmenize izin verir. Yani sizin kötü niyetli olup olmadığınızı algılamaz. Bununla alakalı bir ayar da yoktur. Sistem bize bu fırsatı veriyorsa saldırgana kalan sürekli şifre kombinasyonları deneyerek şifreyi bulmaya çalışmaktır.
Bir MSSQL veritabanına giriş için ihtiyacınız olanlar şunlardır.
1.Fiziksel bağlantı
2.1433 portunun açık olması
3.Kullanıcı adı
4.Şifre

Şimdi düşünelim.
SQL sunucunuz internete açık değil. O zaman saldırgan dışarıdan saldıramaz. Çünkü fiziksel bağlantı yok.
SQL sunucunuz internete çıkabiliyor ama 1433 portu kapalı. Fiziksel bağlantı var ama port kapalı yine giremez.
SQL Sunucunuz internete çıkabiliyor ve evden vpnsiz bağlanmak için 1433 ü açtınız. Bu durumda saldırgan kullanıcı adı ve şifreyi tahmin etmeli. Türkiye’de neredeyse MSSQL kullananların %99 u default admin olan “SA” kullanıcısını disable etmiyor. O zaman geriye ne kaldı? Şifreyi tahmin etmek.
“safak” şifresi İngiliz alfabesi ile 26 karakterin 5 li kombinasyonu ile bulunabilir.
Yani 26x26x26x26x26 =11.881.376 farklı şifre kombinasyonu.
Diyelim ki saldırgan internete üzerinden saniyede 10 şifre deneyebiliyor.
Bu da 11.881.376/10=1188137.6 Sn, 19.802 Dakika,330 Saat, 13.75 Gün demektir.
Peki saldırgan içeriden saldırıyorsa durum nasıl?
Bir çok işletmede GBit bağlantı hızı ve i5,i7 ayarında kullanıcı bilgisayarları var.
Bu durumda saniyede 5.000 şifreye kadar deneyebilirsiniz.
Bu da şu anlama gelir.
11.881.376/5.000= 2.376 Sn, 39 Dk
39 dakikada şifreyi kırabiliyorsunuz demektir.
Hemen aklımıza şu soru geliyor değil mi? “5 karakter şifre mi olur?”
Doğru olmaz. Ama 5 karakterden fazla olan,büyük küçük harf olan bir şifrenin kırılması için gereken zaman biraz daha fazla zamandır. Belki 1 gün, belki 1 hafta, belki 1 ay.
Ama sonuçta biz sistem yöneticilerine düşen böyle bir saldırıyı
1.Tespit etmek
2.Kayıt altına almak
3.Saldırıyı engellemek
4.Mümkünse saldırganı oyalayıp onu iş üstünde yakalamaktır.

İşte bugün bu makalede bu durumu nasıl yapacağımızı anlatacağım.
Aşağıda resmini gördüğünüz uygulama sisteme sürekli şifre deniyor. Denedikleri şifreler ise bir kombinasyon değil internette bolca bulabileceğiniz 2.000.000 şifreden oluşan bir şifre sözlüğündeki şifreler.
Benim yazdığım çok basit bir uygulama. Tek thread kullanıyor ve yaklaşık 1 sn de 500 şifre deneyerek şifreyi kırdı.

Uygulamayı kaynak kodları ve 2.000.000 satırlık şifre sözlüğü ile birlikte buradan indirebilirsiniz.
https://drive.google.com/open?id=1hTYb-uxlxpwNUH3AZguF81vVltjnGbGn

Şifre sözlüğü ise bu şekilde.

Birileri şifremizi bu şekilde kırarken biz elimiz kolumuz bağlı oturacak mıyız?
Tabi ki Hayır!
SQL Server’da Server Properties’e tıkladığımızda orada “Login Auditing” yazan bir bölüm görürüz.

Burada login işlemlerinden hangisini loglamak istediğimizi belirtiriz.
None dersek hiçbir şeyi kayıt altına almaz.
Failed logins only dersek ki default u budur, o zaman sadece hata veren login işlemlerini kayıt altına alır.
Successfull logins only dersek sadece başarılı girişleri kayıt altına alır.
Both failed and sucessfull logins dersek de her ikisini de kayıt altına alır.

Şimdi bu logları nasıl görüyoruz ona bakalım.
Bunun için,
Management Studio da, Management bölümünde, SQL Server Logs sekmesine girip Current Logs menüsüne tıkladığımızda bu logları görebiliriz.


Baktığımız zaman loglarda çok sayıda “Login Failed for user ‘SA’ Reason: Password did not match that fort he login provided. [CLIENT:192.168.182.1]” kayıtlarını görüyoruz.
İşte bu durum bize bir şifre denemesi yapıldığını gösteriyor. Üstelik hangi ip den yapıldığı bilgisi de elimizde mevcut.
Peki bu saldırıyı anlamak için bu ekrana sürekli bakmamız mı gerekiyor?
Bu soruyu sorunca Vizontele’de Artos Dağı’nda yayın geldiğinde haber vermesi için bekleyen zabıta geliyor aklıma nedense 🙂

Böyle yapmayacağız tabiki.
Ne demiştik? SQL Server geri planda SQL dilinden başka bir şeyden anlamaz.
Yani bizim önümüze gelen log bilgisini geri planda getiren bir sql cümlesi var.
“EXEC XP_ReadErrorLog”

Madem elimizde böyle bir komut var o zaman şöyle bir senaryo nasıl olur dersiniz?
Sistem 3 dakikada bir çalışsın
Bu logları okusun
İçinde “Login Failed for user ‘SA’ Reason: Password did not match that fort he login provided.” cümlesinden şayet 100’den fazla geçiyorsa bir saldırı olduğunu tespit etsin. Burada 100 sembolik bir rakam. Daha az ya da daha fazla verebilirsiniz.
Peki “EXEC XP_ReadErrorLog” gibi hazır bir sorguyu nasıl filtreleriz.
Çok kolay. Temp table kullanarak yapabiliriz. Temp table lar hafızada oluşturulan ve sonra yok olan tablolardır.


CREATE TABLE #SQLErrorLog
(
LogDate DATETIME ,
ProcessInfo VARCHAR(20) ,
Text VARCHAR(500)
);

INSERT INTO #SQLErrorLog
EXEC xp_readerrorlog 0;
SELECT * FROM #SQLErrorLog
WHERE Text LIKE ‘%Login failed for user%’
AND LogDate >= DATEADD(MINUTE, -1 * 3, GETDATE())

Görüldüğü gibi sisteme son 3 dakika içerisinde 476 kez şifre denemesi yapıldığını anlayabiliyoruz.

Şimdi burada yapmamız gereken burada ip yi tespit etmek ve db admine haber vermek. Bunun için SQL Server’da DB Mail aktif etmemiz gerekiyor. SQL DB Mail kurulumu aşağıdaki gibi.





Şimdi bir test maili gönderelim.



SQL Server tarafından gönderdiğimiz mail alındı.


EXEC msdb.dbo.sp_send_dbmail
@profile_name = ‘sqlegitim’,
@recipients = ‘[email protected]’,

@subject = ‘Brute Force Saldırısı’,
@body=’Sisteminize 01:30:00 ile 01:33:00 saatleri arasında 192.168.189.1 ip li makineden 475 kez şifre denemesi yapılmıştır.’

Mail sistemini aktif ettikten sonra anlamlı bir cümle ile db admine mail göndermemiz gerekiyor. Yine mail gönderme işlemi de aslında bir TSQL komutudur.

Şimdi bu işlemi otomatik yapacak bir sorgu yazalım.

CREATE PROC BRUTFORCE_CONTROL @MINUTE AS INT = 3
AS
    BEGIN
CREATE TABLE #SQLErrorLog
    (
        LogDate DATETIME ,
        ProcessInfo VARCHAR(20) ,
        Text VARCHAR(500)
    );
INSERT  INTO #SQLErrorLog
        EXEC xp_readerrorlog 0;
        DECLARE @TEXT AS VARCHAR(1000);
        DECLARE @COUNT AS INT; 
        DECLARE @MINDATE AS DATETIME;
        DECLARE @MAXDATE AS DATETIME;
        SELECT  @TEXT = Text ,
                @COUNT = COUNT(*) ,
                @MINDATE = MIN(LogDate) ,
                @MAXDATE = MAX(LogDate)
        FROM    #SQLErrorLog
        WHERE   ( Text LIKE '%Login failed for user%' )
                AND LogDate >= DATEADD(MINUTE, -1 * @MINUTE, GETDATE())
        GROUP BY Text
        HAVING  COUNT(*) > 5;
 
        DECLARE @USER AS VARCHAR(100);
        DECLARE @IP AS VARCHAR(100);

--ORDER BY LogDate DESC
        DECLARE @POS AS INT= 0;
        DECLARE @POS2 AS INT= 0;

        DECLARE @STR1 AS VARCHAR(1000)= REPLACE(@TEXT, 'Login failed for USER',
                                                '');
        SET @POS = CHARINDEX('. Reason:', @STR1);
        SET @USER = LEFT(@STR1, @POS - 1);

        SET @POS = CHARINDEX('[CLIENT: ', @TEXT);
        SET @POS2 = CHARINDEX(']', @TEXT);

        SET @IP = SUBSTRING(@TEXT, @POS, @POS2 - @POS);
        SET @IP = REPLACE(@IP, '[CLIENT: ', '');
 
        DECLARE @MSG AS VARCHAR(1000);
        SET @MSG = CONVERT(VARCHAR, @MINDATE, 109) + ' VE '
            + CONVERT(VARCHAR, @MAXDATE, 109) + ' TARİHLERİ ARASINDA ' + @USER
            + ' KULLANICISI ' + CONVERT(VARCHAR, @COUNT)
            + ' KEZ YANLIŞ ŞİFRE GİRDİ';
 
        IF @COUNT > 5
            BEGIN
			EXEC msdb.dbo.sp_send_dbmail  
			@profile_name = 'sqlegitim',  
			@recipients = '[email protected]',  
    
			@subject = 'Brute Force Saldırısı',  
			@body=@MSG 
            END; 
        SELECT  @MSG; 
        DROP TABLE #SQLErrorLog; 
    END; 

Şimdi ise sisteme birkaç kez brute force saldırısı yapalım.


BRUTFORCE_CONTROL isimli sorgumuzu elle çalıştıralım.

Sorgumuzun sonucu bu şekilde geldi.
Aşağıda ise gelen maili görüyorsunuz.

Şimdi sırada bu işlemi elle değil otomatik yapmak var.
Bunun için sql server agent a bir job yazmak en pratik yol.




Tekrar saldırdığımızda 3 dakika içinde otomatik olarak sistemin bize mail gönderdiğini görüyoruz.


Şimdi otomatik olarak saldırıyı tespit ettiğimize göre bu ip den girişleri otomatik olarak engellemek kalıyor geriye.
Bunun için powershell ile Windows firewall a kural yazabileceğiniz gibi, daha kolay bir yol olan server logon trigger ları da kullanabilirsiniz.
Mantık çok basit madem saldırı yapan ip yi yakaladık, bir blacklist tablosu oluşturup içine bu ip yi yazalım. Sonra da bir logon trigger yazalım ve bağlantı yapan ip bu blacklist tablosunda var ise içeriye şifreyi bilse bile girmesine izin vermeyelim.
Bunun için yukarıda yazdığımız BRUTEFORCE_CONTROL isimli procedure de bir değişiklik yapacağız.
Öncelikle AUDITLOG isimli bir db oluşturalım.


Bu database e de blacklist isimli bir tablo oluşturalım.

CREATE TABLE [dbo].[BLACKLIST](
	[ID] [int] IDENTITY(1,1) NOT NULL,
	[DATE_] [datetime] NULL,
	[IPADDRESS] [varchar](50) NULL
) 

Şimdi de BRUTEFORCE_CONTROL  isimli procedurumuz ü şu şekilde güncelleyelim. Mail göndermeden hemen öncesine aşağıdaki kodu ekleyelim.

INSERT  INTO AUDITLOG.dbo.BLACKLIST
                        ( IPADDRESS,
                          DATE_)
                VALUES  ( @IP ,
                          GETDATE())

Son olarak bir de server trigger yazıyoruz ki bu blacklistte olan makine sisteme login olamasın.
Yalnız bu işlemi yapmadan önce sistem database lerinin yedeğini almanızı şiddetle tavsiye ederim. Bir hata olursa sql server’a siz de giremiyorsunuz zira.:)
C:\Program Files\Microsoft SQL Server\MSSQL12\MSSQL\DATA klasörü içerisinde master.mdf ve master.ldf dosyalarının yedeklerini alın mutlaka. Yedek almak için sql servisini durdurmanız gerekiyor.
Sonra aşağıdaki sorguyu çalıştırarak sisteme blacklistteki bilgisayarlardan girişi engellemiş olursunuz.

create TRIGGER [connection_limit_trigger]  
ON ALL SERVER  
FOR LOGON  
AS  
BEGIN  
IF CONNECTIONPROPERTY ('client_net_address') IN (SELECT IPADDRESS FROM AUDITLOG.DBO.BLACKLIST)  
ROLLBACK;  
END 

Oluşturduğumuz bu triggerı Server Objects kısmında bu şekilde görürüz.

Şimdi saldırdığımızda artık saldıran ip nin blackliste düştüğünü görüyoruz.

Ve artık şifreyi doğru girseniz bile içeri giremediğinizi görüyoruz.


Umarım faydalı bir yazı olmuştur.

Sağlıcakla…

Not:Bu yazı Arka Kapı Dergi’nin 5. sayısında baskılı olarak yayınlanmıştır.

İlgili Makaleler

29 Yorum

      1. Hocam elinize sağlık. Brute force yanlış kullanıcı bilgileri ile yaptığında klasik login failed hatası dönmekte. Fakat doğru bilgilerle giriş yapmak istediğinde trigger execute hatasi dönmekte. Burada farklı logda olmayan ip ile denemek kaldı. Mesaj bypass edilebilir mi
        Teşekkür ederim.

  1. google drive linki calismiyor. rica etsem yeni linki paylasabilir misiniz ? tesekkurler

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Başa dön tuşu