Blog

SQL Server Brute Force Ataklarini Tespit Etme Ve Engelleme

Merhaba, SQL Server logging ve auditing konusunda yazılarımıza bir yenisi ile devam ediyoruz. Bu makalemizde SQL Server (aslında kullanıcı adı ve şifre ile girilen her platformda geçerli olan) brute force ataklarını tespit etme, engelleme ve saldırganı iş üstünde yakalama konularına değineceğiz.

Kısaca brute force nedir? Biraz bahsedelim.

Brute force, rastgele anlamsız ya da anlamlı şekilde şifre deneyerek sisteme girmeye  çalışmak demektir. Bu ataklarda ya tüm yazı karakterleri sırayla anlamsız da olsa denenir, ya da internette bir çok yerde bulabileceğiniz şifre sözlüğü listelerindeki en çok kullanılan şifreler ile saldırılır.

Birinci yöntem uzun sürmesine rağmen sonuca ulaşma olsılığı daha yüksektir. İkinci yöntemde ise durum biraz şansa kalmış. Tabi bu sözlük listelerinde bile 5-10 milyon şifre bulunmakta.

Belki de yazının sonunda yazmamız gereken konuyu olur da sonuna kadar sabredemeyenler olur diye şimdi söylemek istiyorum. Brute force atakta ihtiyacımız olan,

  • IP
  • Port
  • Kullanıcı adı
  • Şifre listesi

Burada dışarıdan saldırılar için portu dışarıya açmamak bir çözüm. Ayrıca firewalllar bu saldırıları farkedip engelleyebiliyor. Ama içeriden olan saldırılar çok daha riskli. Bu anlamda IP bellidir, portu da kapatamazsınız. Bu durumda kullanıcı adı default SA kullanıcısını disable etmek en mantıklı çözüm. Zira saldırgan hem şifreyi hem kullanıcı adını bulmak zorunda kalacak. Tabi bu arada siz onu bulamazsanız.

Brute force ataklarını tespit etmek ve engellemek için çeşitli 3. Parti sistemler ve yazılımlar mevcut. Ancak bunlar oldukça maliyetli sistemler ve iyi haber, SQL Server ı iyi biliyorsanız bu korumayı kendiniz yapabilirsiniz.

Bu makalede şunu gerçekleştiriyor olacağız.

  • 2 Milyon kayıt içeren bir şifre sözlüğümüz var.
  • Bu şifreler ile sisteme saldıran bir yazılımımız var.
  • 3 dk da bir SQL Server’ın sistem logunu okuyacağız ve sisteme login failed ile düşen 3 dk da belli bir sayıdan fazla (burada ben 100 olarak belirttim.) event var mı ona bakacağız.
  • Eğer varsa bu bilgisayarı tespit edip kara liste olarak tanımladığımız tablomuza kaydedeceğiz.
  • Sisteme koyacağımız bir logon trigger ile bu makine üzerinden gelen login isteğini reddedeceğiz.
  • Saldırgan şifreyi kırsa bile kıramadığını sanıp saldırmaya devam edecek.
  • Biz ise onu iş üstünde yakalayacağız.

Öncelikle brute force atak yapacak bir yazılımımız var. Aşağıdaki kodları ile birlikte aşağıdaki linkten indirebilirsiniz.

https://drive.google.com/open?id=0B1ie-PwA7YrMQnA3RWVOMW15dEU

Programı çalıştırdığımızda aşağıdaki ekranı görüyor olacağız.

Burada,

Sunucu:Bağlanacağımız SQL Server adı

Kullanıcı :SA

Database:Master

Olarak ayarlayabiliriz. Benim burada denediğim makinede password bilgisi “Password1” olarak belirlendi ve “Password1” kelimesini uniquePass_preview.txt şifre sözlüğü dosyasının içinde başlarda bir yere koyarak sistemin hemen şifreyi bulmasını sağladım.

Örneğin bendeki dosyada 19. Sırada.

Programı çalıştırdığımızda aldığımız görüntü ise şu şekilde. Görüldüğü gibi 19. Sıradaki bir şifreyi 5 sn de buldu. İlginç bir şekilde networkteki başka bir makineden local makineye göre daha hızlı bulduğunu farkettim.

Şimdi burada bizim amacımız önce brute force yapıldığını, sonra da brute force yapanı tespit etmek ve kara listeye düşürmek.

Burada tüm saldırıların içeriden olduğunu tekrar hatırlatmak isterim.

Sisteme brute force yapıldığında sistem SQL Server log dosyasına ve Windows log dosyasına

“Login failed for user 'SA'. Reason: Password did not match that for the login provided. [CLIENT: 192.168.1.24]”

Şeklinde bir kayıt atmaktadır. Bunu aşağıdaki şekilde management studio üzerinden görebiliriz.

 

Şimdi biz burada log dosyasına kendimiz bakabiliyoruz ancak yapmak istediğimiz, 3 dakikada bir çalışacak bir job ile 3 dakika içerisinde birden çok kez (ben 100 olarak belirledim) Login failed hatası alıyorsak atak yapıldığını anlayacak ve yöneticiyi uyaracak bir sistem geliştirmek.

Öncelikle log dosyasını sorgu ile okumamız gerekiyor.

EXEC xp_readerrorlog 0;

Komutu log dosyasını okumamızı sağlar. Komutun ekran çıktısı aşağıdaki gibidir.

Görüldüğü üzere burada bir çok log hareketi var. Bizim için önemli olan ise “Login failed…” şeklindeki mesajlar.

Bu mesajları filtrelemek için bir temp tablo oluşturuyoruz ve stored procedure den dönen değerleri bu tabloya dolduruyoruz. Aşağıdaki script bu işi gerçekleştiriyor.

CREATE TABLE #SQLErrorLog

            (

              LogDate DATETIME ,

              ProcessInfo VARCHAR(20) ,

              Text VARCHAR(500)

            );

INSERT  INTO #SQLErrorLog

     EXEC xp_readerrorlog 0;

Daha sonra bu tablodan Text alanı “Login failed…” şeklinde olanları çekiyoruz.

SELECT * FROM #SQLErrorLog WHERE Text LIKE '%Login failed%'

Yine son 3 dakika öncekileri çekiyoruz.

SELECT * FROM #SQLErrorLog WHERE Text LIKE '%Login failed%' AND logdate>=DATEADD(MINUTE,-3,GETDATE())

Bu sorgudan 18 satır geliyor. Çünkü biz 19. Sırada doğru şifreyi bulmuş ve login olmuştuk.

Şimdi UniqePass_preview.txt dosyasında bulunan Password1 textini daha aşağıya taşıyalım. Örneğin ben 180. Satıra taşıdım.

Şimdi programı tekrar çalıştırıyoruz.

Görüldüğü gibi bu kez 179 denemede ve 1dk 16 sn de buldu şifreyi. Şimdi son 3 dakikalık loglara tekrar bakalım.

Görüldüğü gibi bu kez 179 den fazla kayıt var ve bu bizim belirlediğimiz eşik değeri olan 100 den fazla o zaman bir saldırı var demektir.

Şimdi bunun için bir sorgu oluşturacağız. Bu sorgu sistemde brute force atak algıladığında SQL DB mail ile admine mail gönderecek. Aşağıdaki sorgu bu işi yapıyor.

DECLARE @COUNT AS INT

DECLARE @TEXT AS VARCHAR(8000)

SELECT @TEXT=TEXT,@COUNT=COUNT (*) FROM #SQLErrorLog WHERE Text LIKE '%Login failed%' ANDlogdate>=DATEADD(MINUTE,-3,GETDATE())

GROUP BY TEXT HAVING COUNT(*)>100

IF @COUNT>100

BEGIN

EXEC msdb.dbo.sp_send_dbmail

@profile_name="BIM",

       @recipients='ocolakoglu@gmail.com', 

    @subject = 'Sisteminize 100 den fazla brute force şifre denemesi yapıldı', 

    @body = 'Sisteminize 100 den fazla brute force şifre denemesi yapıldı<br>',--+ @text , 

    @body_format = 'HTML' ; 

END

DROP TABLE #SQLErrorLog

Şimdi bu sorguyu derli toplu olması adına stored procedure yapalım.

Create PROC BRUTE_FORCE_CONTROL AS

CREATE TABLE #SQLErrorLog

            (

              LogDate DATETIME ,

              ProcessInfo VARCHAR(20) ,

              Text VARCHAR(500)

            );

INSERT  INTO #SQLErrorLog

     EXEC xp_readerrorlog 0;

DECLARE @COUNT AS INT

DECLARE @TEXT AS VARCHAR(8000)

SELECT @TEXT=TEXT,@COUNT=COUNT (*) FROM #SQLErrorLog WHERE Text LIKE '%Login failed%' ANDlogdate>=DATEADD(MINUTE,-3,GETDATE())

GROUP BY TEXT HAVING COUNT(*)>100

IF @COUNT>100

BEGIN

EXEC msdb.dbo.sp_send_dbmail

       @profile_name="BIM",

       @recipients='ocolakoglu@gmail.com', 

    @subject = 'Sisteminize 100 den fazla brute force şifre denemesi yapıldı', 

    @body = 'Sisteminize 100 den fazla brute force şifre denemesi yapıldı<br>',--+ @text , 

    @body_format = 'HTML' ; 

END

DROP TABLE #SQLErrorLog

Bundan sonra ise 3 dk da bir çalışacak bir SQL Job oluşturacağız.

Sql Job’ımızı da oluşturduk. Manuel olarak çalıştıralım. Bundan sonra otomatik olarak çalışacaktır.

Şimdi brute force programımız ile saldıralım.

Görüldüğü gibi sistem otomatik mail gönderiyor.

Buraya kadar saldırganı tespit etme çalışması yaptık. Bundan sonrasında ise saldırganın içeriye girmesine engel olacağız.

Bunun için otomatik çalışan job ımız burada okuduğu ip yi bir blacklist tablosuna atacak.

Kullanacağımız tablo aşağıdaki gibi.

CREATE TABLE [dbo].BLACKLIST(

       [ID] [INT] IDENTITY(1,1) NOT NULL,

       [COMPUTERIP] [VARCHAR](250) NULL,

       [DATE_] [DATETIME] NOT NULL,

       [MINDATE] [DATETIME] NULL,

       [MAXDATE] [DATETIME] NULL,

       [ERRORTEXT] [VARCHAR](5000) NULL)

Sistemde 3 dk da bir çalışacak job için oluşturduğumuz stored procedure ü aşağıdaki gibi değiştiriyoruz.

ALTER PROC [dbo].[BRUTEFORCE_CONTROL]

AS

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, -3, GETDATE())

        GROUP BY Text

        HAVING  COUNT(*) > 100;

SET @COUNT=ISNULL(@COUNT,0)

IF @COUNT>5

BEGIN

       DECLARE @CLIENT AS VARCHAR(50)

       DECLARE @POS1 AS INT

       DECLARE @POS2 AS INT

       SELECT @POS1=CHARINDEX('CLIENT:',@TEXT)+8

       SELECT @POS2=CHARINDEX(']',@TEXT)

       SELECT @CLIENT=SUBSTRING(@TEXT,@POS1,@POS2-@POS1)

       DECLARE @MSG AS VARCHAR(200)='BRUTE FORCE ATAK UYARISI:'

       SET @MSG=@MSG+CONVERT(VARCHAR,@MINDATE,109)+' ILE '+CONVERT(VARCHAR,@MAXDATE,109) +' TARIHLERI ARASINDA '

       SET @MSG=@MSG+CONVERT(VARCHAR,@COUNT)+' KEZ LOGIN FAILED HATASI ALINDI'

       SET @MSG=@MSG+' CLIENT='+@CLIENT

                INSERT  INTO AUDIT.dbo.BLACKLIST

                    ( 

                          COMPUTERIP ,

                          DATE_ ,

                          MINDATE ,

                          MAXDATE ,

                          ERRORTEXT

                        )

                VALUES  (

                          @CLIENT ,

                          GETDATE() ,

                          @MINDATE ,

                          @MAXDATE ,

                          @TEXT 

                        );

EXEC msdb.dbo.sp_send_dbmail

       @profile_name="BIM",

       @recipients='ocolakoglu@gmail.com', 

    @subject = 'Sisteminize 100 den fazla brute force şifre denemesi yapıldı', 

    @body = @msg ,

    @body_format = 'HTML' ; 

END

DROP  TABLE #SQLErrorLog

Blacklist tablomuza kayıtlar şu şekilde atıldı.

Gelen mail ise bu şekilde.

Şimdi sıra geldi blackliste düşen ip lerin sisteme girişinin engellenmesi. Saldırgan şifreyi kırsa bile içeri giremeyecek ve şifreyi kırdığının farkına varmadan saldırmaya devam edecek.

Bunun için bir logon trigger yazıyoruz. Yalnız saldırıyı kendi makinemizden yapıyorsak bu kodu koyduğumuzda tekrar kendimiz de bağlanamayabiliriz. O yüzden bundan sonraki saldırıları başka bir makineden yapmak gerekiyor ya da master database i mizin bir yedeğini almakta fayda var.

Yazdığımız logon trigger aşağıdaki gibi.

USE [master]

GO

CREATE TRIGGER BRUTE_FORCE_DISABLE_CONNECTION

ON ALL SERVER 

FOR LOGON

AS  

   IF CONVERT(VARCHAR,CONNECTIONPROPERTY ('client_net_address')) NOT IN (SELECT COMPUTERIP FROMAUDIT.DBO.BLACKLIST)

   BEGIN

        ROLLBACK 

   END

GO

Şimdi tekrar saldırıyoruz. 179. Sırada bizim şifremizi bulması gerekirken bulamadan atlayacak ve diğer şifreleri denemeye devam edecek. Böylece yazının en başında bahsettiğimiz gibi biz saldırganı hem engellemiş hem de iş üstünde yakalamış olacağız.

Aşağıdaki görüntüde görüldüğü gibi sistem 561 kez denemesine rağmen halen bulamamıştır. Oysa saldırgan şifreyi daha 179 uncu denemede bulmuştu. Ancak bulduğunu farkedemedi.

Bu konunun CezeriSGA bünyesinde eğitimi verilmiş olup video görüntüsü aşağıdaki linkte mevcuttur.

https://drive.google.com/open?id=0B1ie-PwA7YrMcDJremktLVJZUUk

Bir sonraki makalede görüşmek üzere.




Yazar Hakkında

1980 Kayseri doğumluyum. 2004 yılında Erciyes Üniversitesi Bilgisayar Mühendisliği Bölümün'nden mezun oldum. 2002 yılında Microsoft Imagine Cup yarışmasında Türkiye 3. sü oldum. Yaklaşık 15 yıldır SQL Server üzerine çalışıyorum. Büyük veri, query optimizasyonu, iş zekası gibi alanlarda uygulamalar geliştiriyorum. Hobi olarak robot programlama, IOT cihazları üzerinde proje geliştirme üzerinde çalışıyorum. 6 yıldır Isısan A.Ş. şirketinin BT Yöneticisi olarak çalışıyorum. Halen Erciyes Üniversitesi Bilgisayar Mühendisliği Bölümü'nde dışarıdan öğretim üyesi olarak derslere giriyorum.






Yorum Yapmak İçin Giriş Yapın.