Bugünkü yazımızda business logic zafiyetlerini ele alıp inceleyeceğiz; nasıl türleri olduğunu, nasıl çalıştıklarını, neden tehlikeli olduklarını ve bunlardan nasıl korunabileceğimiz üzerinde duracağız.
Öncelikle:
Business Logic Zafiyeti Nedir? Nasıl Çalışır?
Web ve mobil uygulama güvenliği denildiğinde çoğu zaman herkesin aklına SQL Injection, XSS veya yetkilendirme problemleri gibi teknik zafiyetler gelir. Ancak bazı durumlarda uygulama teknik olarak tamamen güvenli görünse de uygulamanın işleyiş mantığında bulunan hatalar, kullanıcıların sistemi kötüye kullanmasına kapı aralayabilir. İşte bu tür zafiyetler "Business Logic Vulnerabilities" olarak adlandırılmaktadır.
Business logic zafiyetleri, uygulamanın tasarlanan iş akışının beklenmeyen şekillerde manipüle edilmesiyle ortaya çıkar. Diğer birçok zafiyetin aksine burada amaç sistemi sömürmek yerine, çalışma mantığını kendi lehimize çevirmektir. Bu nedenle de çoğu zaman otomatik araçlarla tespit edilemezler. Uygulamanın nasıl çalıştığını dikkatli şekilde analiz etmemizi gerektirir.
Bir örnek verecek olursak; bir e-ticaret uygulamasında aynı indirim kuponunun birden fazla kez kullanılabilmesi, ödeme işleminin atlatılması veya karşı tarafta uygulanan fiyat bilgilerinin değiştirilebilmesi, business logic zafiyetlere güzel birer örnek olabilir.
Yazımızın devamında bu örneklere bir kez daha detaylı şekilde bakacağız.
Peki Nedir Bu Logic Zafiyet Türleri?
Bu tarz zafiyetler işleyiş sürecindeki eksikliklerden kaynaklandığı için, aynı zafiyet farklı şekillerde farklı platformlarda ortaya çıkabilir.
-Yetkilendirme ve İş Akışı Bypass Problemleri:
Bazı uygulamalarda, örneğin e-ticaret sitelerinde, kullanıcıların belli adımları takip etmesi beklenir. Ancak bu adımlar yalnızca istemci tarafından kontrol ediliyorsa, kötü niyetli bir kişi doğrudan HTTP istekleri göndererek süreci manipüle edebilir. Örneğin ödeme adımı tamamlanmayan bir siparişin onaylanabilmesi veya yalnızca premium kullanıcıların erişmesi gereken bir işlemin, normal kullanıcılar tarafından da yapılabilmesi bu tür zafiyetlere birer örnek olabilir.
-İndirim Kuponu ve Fiyat Manipülasyonu:
Bir başka sık karşılaşılan business logic yöntemi ise indirim sistemlerinin yanlış uygulanmasından kaynaklanır. Bazı durumlarda aynı kupon birden fazla kez kullanılabilir veya bazı durumlarda istemci tarafında tutulan fiyat bilgisi sadece web sitesi üzerinden görüntüleniyor fakat işlem sırasında sunucu üzerinden doğrulanmıyorsa, bu bilgilerin değiştirilmesi mümkün olabilir. Bu senaryolar doğrudan finansal kayba yol açtığı için yüksek seviyede değerlendirilir.
-Race Condition Zafiyetleri:
Race condition problemleri aynı işlemin eş zamanlı olarak birden fazla kez gerçekleştirilebilmesiyle ortaya çıkar. Az önce de bahsettiğimiz kupon manipülasyonları da dahil olmak üzere, özellikle bakiye yükleme ve ödeme işlemleri sırasında gerçekleştirilir ve yeterli doğrulama sağlanmazsa, tahmin edebileceğiniz gibi saldırganların ücretsiz ürün satın almasına veya fazladan hesap bakiyesi yükleyebilmesine yol açabilir.
-Mobil Uygulamalarda API Güven Problemleri:
Mobil uygulamalarda kullanıcı kontrollerinin yalnızca uygulama üzerinden yapılması da oldukça yaygın bir problemdir. Eğer sunucu tarafında yeterli doğrulama bulunmuyorsa bu API istekleri değiştirilerek, normalde erişilmemesi gereken verilere ulaşılabilir. Bu durum özellikle mobil uygulamalarda logic zafiyetlerin sık görülmesine neden olmaktadır.
Günlük hayatta karşımıza çıkabilecek kısa bir örnek verelim
Bazı sistemlerin, kullanıcıların belirli adımları takip etmesini beklediğinden söz etmiştik. Peki bu adımlar kullanıcı için pek de istenmeyen bir duruma dönüşüyorsa?
Geçtiğimiz günlerde bunun güzel bir örneğini gördüm. Görünüşe göre American Airlines şirketinin bilet satışı sayfasında şöyle bir sistem çalışıyor:
Gitmek istediğiniz rotayı seçiyorsunuz ve devamında hangi plana göre uçacağınızı seçmeniz gerekiyor. Bu sayfaya geçmeden önce örneğin size; "Basic Economy" adı altında 270 dolarlık bir fiyatla uçuş yapabileceğiniz yazıyor.
Siz bu planla devam etmek için üzerine tıkladığınızda, karşınıza bir pop-up sayfa açılıyor ve buradaki sayfada iki seçeneğiniz var: 270 dolar ücrete "Basic Economy" seçmek veya 330 dolar vererek "Main Cabin" bölümünde oturmak.
Haliyle ucuz olanı seçmek istiyorsunuz fakat sistem onu seçebileceğiniz tuşu pasif hale getirmiş. (Örnek 1.)

Bunun sebebini tam olarak bilmiyorum fakat tahminimce; havayolu şirketi son zamanlarda sık sık baktığınız rotaları fark edip, bu uçuşlarda koltuk sayısı azalmaya başlarsa, kâr edebilmek için size daha pahalı bileti satmaya çalışabiliyor olabilir.
Bu örnekte aslında işleminize devam edebilseniz, bileti istediğiniz fiyattan alabileceksiniz fakat karşınıza çıkan bu sayfayı kapatmanın tek yolu pahalı olan yeri seçmek. O da haliyle koltuğunuzu ve vereceğiniz ücreti değiştiriyor.
Bu durumda kullanıcı basit bir şekilde tarayıcı içerisindeki geliştirici ayarlarını kullanarak bu ekranda bulunan birkaç gereksiz öğeyi silerek işlemine kaldığı yerden devam edebiliyor.
Size böyle bir şey yapın demiyorum tabii ki fakat hiçbir teknik bilgi bilmeden ve harici bir araca ihtiyaç duymadan da günlük hayatta böyle durumlarla karşılaşılabiliyor ve bir şekilde çözüm üretebiliyorsunuz.
Şimdi de kısa ama biraz daha teknik bir örnek ile devam edelim.
İstemci Tarafındaki Kontrollere Fazla Güven
İstemci tarafına fazla güvenilmesinden kaynaklanan sorunlardan birkaç kere söz ettiğimizin farkındayım fakat bu ele aldığımız konuya güzel bir örnek olduğunu düşündüğüm için buradan ilerliyoruz.
Şimdi de PortSwigger üzerinde bulunan bir senaryo ile bu logic zafiyetini inceleyeceğiz.

Siteye giriş yaptığımızda bizi bu şekilde bir mağaza karşılıyor, kendi hesabımıza giriş yaptığımızda 100 dolarlık bir bakiyemizin olduğunu görüyoruz.
Şimdi en üst sırada bulunan ceketi almak istediğimizi varsayalım ve ürünü sepetimize ekleyelim.
Ürünümüzü sepete ekledikten sonra bu şekilde bir satın alma ekranı bizi karşılıyor. "Place Order" butonuna basıp Burp Suite ile istemci ile aramızda olan trafiği yakalayıp paketleri inceliyoruz.


Buradaki POST requestini incelediğimizde müdahale edebileceğimiz bir şey yokmuş gibi görünüyor. Devam etmek istediğimizde ise "bakiye yetersiz" uyarısı alıyoruz.
Bu sefer ürünü sepetten çıkarıp tekrar eklemeyi deniyoruz. Tabii bu sefer de aradaki trafiği incelemeyi atlamıyoruz. (Örnek 5.)


İşte tam da aradığımız şeyi burada bulabildik. Giden POST request içerisinde ürün sayısı ve ücreti gibi parametreler gönderiliyor. Price değerini price=10 şeklinde değiştirip bu paketi gönderirsek, şekilde görebileceğiniz gibi ürün sepetimize 0.10$ olarak ekleniyor. (Örnek5- Örnek6.)
Burada şunu öğreniyoruz ki bu parametreler işlem sırasında sunucu tarafında tekrar doğrulanmıyor ve her şey client-side tarafında yürütülüyor.
Gerçek hayatta bu kadar basit bir örnekle karşılaşacağınızı pek sanmıyorum, ancak buradaki fikir hakkında kafanızda bir şeyler canlanmıştır diye umuyorum.
Şimdi buraya kadar konuştuk.
Peki Business Logic Zafiyetlerinden Nasıl Korunabiliriz?
Bu zafiyetlerde yalnızca klasik güvenlik kontrollerine güvenmek yeterli değildir. Bu açıklar iş akışının yanlış tasarlanmasından kaynaklandığı için güvenlik kontrolleri hem teknik hem de iş kuralı seviyesinde ele alınmalıdır.
İlk olarak kritik işlemler mutlaka sunucu tarafında doğrulanmalıdır. Fiyat, indirim oranı, kullanıcı rolü, bakiye, sipariş durumu veya yetki bilgisi gibi değerler istemci tarafından gönderiliyor olsa bile, sunucu bu değerlere asla doğrudan güvenmemelidir. Örneğin bir ürünün fiyat bilgisi; veri tabanındaki güncel ürün bilgisinden alınmalıdır.
İkinci olarak uygulamanın iş akışı da sunucu tarafından kontrol edilmelidir. Kullanıcının ödeme yapmadan siparişi tamamlaması, gerekli adımları atlaması veya yetkisi olmayan bir işlemi doğrudan HTTP isteği göndererek gerçekleştirmesi kesinlikle engellenmelidir.
Bunun için her kritik işlem öncesinde kullanıcının rolü, işlem durumu ve önceki adımları tamamlayıp tamamlamadığı doğrulanabilir.
Bir diğer önemli nokta eş zamanlı işlemlere karşı önlem alınmasıdır. Kupon kullanımı, bakiye yükleme, para transferi veya stok azaltma gibi işlemler "transaction" mantığı ile yönetilmeli yani aynı işlemin birden fazla kez çalıştırılmasına izin verilmemelidir. Aksi durumda race condition gibi zafiyetlere yol açabilir.
Mobil uygulamalarda da güvenlik yalnızca uygulama arayüzünde bırakılmamalıdır. Örneğin normal kullanıcıların erişmemesi gereken bir işlemin yalnızca uygulama içerisindeki bir butonun gizlenmesi veya premium kullanıcılara özel bir özelliğin sadece arayüz seviyesinde tıklanamayarak kısıtlanması yeterli değildir. Eğer sunucu tarafında gerekli yetki kontrolleri yapılmıyorsa, saldırganlar mobil uygulamanın API isteklerini değiştirerek bu işlemleri doğrudan gerçekleştirebilirler. Bu nedenle mobil uygulamalarda güvenlik kontrolleri arayüz değil, API tarafında da uygulanmalıdır.
Son olarak loglama ve anomali takibi de bu zafiyetlerin tespitinde en önemli yöntemlerden birisidir. Aynı kuponun çok kısa sürede tekrar kullanılması, olağan dışı indirim oranları, beklenmeyen sipariş sayıları veya normalden farklı API kullanımı sistem tarafından izlenmelidir. Bu sayede zafiyetler yalnızca geliştirme aşamasında değil, canlı sistemlerde de daha erken fark edilebilir.
Günümüzde birçok modern uygulama oldukça gelişmiş güvenlik mekanizmalarına sahip olsa da business logic zafiyetleri hâlâ en zor tespit edilen problemler arasında yer alıyor. Bu nedenle geliştiriciler davranışsal olarak da sistemin nasıl kötüye kullanılacağını düşünmek zorundadır.
Sonuç
Evet, bugün logic zafiyetlerin üzerine konuştuk; ne olduklarını, nasıl çalıştıklarını, neden tehlikeli olduklarını ve nasıl önlemler alabileceğimizden bahsettik.
Daha çok sözel ağırlıklı ve genel örneklerden bahsetmiş olsak da logic zafiyet mantığını öğrendiğinizi umuyorum.
Okuduğunuz için teşekkür ederim.