İçeriğe atla
Noroxi
Araştırma7 dk

301 Redirects 2.85: Eksik Yetkilendirme (CWE-862)

301 Redirects 2.85'te yalnızca nonce denetleyen bir AJAX eylemi, Abone düzeyindeki kullanıcıya site geneli bir seçeneği yazdırıyor (CWE-862).

Noroxi EkibiSızma testi ve güvenlik danışmanlığı

Özet. WordPress eklentisi 301 Redirects'in 2.85 sürümü, nonce doğrulayan ama hiçbir yetki (capability) denetimi yapmayan bir AJAX eylemi kaydediyor. Sonuçta kimliği doğrulanmış herhangi bir kullanıcı — bir Abone bile — site geneli bir seçeneğe yazabiliyor (CWE-862). Durumu eşgüdümlü ifşa kapsamında eklenti geliştiricisine bildirdik; çalışır kavram kanıtını (PoC) yama çıkana dek paylaşmıyoruz. Aşağıda kök nedeni, arkasındaki güvenli kodlama dersini ve mekanizmadan doğrudan çıkan tespit ile sertleştirme adımlarını bulacaksınız.

Anahtar sözcükler: WordPress güvenliği, eksik yetkilendirme, erişim denetimi, CWE-862, AJAX nonce, yetki denetimi, yetki sınırı.

1. Giriş

301 Redirects (slug eps-301-redirects), yönetim alanından URL yönlendirmelerini yöneten ve 300.000'den fazla sitede çalışan bir eklenti. Bu sitelerin azımsanmayacak bir kısmı herkese açık kayda izin veriyor, yani yabancılara Abone düzeyinde hesap açıyor. Böyle bir kurulumda, bir Abone'nin yetki sınırını aşmasına kapı aralayan her kusur — doğrudan etkisi küçük kalsa bile — yakından bakmayı hak eder.

Buradaki kusur eksik yetkilendirme; bozuk erişim denetiminin sunucu tarafındaki yarısı. Kod, bir isteği kimin gönderdiğini nonce ile doğruluyor ama o kullanıcının eylemi yapmaya yetkisi olup olmadığını yetki denetimiyle hiç sorgulamıyor. WordPress eklenti dünyasının en sık rastlanan hatalarından biri bu. Elimizdeki örnek ise iki denetimin neden farklı sorunları çözdüğünü anlatan, bulabileceğiniz en temiz ders örneklerinden.

2. Etkilenen bileşen

Eklenti301 Redirects — slug eps-301-redirects
Test edilen sürüm2.85 (test sırasında güncel)
Etkin kurulum300.000+
Açık türüEksik Yetkilendirme / Bozuk Erişim Denetimi
CWECWE-862 Missing Authorization
Gereken yetkiKimliği doğrulanmış herhangi bir kullanıcı — Abone
CVSS 3.1~4.3 (Düşük) AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
DurumTaze; güncel sürümde kod düzeyinde doğrulandı ve laboratuvarda yeniden üretildi

3. Teknik analiz

Eklenti, kimliği doğrulanmış kullanıcılara açık eps_dismiss_pointer adlı bir AJAX eylemi kaydediyor. İşleyici önce nonce'u denetliyor, ardından site geneli eps_pointers seçeneğine yazıyor. Geçerli kullanıcının bu seçeneği değiştirmeye yetkili olup olmadığını ise hiçbir noktada sormuyor.

Kök neden kodu — eps-301-redirects.php:

php
add_action('wp_ajax_eps_dismiss_pointer', array($this, 'dismiss_pointer_ajax'));   // authenticated; any role
function dismiss_pointer_ajax() {    check_ajax_referer('eps_dismiss_pointer');          // nonce only — NO current_user_can()    if (!isset($_POST['pointer_name'])) { wp_send_json_error(); }    $pointers = get_option('eps_pointers');    $pointer  = trim(sanitize_text_field(wp_unslash($_POST['pointer_name'])));    if (empty($pointers) || empty($pointers[$pointer])) { wp_send_json_error(); }    unset($pointers[$pointer]);    update_option('eps_pointers', $pointers);           // SINK: site-global option write    wp_send_json_success();}

check_ajax_referer() bir WordPress nonce'unu doğrular ve nonce bir CSRF karşıtı belirteçtir. İsteğin, kullanıcının meşru biçimde açtığı yakın tarihli bir sayfadan geldiğini gösterir; kullanıcının yetkileri konusunda tek kelime etmez. Yetkilendirme WordPress'te current_user_can( $capability ) ile yapılır, bu işleyici ise o çağrıyı hiç içermez. Böylece site geneli bir update_option() önündeki tek engel "çağıran oturum açmış mı ve elinde geçerli bir nonce var mı" sorusuna iner. Bir Abone her ikisini de geçer.

Eylemin yalnızca wp_ajax_ altında kaydedilmesi (yani wp_ajax_nopriv_ olmaması) onu anonim ziyaretçilerden doğru biçimde uzak tutar. Ama kimliği doğrulanmış olmak, yetkili olmak demek değildir. Abone kimliği doğrulanmış bir kullanıcıdır ve bu eklentide sink'e ulaşmak için gereken yalnızca budur.

4. Kusura nasıl ulaşılıyor (kavramsal)

Abone'nin bu eylemi tetikleyebilmesinin ardında, daha yukarıda duran ikinci bir ihmal var: eyleme çağrı için gereken nonce fazlasıyla geniş dağıtılıyor.

Eklenti, yönetim varlıklarını — yerelleştirilmiş nonce dahil — init'e kancalanan ve tek korumasını is_admin()'den alan bir plugin_resources() yönteminde kuyruğa alıyor. is_admin() yalnızca isteğin yönetim alanını hedefleyip hedeflemediğine bakar; bir yetki denetimi değildir ve bir yönetim sayfasını açan her oturumlu kullanıcı için true döner. Aboneler bu sayfaların bir kısmını — örneğin kendi profil ekranlarını — meşru şekilde açabilir, nonce da tam bu sayfaların çıktısında bulunur.

Öğretici düzeyde zincir üç halkadan oluşur:

  1. Site geneli bir seçeneğe yazan işleyicinin tek koruması nonce'tur.
  2. Bu nonce, verilmesi bir yetki yerine is_admin()'e bağlandığı için Abonelerin görebildiği yönetim sayfalarında yayımlanır.
  3. Böylece Abone, yalnızca yöneticiler için düşünülmüş bir eyleme ait geçerli bir nonce edinir ve işleyici çalışırken yetkilerini bir daha denetlemez.

Ortaya çıkan şey bir yetki sınırı aşımıdır: tek yeteneği read olan bir kullanıcı, değiştirmeye hiç yetkisi olmayan site geneli bir ayarı değiştirir. İstek dizisini ve yükleri (payload) bilerek dışarıda bırakıyoruz. Savunmacı için ders, çalıştırılabilir bir tarif değil, hatanın biçimidir.

5. Etki değerlendirmesi

Pratikte etki düşük. Bu işleyiciyle ulaşılabilen tek seçenek eps_pointers; yöneticiye yönelik tanıtım ipuçlarını ("pointer") tutan bir kayıt. Abone buradan girdi silebilir ve bu ipuçlarını yöneticilerden gizleyebilir. Veri ifşası yok, erişilebilirlik kaybı yok, bu yolla yönlendirmeleri ya da güvenlikle ilgili başka bir ayarı değiştirme imkânı da yok.

CVSS vektörü bunu birebir yansıtır: AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N (~4.3, Düşük) — ağ üzerinden erişilebilir, düşük karmaşıklık, düşük yetki, kullanıcı etkileşimi yok, kapsam değişmez, gizlilik ve erişilebilirlik etkisi yok, yalnızca düşük bütünlük etkisi. Bu bulguyu yayımlamaya değer kılan, etki yarıçapı değil; 300.000 kurulumlu bir eklentide açığa çıkardığı kalıp. Aynı kalıbı daha hassas bir seçeneğe yöneltin, sonuç artık düşük olmaktan çıkar.

6. Giderme

Zaten orada duran nonce denetiminin hemen yanına işleyiciye bir yetkilendirme denetimi ekleyin. Eklenti, başka yerlerde — örneğin add_widget() içinde — kullandığı bir yetki filtresini tanımlar; bunu yeniden kullanmak davranışı tutarlı tutar:

php
function dismiss_pointer_ajax() {    check_ajax_referer('eps_dismiss_pointer');    if (!current_user_can(apply_filters('eps_301_redirects_capability','manage_options'))) {        wp_send_json_error();                           // yetkilendirme: yalnızca yetkili kullanıcılar    }    // ... mevcut mantık ...}

Site sahipleri için:

  • Geliştirici bir yama yayımladığı an güncelleyin. Bu satırların yazıldığı sırada 2.85 hâlâ güncel sürüm ve ortada bir yama yok.
  • O zamana dek sorunu düşük riskli ama gerçek sayın ve aşağıdaki sertleştirmeleri uygulayın — en çok da açık kayda izin veren sitelerde.

7. Site sahipleri için tespit ve sertleştirme

Aşağıdakilerin tümü yukarıdaki mekanizmadan doğrudan çıkar.

  • Düşük yetkili hesapları asgaride tutun. Siteniz herkese açık kayda ihtiyaç duymuyorsa kapatın (Ayarlar → Genel → Üyelik). Açık, kimliği doğrulanmış bir Abone ister; bu tür hesap azaldıkça maruziyet de azalır.
  • En az ayrıcalık ilkesini uygulayın. Eldeki hesapları gözden geçirin, her kullanıcıya işini gören en düşük rolü verin. Burada asıl önemli saldırı yüzeyi, atıl ya da beklenmedik Abone hesaplarıdır.
  • admin-ajax.php'de sıra dışı çağıranı izleyin. Erişim günlüklerinde, bu eklentinin dismiss-pointer eylemini taşıyan ve yönetici olmayan hesaplardan gelen istekler bir göz atmayı hak eder. Daha genel olarak, kimliği doğrulanmış yönetici olmayan kullanıcıların yönetim odaklı AJAX eylemlerini çağırması sağlam bir tespit ipucudur.
  • Sanal yama / WAF. Bir web uygulaması güvenlik duvarı veya sanal yama kuralı, eklenti güncellenene kadar eksik yetkilendirme sınırını uç noktada tutabilir — örneğin bu AJAX eylemini yalnızca yetkili oturumlara açarak. Bu bir hafifletme yaklaşımıdır, belli bir ürünün tavsiyesi değil.
  • Güncel kalın. Eklentileri güncel tutun ve yamalı sürümün hızla uygulanması için geliştiricinin sürüm notlarını takip edin.

8. Daha geniş ders

Nonce bir yetkilendirme denetimi değildir. Akılda tutulması gereken tek fikir bu ve bu eklentinin çok ötesinde geçerli:

  • check_ajax_referer() ve wp_verify_nonce() bir CSRF karşıtı soruyu yanıtlar: Bu istek, bu kullanıcının meşru ve yakın tarihli bir sayfa yüklemesinden mi geldi?
  • current_user_can() yetkilendirme sorusunu yanıtlar: Bu kullanıcının bunu yapmasına izin var mı?

Durum değiştiren her işleyicinin iki yanıta da ihtiyacı vardır. Yanında ikinci bir ilke gelir: yetki taşıyan belirteçleri, o yetkiye sahip olmayan kullanıcılara sızdırmayın. Nonce verilmesini bir yetki yerine is_admin()'e, yani bir bağlam denetimine bağlamak, eylemi yapabilecek kitleyi genişletir. Yetkili bir eylem tasarlarken belirteci ve işleyiciyi aynı yetkiye bağlayın, varsayılan olarak reddedin.

9. Sorumlu ifşa

Bu araştırma eşgüdümlü (sorumlu) ifşa kapsamında yürütüldü. 301 Redirects geliştiricisini özel olarak bilgilendirdik; çalışır kavram kanıtının tamamı yama çıkana dek bu kamuya açık yazının dışında kalıyor. Tam teknik ayrıntıyı yalnızca yamalı sürüm yayımlandıktan sonra ya da standart 90 günlük pencerenin ardından, zamanlamayı geliştiriciyle eşgüdümleyerek paylaşmayı planlıyoruz; ayrıca bir CVE talep edeceğiz.

Tüm testler, herkese açık GPL eklentisine karşı izole ve yalnızca localhost'a bağlı bir laboratuvar ortamında yapıldı. Hiçbir üçüncü taraf ya da üretim sistemine dokunulmadı. Test eklentisi ve test hesapları sonradan kaldırıldı. Buradaki hiçbir şey saldırıyı kolaylaştırmak için değil; geliştiriciler ve site sahipleri bu hata sınıfını tanıyabilsin, önleyebilsin ve tespit edebilsin diye yayımlandı.

Kaynaklar


Savunma ve eğitim amacıyla yayımlanmıştır. Noroxi LLC yalnızca yetkili güvenlik araştırması yürütür; operasyonel istismar ayrıntıları bir yama çıkana kadar yayımlanmaz.

Bu hafta sömürülenler · her pazartesi

KEV'e girenler, yeni PoC'ler, WordPress triyajı ve bu hafta ne yapmalı. Hesap gerekmez.

Adresiniz yalnızca bu e-posta için kullanılır; üçüncü tarafla paylaşılmaz.

Sıradaki

Admin and Site Enhancements'ta IDOR: ek dosya URL'si ifşası