Psikiyatri kliniklerinde ve acil servis nöbetlerinde hekimlerin sıkça karşılaştığı klinik tablolardan biri "Perseküsyon ve Megalomanik Sanrılar"dır (Büyüklük ve Takip Edilme Hezeyanı).

Kendi halinde, mahallede kimsenin tanımadığı sıradan bir vatandaş nefes nefese acil servise dalar. Gözleri yuvalarından fırlamıştır:
"Doktor bey beni MİT ve CIA takip ediyor! Karşı apartmanın çatısına keskin nişancılar yerleştirdiler, uydudan beynime mikrodalga sinyaller gönderiyorlar, beni ortadan kaldırmaya çalışıyorlar!"

Hekim sakinleşip hastayı muayene eder: Tansiyonunu ölçer: 190/110 mmHg.
Kafasındaki o uğultu ve baş ağrısı gizli servislerin lazer silahlarından değil; sabah almayı unuttuğu tansiyon ilacı yüzünden beynine vuran yüksek kan basıncından kaynaklanmaktadır!

İnsan egosu o kadar tuhaftır ki; kendi sıradanlığını, kendi vücudunun basit bir arızasını kabullenmektense, tüm dünyanın ve süper güçlerin kendisini yok etmek için birleştiği o görkemli komplo teorisine inanmayı çok daha çekici bulur. "Önemsiz bir arıza" olmak acı verir; "küresel bir hedefin kurbanı olmak" ise sahte bir tatmin sağlar.

Web hosting dünyasında, siber güvenlik operasyonlarında ve teknik destek masalarında da her gün hekimlerin bu tablosunu birebir kopyalayan meşhur bir müşteri mizahı yaşanır: Günde Toplam Yirmi Ziyaretçisi Olan Bir Sitenin Sahibi Sitem Yavaşlayınca "Devasa DDoS Saldırısı Altındayız!" Diye Bilet Açması.


Rus Hackerlar Mahalle Tesisatçısına Karşı!

Senaryo Türk internetinin değişmez bir klasiğidir.
Müşterinin bir web sitesi vardır: ankaratesisattemizleme.com veya kişisel şiirlerini paylaştığı küçük bir blog.
Google Analytics verilerine bakarsınız: Günde ortalama 15 ila 25 tekil ziyaretçi girmektedir (onların da yarısı yanlışlıkla tıklayan akrabalardır).

Bir salı günü öğleden sonra müşteri sitesine girmek ister: enter.
Sayfa 40 saniye boyunca yüklenmez.
Ardından tarayıcıda o meşhur beyaz sayfa belirir:
Error establishing a database connection
Veya Nginx'in 504 Gateway Timeout hatası.

Müşteri telefonunu eline alır. Kalbi küt küt atmaktadır.
İçindeki o megalomanik siber savaş kahramanı anında uyanır!
Kendi kendine fısıldar:
"Rakipler! Çankaya'daki diğer tesisat firması beni çekemedi! Gittiler Dark Web'den Rus hacker ordusu kiraladılar! Bana siber savaş açtılar!"

Müşteri hemen hosting firmasının destek masasına dalar ve Caps Lock'u açarak o destansı bilet metnini yazar:

Konu: ÇOK ACİL! BİZE ORGANİZE DDOS SALDIRISI YAPILIYOR!
Mesaj: "Şu an sitemize organize bir siber çete tarafından saniyede 100 Gbps büyüklüğünde devasa bir Dağıtık Servis Dışı Bırakma (DDoS) saldırısı düzenlenmektedir! Rakiplerimiz şirketimizi batırmak istiyor! Derhal paketimizi en üst seviyeye yükseltin, tüm donanımsal güvenlik duvarı (Firewall) ve anti-DDoS filtrelerinizi açın! Gerekirse IP adresimizi korumalı yurt dışı hatlarına taşıyın!"


Adli Bilişim Masası: Saniyede 0.1 İstek!

Hosting firmasının ağ operasyon merkezindeki (NOC) ağ mühendisi bildirimi alır.
"Acaba gerçekten bir BGP fırtınası veya volumetrik bir SYN-Flood saldırısı mı var?" diyerek hemen omurga switch'in NetFlow ve sFlow trafik grafiklerini açar.

Müşterinin IP adresine gelen anlık trafiğe bakar:
Gelen trafik: Saniyede 12 Kilobit!
Gelen HTTP isteği sayısı: Dakikada 3 adet istek! (O üç isteğin ikisi de zaten müşterinin panikle F5'e basıp durmasından ibarettir!)

Ortada ne bir Rus botneti vardır, ne bir Anonymous saldırısı, ne de rakiplerin kiraladığı bir siber ordu.
Ağ trafiği pırıl pırıldır, hatta sunucu adeta bir göl kenarı kadar sakindir.

Peki o zaman bu site neden açılmamaktadır? Veritabanı neden kilitlenmiştir?


İçerdeki İntihar Bombacısı: ORDER BY RAND() Faciası

Mühendis sunucunun MySQL konsoluna girer ve çalışan aktif sorguları listeler:
SHOW FULL PROCESSLIST;

Ve ekranda beliren tek bir satır, tüm o "uluslararası siber saldırı" tiyatrosunu bir saniyede yerle bir eder:

SELECT * FROM wp_posts 
WHERE post_type = 'post' AND post_status = 'publish' 
ORDER BY RAND() 
LIMIT 5;

Mühendis acı bir tebessümle başını sallar.
Müşteri bir gün önce WordPress sitesinin yan sütununa (sidebar) "Rastgele İlginç Yazılar" adında süslü bir bileşen eklemiştir!

Ve o bileşenin geliştiricisi, tembel ve cahil bir yazılımcı olduğu için rastgele 5 yazıyı seçebilmek adına SQL'in en ölümcül fonksiyonunu kullanmıştır: ORDER BY RAND()!

Bu tek satırlık sorgu arka planda ne yapar biliyor musunuz?

  1. Sitede 5.000 adet blog yazısı veya ürün vardır.
  2. MySQL, rastgele 5 satırı seçebilmek için o 5.000 satırın tamamını RAM'e kopyalar.
  3. Her bir satır için rastgele bir ondalık sayı üretir.
  4. Bu devasa veri kümesini sunucunun diskinde geçici bir tabloya (Temporary Table) yazar.
  5. Diskteki o tabloyu baştan sona sıralar (Disk Sorting), en üstteki 5 satırı alır ve geçici tabloyu siler!

Yani tek bir ziyaretçi o sayfayı her açtığında; sunucu 5.000 satırlık veriyi diskte evirip çevirmekte, işlemcinin tüm çekirdeklerini %100 yüke sokmakta ve MySQL'in tüm iş parçacıklarını kilitlemektedir!

Ve müşteri gibi beş kişi aynı anda F5 tuşuna bastığı o saniyede; MySQL motoru nefes alamaz hale gelmiş, kilitlenmiş (Deadlock) ve Error establishing database connection diyerek yere çakılmıştır!

Müşteriyi vuran şey Rusya'dan gelen 100 Gbps'lik DDoS füzeleri değildir; müşteriyi vuran şey, kendi eliyle sitenin göbeğine yerleştirdiği o berbat, optimize edilmemiş tek satırlık SQL sorgusudur!


Megalomaninin Tedavisi: Kendi Kodunla Yüzleşmek

Destek mühendisi bilet üzerinden sorgu analizini müşteriye açıklar:
"Hasan Bey, sitenize gelen hiçbir harici saldırı yoktur. Sitenizin yan sütunundaki 'Rastgele Yazılar' bileşenindeki ORDER BY RAND() sorgusu MySQL'i kilitliyor. O eklentiyi kaldırdık, siteniz anında açıldı."

Fakat o megalomanik tatmini yaşayan müşterinin bu gerçeği kabullenmesi çok zordur:
"Nasıl yani? Bir satır yazı yüzünden miydi? Ben saldırı altındayız sanmıştım..."

Bir web projesi yönetiyorsanız, şu teknik olgunluğa ulaşmak zorundasınız:

  1. Önce Aynaya Bakın: Siteniz yavaşladığında veya çöktüğünde suçu hemen dış mihraklara, hackerlara veya hosting firmasına atmayın. Sitenin koduna, eklentilerine ve veritabanı sorgularına bakın. Dünyadaki web kesintilerinin %95'i dış saldırılardan değil; içerideki kötü mimariden kaynaklanır.
  2. EXPLAIN ile Sorgu Analizi Yapın: Veritabanınızda yavaş çalışan sorguları slow-query-log üzerinden bulun. Sorgunun başına EXPLAIN yazarak o sorgunun indeks kullanıp kullanmadığını, geçici tablo açıp açmadığını denetleyin.
  3. Önbellek (Caching) Kullanın: Rastgele veri çekmek gibi ağır matematiksel işlemleri her sayfa yenilemesinde veritabanına yaptırmayın! Sonucu Redis veya Memcached'e yazın, 1 saat boyunca oradan okutun.

Tıpta tansiyonu fırlayınca CIA suikastı sanan hastaya ilaç verip sakinleştirirler.

Web dünyasında da günde 20 ziyaretçiyle DDoS paranoyası yaşayan site sahibine sunulacak tek bir reçete vardır: Kodunu optimize et, sorgularını düzelt ve kendi sıradanlığınla barış.

Çünkü en ölümcül hacker; çoğu zaman kendi klavyenizin başında oturan o dikkatsiz yazılımcıdır.