29 Eylül 2017 Cuma

Veritabanınızdaki veriler ne kadar güvende sizce?

Güvenlik gündemden düşmeyen ve düşmeyecek bir konu, sonuçta İhtiyaçlar Hiyerarşisinin de 2. basamağında. Hatta malumunuz son günlerde her yerde Gartner'ın Güvenlik Danışmanlığı dalında ve ciro bakımından 5 yıl art arda 1. sıraya koyduğu Deloitte'ta yaşanan güvenlik açığı konuşuluyor. Peki sizin sistemlerinizin güvenliği ne alemde? Bunu yeterince sorguluyor musunuz?

Bu yazımda size son günlerde yaşadığım bir güvenlik sorunundan ve bir Microsoft SQL Server veritabanı yöneticisinin gözünden güvenlik ile ilgili alınması gereken tedbirlerden bahsedeceğim.

Kısa bir süre önce yönetimini yaptığım sunucuların birinden güvenlik alarmları geldiğini gördüm, durumu analiz edip hemen ilgili IT yöneticisine bildirdim. O da ilgili diğer arkadaşlara bildirdi ve sisteme bir saldırı olduğu netleşti. İlgili ekip tarafından gerekli önlemler alındı ve atak engellenmiş oldu. 

Peki saldırının türü neydi ve saldırıyı nasıl fark ettim? Microsoft SQL Server ürününün varsayılan olarak böyle bir alarmı veya mekanizması yok. Fakat bunun temel altyapısı var. Eğer biraz tecrübeniz varsa, biraz bu konulara kafa yoruyorsanız ve üşengeç biri de değilseniz o zaman eminim sizin de aklınıza gelmiştir bu mekanizma ve bazılarınız zaten uygulamıştır. 

Bakım ve destek anlaşması kapsamında ilgili sunuculara kurduğum izleme sistemindeki onlarca kontrolden biri şöyle:
- Her X dakikada bir Error Log dosyası içerisindeki (ki Error Log dosyasına yazılan her şey Windows Application Event Log'a da yazılır, yani alternatif bir yöntem) tüm "Login Failed" kelimeleri geçen hatalar taranır, 
- Eğer bulunan kayıt sayısı beklenilen/normal sayılan değerden yüksekse, ilgili yöneticilere e-posta ile (aşağıdaki resimdeki gibi bir liste) bildirilir.

Çok basit bir oto-denetim, ama çok etkili. Bahsettiğim saldırıyı güvenlik, ağ ve sistem yönetiminden önce benim fark etmemi sağlayan yöntem bu idi.

Bu saldırıya "Brute Force" mu desek, DDoS mu? Sonuç itibariyle farklı farklı IP adreslerinden, farklı farklı kullanıcı adı ve şifre kombinasyonuyla veritabanına girilmeye çalışıldı.


Saldırı sırasında oluşan hatalar

Çok iyi hatırlıyorum, 2 sene önce bir başka ortamda da aynen yukarıdaki hata mesajlarına benzer hatalar oluşmuştu. Müşteriyle daha yeni bakım ve destek anlaşması yapmıştık. Bana sunucularının çok kritik olduğundan bahsetmişti. Sunucuya daha ilk bağlandığımda hata kayıt dosyalarının böyle mesajlarla dolu olduğunu görmüştüm. Kim bilir ne süredir saldırı altındaydı ve bundan hiç haberi yoktu. Bunu müşteriyle ilettiğimde tüyleri diken diken olmuştu.

Microsoft SQL Server, yıllardır güvenlik açıkları kapsamında rakiplerine göre katbekat güvenli bir ilişkisel veritabanı ürünüdür. Bununla birlikte, nasıl güvenli olduğundan emin olduğunuz herhangi bir aracı, gereci kullanırken tüm güvenlik önlemlerini almanız gerekiyorsa, SQL Server'ı da kullanırken en azından temel güvenlik önlemlerini almalısınız.


Kaynak: Microsoft'un bir sunumundan...

Uzun yıllardır gerek projeler kapsamında, gerekse tam zamanlı olarak verilerin çok hassas olduğu sağlık ve finans sektörlerlerinden birçok kurumda çalışmalar yaptım. Kontrolümde olan sunucular yüzlerce kez dahili ve harici denetimlere tabi tutuldu. Aşağıda sizlerle bu tecrübelerimden aklıma gelen başlıca maddeleri paylaşmak istiyorum. Eğer birçoğu klasikleşmiş bu maddeleri ortamınıza uygulayabilirseniz, SQL Server kapsamında alınabilecek başlıca güvenlik tedbirlerini almış olursunuz. Hem kendi güvenliğinizi sağlamış olursunuz, hem de olası denetimlerde başınız ağrımaz.

- SQL Server'ın varsayılan (daha fazla bilgi için) portu 1433'tür, bunu dünyadaki tüm saldırganlar bilir. Farklı bir port kullanın.

- SQL Server kurulumuyla birlikte "sa" hesabı varsayılan olarak gelir. Bunu da aynı şekilde tüm saldırganlar bilir. Bu nedenle yukarıdaki loglarda da görebileceğiniz üzere "sa" hesabı da saldırılan hesaplardan biriydi. "sa" hesabının yerine başka kullanabileceğiniz "sysadmin" rolü üyesi hesaplar olduğundan emin olduktan sonra "sa" hesabını "Disable" duruma getirin veya "sa" hesabının adını değiştirin.

- Guest hesabını kullanmayın. Public kullanıcısına yetki vermeyin.

- Kullanıcılarınızın Login'ler için basit veya boş şifreler belirleyebilmesini engelleyin. 

- Mümkün olduğunca SQL Authentication yerine Windows Authentication'ı tercih edin.

- Yazılımcılarınız "SQL Injection" konusunda bilinçlendirilmeli. Uygulama arayüzlerinde kullanılan metin kutuları sadece almaları gerektiği türden ve uzunlukta değerler almalı. Örneğin sayısal bir değer kutusuna metin girilememeli veya TC Kimlik No alanına 11'den fazla karakter girilememeli.

- Uygulamalarınız sadece ihtiyacı olan uygulama kullanıcılarıyla erişsin veritabanına. Böylece uygulamanızdaki bir açık vasıtasıyla veritabanına ulaşılırsa, sadece uygulamanın ulaşabileceği veriye ulaşılabilir olsun, daha fazlası yapılamasın.

- Kod yazarken güvenlik (ve performans) açısından mümkün olduğunca dinamik SQL kullanmayın. Kullanacağınız zaman da dinamik SQL metinlerini güvenlik denetimine tabi tutmadan çalıştırmayın.  Örneğin "Doğum Yılı" veya benzer bir veri giriş kutusuna kesme işareti, "DROP, ALTER, GRANT, EXECUTE" gibi komutlar girilememeli.

- Uygulama yazarken kesinlikle ve hiçbir zaman son kullanıcının gireceği veriye güvenmeyin. Sadece güvenlik açısından değil, performans ve işlevsellik açısından da.

- Uygulama yazılırken sadece işlev değil, güvenlik (ve performans) odaklı yazılmalı. Yazılımcılar bu konuda net olarak bilinçli ve eğitimli olmalı. Projeler sadece işlevsellik ihtiyaçlarının giderileceği kadar sürelendirilmemeli. Yazılımcılar ve iş analistleri üstünde zaman baskısı olursa herkes sadece işlevselliğe odaklanır. Güvenlik ve performans testleri için de projelere süreler eklenmeli. Gerçekçi süreler! Zaman baskısı nedeniyle birçok şirkette hala doğru düzgün işlevsellik testi bile yapılmadan canlıya kod taşıması yapıldığını biliyorum maalesef.

- Her seviyedeki tüm kullanıcılara, sadece gerektiği kadar yetki verilmeli. Birçok ortamda gördüğümüz gibi tüm kullanıcılar "sysadmin" olmasın veya tek bir kullanıcıyla (genellikle "sa") tüm sistemi yönetmeye kalkmayın.

- Veritabanı yöneticisinin işlemleri dahil tüm kritik işlemleri 3. parti araçlarla veya SQL Server'ın sağladığı imkanlarla kayıt altına alın. Fakat birçok ortamda olduğu gibi sadece işlemleri kaydetmekle kalmayın, bu kayıtları otomatik olarak inceleyin ve anlam çıkartın ve sonuçlar için alarmlar ve raporlar ürettirin. 

- Görevler ayrılığı ilkesini işletin. Domain veya Windows yöneticileri için "sysadmin" rolüyle kullanıcılar olmadığından emin olun. Mümkünse herkes kendi işini yapsın. Örneğin bir önceki maddede bahsettiğim kayıt mekanizmasını hem kuran, hem yöneten aynı kişi olmamalı. Kayıt altına alınan işlemler değiştirilememeli.

- Sisteminizde her zaman neyin normal, neyin anormal olduğunu bilmelisiniz. Nasıl performans için bir referans hattınız varsa (var, değil mi?), güvenlik için de bir referans hattınız olmalı. Örneğin özellikle çok kritik tablolardan toplu sorgulamalar yapılmasını istemeyebilirsiniz ve böyle bir şey olduğunda haberdar olmak isteyebilirsiniz. Böyle tabloları belirleyin ve gerekli alarm mekanizmalarını kurun.

- Yazılımcılar, iş analistleri ve diğer personel uygulama kullanıcılarının şifrelerini bilmemeli. Bu bilgiler (Connection String) şifreli saklanmalıdır.

- Yazılımcılar, iş analistleri ve diğerlerinin doğrudan canlı sunuculara uygulama kullanıcılarının bilgileri ile bağlanamamasını sağlayın. Canlı sunuculara uygulama kullanıcıları kullanılarak ancak uygulama sunucularından veya ilgili sunuculardan ve uygulamalar aracılığıyla gelinebilmeli.

- Mümkünse canlı ortamınız için ağ bölümü ile koordineli çalışarak IP kısıtlaması koydurtun. Canlı ortamınıza mümkünse sadece belli IP adreslerinden/bloklarından (uygulama sunucuları) gelinebilsin.

- Gerek canlı ortamınız, gerekse geliştirme ve test ortamınızdaki hassas verilerinizi maskeleyin. Sadece yetkili kişiler, görmeleri gereken verilerin, görmeleri gereken kısımlarını görebilsinler. Hem bir veri sızıntısı durumunda ilgili, ilgisiz herkes zan altında kalmamış olur, hem saldırganların işi zorlaşmış olur, hem de olası sızıntının nereden kaynaklanabileceği hakkında inceleme yapacağınız daha dar bir alan olur.

- Veritabanı yedeklerinizi de canlı ortamınızı koruduğunuz gibi koruyun. Mümkünse yedeklerinizi şifreleyin (Backup Encryption SQL Server 2014 ile geldi). Yedeklere kimlerin erişebildiği net ve sınırlı olmalı. Ayrıca mümkünse kimlerin eriştiğinin kaydı tutulmalı ve raporlanmalı.

- SQL Server servis hesaplarınız olarak Local System gibi geniş yetkilere sahip hesapları kullanmayın. Eğer bir Domain hesabı kullanacaksanız bu normal bir "Domain User" hesabı olsun mesela.

- CLR veya xp_cmdshell gibi aktif olarak kullanılmayacak hiçbir özelliği etkinleştirmeyin. Kullanmayacağınız hiçbir SQL Server servisini veya uygulamayı veritabanı sunucunuza kurmayın.

- Daha ileri seviye güvenlik tedbirleri için örneğin diskteki veriyi ve yedekleri korumak için Transparent Data Encryption özelliğini kullanmayı düşünün. (İleri seviye. Enterprise Edition gerektirir.)

- Veriyi hareket halindeyken (uygulama ve veritabanı arasında gidip geliyorken) ve veri veritabanında dururken şifreli olsun istiyorsanız SQL Server 2016 ile birlikte gelen Always Encrypted özelliğini kullanmayı düşünün. (İleri seviye, her senaryo için uygulanabilir değil. Enterprise Edition gerektirir.)

- Kullandığınız SQL Server versiyonunun güncel sürümlerini kullandığınızdan emin olun.

- Güvenlik haberlerini yakından takip edin, sadece yazılımlarınızı değil, kendinizi de güncel tutun.

Unutmayın, güvenlik sadece ağ katmanı veya daha çok bütçeniz varsa güvenlik bölümlerinde kullanılan pahalı araç gereçlerle sınırlı değildir. Diğer katmanlardan bağımsız olarak sadece veritabanında alacağınız önlemler de yeterli değildir. Geliştirdiğiniz ve kullandığınız uygulamalarınız da kesinlikle bir istisna değildir, olamaz. Güvenlik baştan sona bir bütündür, şirket sekreterinden girişteki güvenliğe, finans müdüründen yazılım mimarına kadar bir takım işidir. Bu katmanlar zincirindeki en zayıf halkanız kadar güçlüdür güvenliğiniz.


Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com

18 Eylül 2017 Pazartesi

Performans: Kendi kendini sabote etmek

Vahşi yaşamdaki Sahadaki sunucularda sağlık kontrolü ve performans iyileştirmesi gibi çalışmalar yaparken, hangi akla hizmet hiç anlam veremediğim bazı ilginç ayarlar yapıldığını, sunucularda aylardır oluşan hataların izlenmediğini ve haliyle herhangi bir müdahalede de bulunulmadığını görüyorum. Ahh, sonra bir de "SQL Server kötü" demiyorlar mı!

Bu tür durumlar, ki piyasada gerçekten çok yaygın, son model spor aracınızı el freni kalkık şekilde kullanmaya benziyor. Donanım kaynaklarına ve lisanslara onca para harcanıyor, fakat bu yatırımlardan verimli bir şekilde faydalanılamıyor.

Geçenlerde 16 işlemci çekirdekli bir sunucuda çalışma yaparken zaman zaman aşağıdaki hataların alındığını gördüm:

"New queries assigned to process on Node 0 have not been picked up by a worker thread in the last 240 seconds. Blocking or long-running queries can contribute to this condition, and may degrade client response time. Use the "max worker threads" configuration option to increase number of allowable threads, or optimize current running queries. SQL Process Utilization: 5%. System Idle: 93%."

Ve bu hatalarla birlikte Dump alınıyordu.

Bu hata mesajı sorguların uzun sürdüğünün, olası bağlantı hatalarının ve CPU kaynaklarının verimli kullanılmadığının işaretidir.

Bekleme tiplerini kontrol ettiğimde "Threadpool" bekleme tipinin "CXPACKET"tan hemen sonra geldiğini görüyordum. Konumuz dahilinde değil, ama "CXPACKET" bekleme tipi paralelliğin kullanıldığı tüm ortamlarda olur ve kendi başına doğrudan bir sorun anlamına gelmez. Fakat ilk 10 bekleme tipi arasında "Threadpool"u görüyorsanız ve bu da ikinci sıradaysa "Worker Thread"lerle ilgili bir sorununuz var ve buna odaklanmanız gerekir demektir.


Threadpool bekleme tipi sorununun görseli

Peki nedir bu "Threadpool" ve "Worker Thread"?

Threadpool, çok miktarda istemci sunucuya bağlandığında performansın optimize edilmesini sağlar. Kullanıcıların yaptığı talepler için, yani çalıştırdıkları sorgular için bir Thread havuzu oluşturur. Threadpool'da kullanılabilecek Worker Thread sayısını SQL Server sunucu mimarisi ve işlemci çekirdek sayısına göre Database Engine servisinin başlangıcında yapar. Bu şartlara göre oluşturulacak Worker Thread sayısını Microsoft'un dokümantasyonundan inceleyebilirsiniz.

Eğer bu hesaplamaya müdahale etmeniz gerekirse, ki şahsen henüz bunu gerektirecek bir durumla hiç karşılaşmadım, o zaman "Max Worker Thread" ayarını değiştirmeniz gerekir. Bu ayar varsayılan olarak 0'dır ve çok istisnai durumlar haricinde de 0 olarak kalması gerekmektedir.

Herhangi bir SQL Server Instance'ındaki o anki "Max Worker Thread" sayısını görmek için aşağıdaki komutu çalıştırabilirsiniz:

SELECT [max_workers_count] FROM sys.dm_os_sys_info;

"Max Worker Thread" ayarınızı görmek için de aşağıdaki komutu kullanabilirsiniz:

SELECT [value], [value_in_use] FROM sys.configurations WHERE [name] = 'max worker threads';

Eğer "Max Worker Thread" ayarınız için [value] ve [value_in_use] alanlarının değerleri 0 ise ayarınız varsayılan değerdedir ve önceden de belirttiğim gibi birçok ortam için de doğru olan değer budur. Eğer bu alanlardan herhangi biri 0 değilse, birisi bu ayarı değiştirmiştir ve eğer bunu gerçekten işini bilen birisi yapmadıysa büyük ihtimalle bu hatalı bir hamledir. Eğer bu ayarı değiştirmeniz gerekirse, değişikliği uyguladıktan sonra Database Engine servisini yeniden başlatmanız gerekir, aksi takdirde değişiklik hemen devreye girmez.

Gelelim Worker Thread'in ne olduğuna. SQL Server'da her bir işlemci çekirdeği Scheduler'la temsil edilir. SQL Server Instance'ınızda kaç tane Scheduler olduğunu, bunların kaç tanesinin kullanılabilir (Visible) olduğunu sys.dm_os_schedulers isimli DMV'yi sorgulayarak görebilirsiniz. Örneğin bazı Scheduler'lar sistem tarafından kullanılır, bazıları ise lisanslama yüzünden (bakınız) pasif durumda olabilir. Worker Thread'ler, Scheduler'lar tarafından kendine atanmış olan Task'ları (örneğin bir sorgunun çalışması veya log in işlemi gibi) çalıştırırlar. Mesela havuzda yeterince kullanılabilir Worker Thread olmazsa bu nedenle "Login failed" hataları alabilirsiniz.

Peki 16 çekirdekli bir işlemci kaynağının olduğu bu ortamda yukarıdaki hata neden alınıyordu dersiniz? Sağolsun birisi ne hikmetse bu ayarı "255" olarak değiştirmiş. Bu nedenle havuzda "704" Worker Thread olabilecekken "255" tane var. Yani aslında ortamda yeterli altyapı var; ama el freni kalkık ve SQL Server çığlık ata ata çalışıyor... Haliyle bir Blocking sorunu oluştuğunda, paralel veya uzun süren bir işlem sık ve yaygın olarak çalıştırıldığında yukarıdaki gibi hata mesajlarına rastlamak da olası oluyor.

Sistem yöneticisi, veritabanı yöneticisi, yazılımcı (evet maalesef...), SQL Server yönetimi yapan tüm arkadaşlar! Eğer ne yaptığınızdan emin değilseniz, emin olmadığınız bir ayarı değiştireceğinize lütfen varsayılan haliyle bırakın. O ayarı çok merak ediyorsanız, o ayar sizi çok rahatsız ediyorsa ve farenize hakim olamıyorsanız buyurun Türkçe Microsoft SQL Server forumlarında sorun, ben veya başka bir arkadaşım müsait olduğunda elinden geldiğince cevaplar. Bu yazıda bahsettiğim sadece bir örnek, bunun gibi daha niceleri var. Yapmak istediğiniz değişiklikleri lütfen ne yaptığınızdan emin olduktan sonra yapın.

Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com

6 Eylül 2017 Çarşamba

Veritabanı sunucularınızın maliyetleri nasıl azaltılır?

Her sektörden birçok firmaya giriyorum, çıkıyorum. Bazılarıyla sadece sohbet ediyoruz, bazılarıyla kısa dönemli, bazılarıyla da uzun dönemli çalışıyoruz. Her firmanın kendine göre ihtiyaçları var, bununla birlikte sonuç itibariyle tüm şirketlerin hedefleri aşağı yukarı aynı:

Yapılması gereken işlemlerin düşük maliyetle, kesintisiz olarak ve performanslı şekilde tamamlanması. Bu sayede firma çalışanlarının daha verimli çalışmasının ve müşteri memnuniyetinin sağlanması. Verimlilik.

Bu amacı gerçekleştirmek için bazı yöneticiler daha fazla donanım veya personel alımı yapıyor. Bu yatırımlarla sorunun çözülmediğini gördüklerinde ise hayal kırıklığına uğrayıp sorunun o anda kullandıkları üründen kaynaklandığını düşünebiliyorlar.

Benim örneğimde, tahmin edebileceğiniz gibi Microsoft SQL Server'dan bahsediyorum. Bugüne kadar bu konuda birçok yazı (son 1 senedeki yazı1, yazı2, yazı3, yazı4, yazı5, yazı6) yazdım. Bu seferki de çarpıcı bir örnek diye ayrıca paylaşmak istedim.

Aşağıda, bakım ve destek anlaşması kapsamında çalışma yaptığım sunuculardan birine ait işlemci kullanımının grafiğini paylaşıyorum. 

Büyütmek için resmin üstüne tıklayın.
Bu sunucuda 16 CPU Core'u mevcut. Yine bu sunucuda 1 ay içerisinde gerçekleştirdiğimiz performans iyileştirme çalışmaları sonucunda işlemci kullanımını zirve yaptığı zamanlarda bile %70'lerden %10 civarına indirdik. Gün içerisinde ise işlemci kullanımı eskiden %40 civarındayken artık ortalama %2'yi geçmiyor.

Bu çalışmanın sonucuna daha geniş bir kapsamdan bakarsak: 
- Microsoft SQL Server, 2012 versiyonundan beri Core başına lisanslanıyor. Eğer Open Licensing gibi bir anlaşmanız yoksa lisanslama maliyeti Enterprise Edition için Core başına 14,256$, Standard Edition için ise 3,717$ (kaynak). 16 Core'lu bir Enterprise Edition 228.096$ ediyor. Yukarıdaki gibi bir performans iyileştirme çalışması sonucu artık gereken işlemci kaynağı büyük ölçüde azalmış oluyor. Bunun sonucu olarak en basit haliyle işlemci kaynakları %50 azaltıldığında bile doğrudan ve sadece Microsoft SQL Server lisanslamasından 114 bin dolarlık kar sağlanmış oluyor.

- Birçok firmada çok elzem olmadığı halde Enterprise Edition kullanıldığını görüyorum veya bazı projelerin sadece Enterprise Edition'da gerçekleştirilebileceği düşünülebiliyor. SQL Server 2016 + Service Pack 1 ile birlikte birçok Enterprise Edition özelliği artık Standard Edition'a da geldi (konu hakkındaki yazım). SQL Server 2016 ile gayet şık ve iş gören sürekli kullanılabilirlik ve felaketten kurtulma projeleri gerçekleştirebiliyoruz. Yukarıdaki gibi bir performans iyileştirme çalışmasından sonra Enterprise Edition'a geçmeye hiç gerek kalmadan veya Standard Edition'a Downgrade yaparak lisans maliyetlerini neredeyse 4 kat düşürmek birçok senaryo için mümkün. Bir önceki madde üstünden gidecek olursak 8 Core'dan oluşan 114 bin dolarlık Enterprise Edition maliyetini, 8 Core'dan oluşan Standard Edition ile 29,736$'a düşürebiliriz.

- Lisans maliyetinin yanısıra, artık daha az donanım kaynağı gerektiği için donanım maliyetlerini de azaltmış oluyoruz.

- Şirket çalışanlarının gün içerisinde verimli çalışabildikleri 2-3 saati en verimli şekilde kullanabilmeleri sağlanmış oluyor. Daha az zamanda, daha çok iş gerçekleştirilebiliyor.

- Nihai olarak son kullanıcı olan müşteriler de memnun oluyor.

Ekrem Önsoy
Microsoft SQL Server Danışmanı
www.ekremonsoy.com