İçeriğe atla
0 XP 0
13 dkderinleşmeyle 14 dk50 XP6 etkinlik

Fonksiyon düzeyi yetki ve sunucu tarafı düzeltme

Bu derste
  • Yatay ve dikey erişim hatasını ayır, HTTP fiil manipülasyonunu tanı, yetkiyi varsayılan ret ve merkezî bir rol katmanıyla sunucuda kapat.
  • Bu derste fonksiyon düzeyindeki yetki hatasını tanır, arayüz gizlemesinin neden denetim olmadığını görür, denetimi sunucu tarafında merkezîleştirirsin.

Puan bütün etkinlikleri cevaplayınca hesaba yazılır. Bu dersi tamamlayınca +50 XP alacaksın. Giriş yapmadan ilerlersen puan yalnız bu tarayıcıda durur.

Fonksiyon düzeyinde yetki hatası, bir işlevi kimin çağırabileceğinin denetlenmemesidir. Önceki derste saldırgan kayıt numarasını değiştiriyordu; burada değişen şey çağrılan işlevin ya da yolun kendisidir. Bu derste iki hata biçimini, yatay ve dikey erişimi ayırır, HTTP fiiliyle yapılan atlatmaları tanır ve denetimi arayüzden alıp sunucuya taşırsın.

Kural aynı kalır: karar istemcide değil, isteğin işlendiği katmanda verilir. Sonunda tek bir unutulan ucun bütün paneli açmasını engelleyen üç ilkeyi kuracaksın.

İşlevi kim çağırabilir: BFLA

Fonksiyon düzeyi yetki hatasının API dünyasındaki adı BFLA'dır (Broken Function Level Authorization, fonksiyon düzeyi yetki kırılması). İki biçimde görünür. Yatay hatada aynı roldeki başka bir kullanıcının verisine ya da işlevine ulaşılır; bir kurye, başka bir kuryenin teslim listesini görür.

Dikey hatada düşük yetkili bir rol, üst rolün işlevini çağırır; bir müşteri, yönetim panelinin ucunu doğrudan çalıştırır. İkisinde de kök neden aynıdır: uç, isteği yapan kişinin rolünü sormadan çalışır.

Fark yalnız yöndedir. Yatay hatada yetki düzeyi aynı kalır, sahibi değişir. Dikey hatada kişi kendi düzeyinin üstüne çıkar. Ölçmek istediğin şey her ikisinde de şudur: bu işlevi çağıran isteğin rolü kontrol ediliyor mu?

En tehlikeli biçim, belgede yer almayan (undocumented) bir yönetim ucudur. Arayüzde ona giden bir düğme yoktur, menüde görünmez, çoğu kullanıcı varlığından habersizdir. Ama uç sunucuda tanımlıdır ve adresi tahmin edilebilir bir kalıptaysa bulunması zor değildir.

Adres bilinip doğrudan çağrıldığında sunucu, isteğin arayüzden mi yoksa bir komut satırı aracından mı geldiğini ayıramaz. Rol denetimi yoksa uç çalışır. Bu yüzden bir işlevi listeden gizlemek onu korumaz; korumak, çağıran her isteğin rolünü sunucuda denetlemektir.

Somut bir örnek gör. Altay Kargo portalının müşteri arayüzünde yalnız gönderi takibi vardır. Ama sunucuda /api/yonetim/personel yolu tanımlıdır ve şube müdürleri kullanır.

Bir müşteri, tarayıcısının ağ sekmesinde kendi isteklerinin kalıbını görür: /api/gonderiler, /api/iadeler. Aynı kalıptan yola çıkıp /api/yonetim/personel adresini elle dener. Uç rol denetimi yapmıyorsa, müşteri kendi oturumuyla bütün personel listesini indirir.

Hiçbir düğmeye basmamıştır; yalnız bir adresi tahmin edip doğrudan çağırmıştır. Olay dikey bir yetki yükselmesidir ve arayüzde hiçbir iz bırakmaz. Savunan için ders açıktır: yolun gizli olması onu güvenli yapmaz, yola konan rol denetimi yapar.

Etkinlik 1 / 6

Altay Kargo portalındaki olayları erişim hatasının türüne göre ayır.

Önce bir seçeneğe, sonra aşağıdaki uygun kutuya bas. İstersen seçeneği kutuya sürükleyip bırak. Yerini değiştirmek için aynı işlemi tekrarla.

0/4 seçenek yerleşti.

Arayüzde gizlemek denetim değildir

Çoğu ekip bu hatayı arayüzde çözmeye çalışır: yönetim düğmesini müşteriden gizler, menüde göstermez. Bu bir denetim değildir, yalnız bir görünüm tercihidir. Saldırgan düğmeye hiç ihtiyaç duymaz; isteği doğrudan bir HTTP aracıyla, ucun adresini bilerek yollar. Arayüzdeki gizleme tarayıcıda çalışır ve tarayıcı kullanıcının elindedir.

Sayfadaki koşulu değiştirmek, gizli alanı geri açmak ya da isteği hiç tarayıcı kullanmadan kurmak mümkündür. Denetim, isteğin sunucuya ulaştığı an, uygulama katmanında yapılmalıdır. Aksi halde koruma, kapının anahtarını kapının önündeki paspasın altına koymak gibidir.

İstemcitarayıcı, JavaScriptUygulamayönlendirme, iş kuralıŞablon motoruçıktı üretimiVeri katmanıSQL, dosya
Web uygulamasının katmanları. Yalnız üstteki istemci katmanı kullanıcının elindedir.

Şemada en üstte istemci durur; oradaki kod kullanıcı deneyimine hizmet eder ve kullanıcı onu kapatabilir ya da hiç çalıştırmayabilir. Asıl denetim uygulama katmanında, her istekte çalışır. Veri katmanındaki sorgu ise sahipliği süzer.

Düğmeyi gizleyen kontrol yalnız istemcide kalırsa, istek doğrudan gönderildiğinde hiç devreye girmez; sunucu isteği sanki yetkili bir kaynaktan gelmiş gibi işler. Katmanları ayırt etmek önemlidir, çünkü aynı kural farklı katmanlarda farklı iş yapar: istemci gösterir, uygulama karar verir, veri katmanı süzer. Güvenlik kararı yalnız ortadaki katmana aittir.

Etkinlik 2 / 6

Rol denetimi hangi katmanda çalışmalıdır?

Diyagramda doğru kutuyu tıkla.

İstemcitarayıcı, JavaScriptUygulamayönlendirme, iş kuralıŞablon motoruçıktı üretimiVeri katmanıSQL, dosya

HTTP fiil manipülasyonu

Bazı denetimler yalnız belli bir HTTP fiiline bakar ve saldırgan fiili değiştirerek bunu atlatır. Buna fiil manipülasyonu (verb tampering) denir. Kök neden, kuralın isteğin kendisine değil, fiiline bağlanmasıdır.

Kural GET için yazılmışsa, aynı yolu HEAD, POST ya da uydurma bir fiille çağıran istek kuralın dışında kalabilir. Çerçeve ise bu isteği çoğu zaman yine bir işleyiciye ulaştırır. Express'te app.head tanımlı değilse HEAD isteği app.get işleyicisine düşer.

Sızma testinde bu yüzden yalnız beklenen fiil değil, HEAD, POST, PUT ve uydurma fiiller de denenir. Giriş sayfasına yönlendirmesi ya da 403 dönmesi gereken bir yolun 200 dönmesi bir atlatma işaretidir.

İkinci bir atlatma yolu fiil örtme başlıklarıdır. Bir ön uç vekil ya da güvenlik duvarı PUT ve DELETE gibi fiilleri engelleyebilir. O zaman saldırgan isteği POST olarak yollar ve gerçek fiili bir örtme başlığında taşır: X-HTTP-Method-Override, X-HTTP-Method ya da X-Method-Override. Uygulama bu başlığı okuyup isteği DELETE gibi işlerse, ön uçta kurulan sınır boşa çıkar.

Savunma iki yönlüdür. Yol yetkisini tek bir fiile değil, o yola izin verilen bütün fiillere göre tanımla. Fiil örtme başlıklarını ya tümden kapat ya da yetki denetiminden sonra uygula. Denetim, fiil ne olursa olsun aynı kararı vermelidir.

// Güvensiz: rol denetimi yalnız GET'e bakıyor
app.use("/api/yonetim", (req, res, next) => {
  if (req.method === "GET" && req.oturum.rol !== "yonetici")
    return res.status(403).end();
  next();
});
app.get("/api/yonetim/rapor", raporUret);

# Müşteri oturumuyla aynı adrese iki deneme
$ PORTAL=https://portal.altaykargo.example
$ curl -s -o /dev/null -w '%{http_code}\n' -b oturum=k9f2 $PORTAL/api/yonetim/rapor
403
$ curl -s -o /dev/null -w '%{http_code}\n' -b oturum=k9f2 -I $PORTAL/api/yonetim/rapor
200
-I seçeneği isteği HEAD fiiliyle yollar. Aynı yol, aynı oturum, farklı sonuç.

Ara katmandaki koşul yalnız GET isteğini yakalar. Müşteri oturumuyla gelen GET 403 alır; ilk curl komutu bunu gösterir.

İkinci komut aynı adrese HEAD yollar. HEAD koşula uymaz ve next() ile yoluna devam eder. Express, app.head tanımlı olmadığı için isteği app.get işleyicisine verir ve raporUret çalışır. Yanıtta gövde yoktur, ama 200 kodu ve Content-Length gibi başlıklar raporun var olduğunu söyler.

Asıl tehlike işleyicinin yan etkisidir: rapor üretmek bir e-posta gönderiyor ya da kayıt yazıyorsa, bu da yetkisiz biçimde gerçekleşir. Düzeltme basittir. Koşuldan fiil kontrolünü çıkarırsın ve rol denetimi fiil ne olursa olsun çalışır.

Derinleş:Fiil manipülasyonunun klasik kökü

Fiil manipülasyonu yeni bir fikir değildir. 2000'lerin sonunda yayımlanan bir araştırma, bazı Java uygulama sunucularında bildirimsel güvenlik kurallarının nasıl atlandığını gösterdi. Yapılandırma dosyasındaki kural, korunacak fiilleri tek tek sayıyordu; örneğin yalnız GET ve POST.

Sayılan fiiller için oturum ve rol denetimi çalışıyor, listede olmayan fiiller ise kuralın tamamen dışında kalıyordu. Buna ikinci bir davranış ekleniyordu: sunucular HEAD isteğini GET işleyicisine veriyor, bazıları tanımadıkları uydurma bir fiili de GET gibi işliyordu. İkisi birleşince oturum isteyen bir işlem, başka bir fiil yazılarak denetimsiz çalışıyordu.

Önerilen düzeltme, kurala fiil listesi yazmamak ve böylece kuralı bütün fiillere uygulamaktı. Ders bugün de geçerlidir: denetim izin verilen fiilleri sayan bir listeye değil, isteğin kendisine bağlanır ve tanımlanmamış her şey reddedilir.

Etkinlik 3 / 6

Ön uç vekil DELETE'i engelliyor. İstek POST olarak gidecek; gerçek fiili X-HTTP-Method-Override başlığında taşıyan satırı yaz.

İsteği tamamla ve gönder.

POST /api/gonderiler/55121 HTTP/1.1
Host: portal.altaykargo.example
Cookie: oturum=k9f2...
Content-Type: application/json
Örtme başlığı:

Sunucu tarafı düzeltme: varsayılan ret

Güvenli tasarım üç kurala dayanır. Varsayılan ret: herkese açık kaynaklar dışında, açıkça izin verilmeyen her istek reddedilir. Merkezî denetim: kural her uca elle yazılmaz, ortak bir ara katmanda durur; yeni uç eklenince kural kendiliğinden uygulanır. Rol eşlemesi: her yol, hangi rollerin çağırabileceğini açıkça listeler.

Üç kural birlikte, unutulan tek bir ucun bütün sistemi açmasını engeller. Bu üç kural, önceki dersteki sahiplik filtresinin fonksiyon düzeyindeki karşılığıdır. Orada sorgu sahipliği süzüyordu, burada ara katman rolü süzer. İkisi de kararı istemciden alıp sunucuya koyar.

// Güvenli: tek rol tablosu, merkezî denetim, varsayılan ret
const izinler = {
  "GET /api/gonderiler": ["musteri", "kurye"],
  "POST /api/iadeler/onay": ["sube-muduru"],
  "GET /api/yonetim/personel": ["yonetici"],
};
app.use("/api", oturumGerekli, (req, res, next) => {
  const roller = izinler[req.method + " " + req.baseUrl + req.path];
  if (!roller?.includes(req.oturum.rol)) return res.status(403).end();
  next();
});
Tabloda olmayan fiil ve yol çifti, rol ne olursa olsun 403 alır.

Tablo her fiil ve yol çiftini, onu çağırabilecek rollere eşler. Ara katman /api altındaki her istekte çalışır: önce oturumu ister, sonra fiil ile yoldan bir anahtar kurar ve tabloya bakar. Anahtar tabloda yoksa ya da oturumdaki rol listede değilse 403 döner.

Yeni bir uç tabloya yazılmadan eklenirse bu koşul onu kapatır. HEAD ya da uydurma bir fiil de tabloda olmadığı için aynı yerde durur; önceki bölümdeki atlatma burada işe yaramaz. Gerçek projede /api/iadeler/55/onay gibi parametreli yollar için yol kalıbını eşleyen bir yardımcı kullanılır, ama ilke değişmez.

Etkinlik 4 / 6

İade onayı yalnız şube müdürünün işidir. Rol denetimi eksik satırı bul.

Zafiyetli satıra tıkla.

Merkezî denetim ile varsayılan ret birlikte çalışınca, insan hatası bile güvenli tarafa düşer. Bir geliştirici yeni bir uç ekleyip rol eşlemesini yazmayı unutursa, uç açıkta kalmaz; hiçbir role eşlenmediği için varsayılan ret onu kapatır. Zayıf tasarımda ise varsayılan izin olur: eşlenmeyen yol açık gelir, unutulan uç sessizce herkese açılır.

Tek fark, sistemin hata anındaki davranışıdır. Güvenli sistem, şüphede kaldığında kapıyı kapatır.

Etkinlik 5 / 6

Yeni bir API ucu eklendi ama hiçbir rol ara katmanına bağlanmadı. Merkezî denetim ve varsayılan ret kuralı birlikte ne yapar?

Rol eşlemesi ve belge-kod farkı

Rol eşlemesi büyüdükçe tek bir listeye sığmaz; bu yüzden çoğu ekip rolleri kümelere ayırır. Müşteri kümesi yalnız kendi kayıtlarını okur ve günceller. Kurye kümesi kendi teslimat listesini görür. Şube müdürü kümesi iade onayı gibi işlemleri de çağırabilir.

Yönetici kümesi personel yönetimine erişir. Her yeni uç yazılırken hangi kümenin çağırabileceği baştan kararlaştırılır; bu karar koda gömülmez, ayrı bir rol eşleme tablosuna yazılır. Bu yaklaşımın adı rol tabanlı erişim denetimidir (RBAC). Böylece bir yıl sonra gelen yeni bir geliştirici de kuralı kod içinde aramak zorunda kalmaz, tabloya bakar.

Tablo aynı zamanda bir doğrulama aracıdır. Çoğu ekip API'yi bir OpenAPI belgesiyle tanımlar; belge her ucun hangi role açık olduğunu da taşıyabilir. Belgeyle koddaki gerçek ara katman eşlemesini karşılaştıran bir denetim, aradaki farkı yakalar.

Belgede yönetici gerektiren bir uç kodda korunmasızsa, bu fark yayına çıkmadan görünür. Böylece yetki, insan belleğine değil, karşılaştırılabilir iki kayda dayanır. Belge ile kodun birbirini tutması, gözden kaçan bir ucun sessizce açık kalmasını önler.

Rol tabanlı denetim çoğu portal için yeter, ama her durumu karşılamaz. Bazı kararlar role değil, kaydın özelliğine bağlıdır. Bir şube müdürü yalnız kendi şubesinin iadelerini onaylayabilmeli, başka şubeninkini değil. Bu tür kurallar için özellik tabanlı erişim denetimi (ABAC) kullanılır; karar, kullanıcının ve kaydın özelliklerini birlikte değerlendirir.

Uygulamada ikisi çoğu zaman birlikte çalışır: rol kaba kapıyı açar, özellik denetimi ince sınırı çeker. Şube müdürü rolü iade onayı ucunu açar, sonra kaydın şube alanı ile kullanıcının şubesi karşılaştırılır. Hangisini seçersen seç, kural yine tek bir yerde, sunucuda ve tabloya yazılı durur; koda dağılmış koşullar zamanla tutarsızlaşır.

Derinleş:İki eski maddenin tek çatısı

Bozuk erişim denetimi listenin en tepesine bir anda çıkmadı. OWASP Top 10'un 2013 sürümünde bugün tek başlık altında topladığımız kusur iki ayrı maddeydi: A4 güvensiz doğrudan nesne başvurusu (IDOR) ve A7 eksik fonksiyon düzeyi erişim denetimi. 2017 sürümünde bu iki madde, resmî sürüm notlarının açıkça belirttiği gibi, tek bir başlıkta, A5 bozuk erişim denetiminde birleştirildi.

Nedeni pratikti: ikisi de aynı kök nedeni, yani sunucunun istemciye güvenmesini paylaşıyordu. Ayrı tutmak, savunanı iki farklı hata gibi düşünmeye itiyordu. 2021'de bu birleşik başlık listenin birinci sırasına yükseldi ve 2025 sürümünde de orada kaldı. Nesne düzeyi ve fonksiyon düzeyi hataları bu yüzden bugün aynı ailenin iki koludur; ikisini birlikte öğrenmek, kök nedeni bir kez kavramak demektir.

Bu iki dersin kök nedeni hep aynıydı: sunucu istemciye güvendi. Sıradaki derste bu güvenin daha en baştan, giriş ve oturum kurulurken nasıl kırıldığını göreceksin; orada saldırgan kayıt numarası ya da yol değil, doğrudan kimliğin kendisiyle oynar. Erişim denetimi kimin ne yapabileceğini korurken, kimlik doğrulama o kişinin sahte olup olmadığını korur.

İki koruma birbirine dayanır: kimliği yanlış bilen bir sistem, yetki denetimi kusursuz olsa bile yanlış kişiyi yetkilendirir. Bu yüzden sıradaki iki ders, zincirin ilk halkasını, yani girişi ve oturumu ele alır.

Etkinlik 6 / 6

Doğru mu, yanlış mı?

Bir yönetim düğmesini arayüzden gizlemek, o işlevi çağıran bir isteği sunucuda da engeller.

Bu derste bir hata mı gördün? Bildir