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

Anywhere Elementor 1.3.0: AJAX katmanında bozuk erişim denetimi

Her ön yüz sayfasına basılan bir AJAX nonce'u ve eksik yetki denetimleri, kimlik doğrulamasız içerik ifşasına ve düşük yetkili ayar yazmaya yol açıyor.

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

Özet. Anywhere Elementor 1.3.0, 70.000'in üzerinde kurulumu bildirilen bir WordPress sayfa oluşturma eklentisi; AJAX katmanında bir dizi bozuk erişim denetimi kusuru taşıyor. Ortak kök neden şu: AJAX nonce'u her ön yüz sayfasının HTML'ine her ziyaretçi için basılıyor. Herkesin gördüğü bir kapıyı bekleyen nonce aslında hiçbir şeyi beklemez. Üstüne, nesne ya da yetki düzeyinde hiçbir doğrulama yapmayan işleyiciler eklenince ortaya kimlik doğrulamasız içerik ifşası ve düşük yetkili bir ayar yazma çıkıyor. Yazı; hata sınıfını, kök neden kalıbını, savunmasız noktaya kavramsal olarak nasıl ulaşıldığını, etkiyi ve somut düzeltme/tespit önerilerini ele alıyor. Eşgüdümlü açıklama gereği tam operasyonel örnek (PoC) bir düzeltme çıkana dek saklanıyor; buradaki her şey savunma ve eğitim amaçlı.

Anahtar sözcükler: WordPress, bozuk erişim denetimi, IDOR, nonce yanlış kullanımı, yetki denetimleri, yetkilendirme, güvenli kodlama.

1. Giriş

Anywhere Elementor, Elementor sayfa oluşturucusunu genişletir; oluşturucuyla hazırlanan içeriğin kısa kodlar ve AJAX uçları üzerinden sitenin her yerinde işlenmesini sağlar. Bildirilen 70.000'in üzerinde etkin kurulumuyla eklenti çok sayıda üretim sitesinde çalışıyor. Bu sitelerin çoğu, herkese açık sayfalarının hemen yanında taslak, özel yazı, şablon ve yazar bazlı belge gibi herkese açık olmayan içerik tutuyor.

Buradaki kusurların hiçbiri manşetlik bir uzaktan kod çalıştırma hatası değil. Her biri bir yetkilendirme boşluğu ve yetkilendirme boşlukları sessiz türden sorunlardır. Herkese açık olmayan içeriği sızdırırlar, iç alan şemalarını açığa çıkarırlar, düşük yetkili kullanıcıların site genelindeki ayarları değiştirmesine izin verirler; üstelik eklenti meşru kullanıcılar için sorunsuz çalışmaya devam eder. Kod incelemesini bu yüzden atlatırlar. Aşağıdaki kalıp, her WordPress site sahibinin ve eklenti geliştiricisinin ilk bakışta tanıması gereken bir kalıp.

2. Etkilenen bileşen

EklentiAnywhere Elementor — slug anywhere-elementor
Test edilen sürüm1.3.0 (test sırasında güncel)
Etkin kurulum70.000+
Zafiyet sınıfıBozuk erişim denetimi — kimlik doğrulamasız/düşük yetkili IDOR içerik ifşası ve düşük yetkili ayar yazma (CWE-862 Eksik Yetkilendirme, CWE-639 Kullanıcı Denetimli Anahtar ile Yetkilendirme Atlatma)
Dürüst önemMedium (en etkili sorunlar için); katkı sağlayan birkaç sorun Low
CVSSYazım anında atanmadı — uydurma puan verilmedi
DurumTaze; güncel sürümde kaynak kodda doğrulandı (ön yüz nonce erişilebilirliği ve eksik yetki kapıları yalıtılmış bir localhost laboratuvarında doğrulandı); yamasız

Aynı zayıflığı paylaşan birkaç uç var:

  • A. ae_post_data — kimliğe göre herkese açık olmayan Elementor içeriğini işler (kimlik doğrulamasız).
  • B. ae_repeater_data — kimliğe göre ACF yineleyici alan değerlerini okur (kimlik doğrulamasız).
  • C. [INSERT_ELEMENTOR id=..] kısa kodu — bir Katkıda Bulunan/Yazar, kimliğe göre herhangi bir Elementor belgesini işleyebilir.
  • D. save_modules (aep_module) — bir Abone (ya da yöneticiye karşı CSRF) eklentinin modül-etkinleştirme ayarını yazar; nonce yok, yetki denetimi yok.
  • E. ae_prev_post / ae_prev_term / ae_acf_repeater_fields / ae_acf_flexible_fields — bir Abone ACF alan şemasını numaralandırır / kimliğe göre içerik önizler (yetki eksik).
  • F. ae_term_data — herkese açık olmayanlar dahil herhangi bir taksonominin terimlerini numaralandırır (kimlik doğrulamasız).

3. Teknik analiz

Kümenin altında birbirinden farklı iki kök neden yatıyor.

3.1 Kimlik doğrulama bariyeri sanılan bir ön yüz nonce'u

Eklentinin AJAX nonce'u (aep_ajax_nonce), bir JavaScript nesnesine (aepro.aep_nonce) her ön yüz sayfasında, her ziyaretçi için yerleştiriliyor; enqueue hiçbir kimlik doğrulama kapısı olmadan wp_enqueue_scripts üzerinde çalışıyor. nopriv AJAX işleyicileri de gelen istekleri yalnızca wp_verify_nonce('aep_ajax_nonce') ile doğruluyor, başka hiçbir şeyle değil.

WordPress nonce'u bir CSRF belirtecidir; kimlik doğrulama ya da yetkilendirme mekanizması değildir. Aynı nonce, herkesin okuyabildiği herkese açık HTML'e basıldığında onu doğrulamak tek bir şeyi kanıtlar: istek, tüm dünyaya serbestçe yayımlanmış bir değer taşıyordu. Kusur şu kalıpta net görünür:

php
// Kusurlu kalıbı temsili olarak gösterir (ae_post_data / ae_repeater_data / ae_term_data).// Oturum açmamış ziyaretçiler için kaydedilmiş:add_action( 'wp_ajax_nopriv_ae_post_data', 'ajax_post_data' );
function ajax_post_data() {    // TEK kapı: her herkese açık sayfaya yerleştirilmiş bir nonce.    if ( ! wp_verify_nonce( $_POST['nonce'], 'aep_ajax_nonce' ) ) {        wp_die();    }    // $_POST['post_id'] üzerinde durum / tür / sahiplik / yetki denetimi YOK.    $id = (int) $_POST['post_id'];    echo get_builder_content( $id );   // taslak/özel/başka-yazar içeriğini işler    wp_die();}

Hata, herkese açık bir CSRF belirtecini kimlik ya da izin kanıtı yerine koymaktır. Belirteç herkese açık olduğu için nopriv işleyicisi fiilen kimlik doğrulamasız çalışır; saldırganın denetlediği post_id (CWE-639), ardında hiçbir nesne düzeyinde yetkilendirme olmadan işlenir (CWE-862). ACF-değer okuyucusu (B) ve taksonomi numaralandırıcısı (F) de aynı yapıyı taşır. Kısa kod işleyicisi (C) bir varyasyon: yalnızca bir varlık denetimiyle (get_post() !== null) bir id kabul eder; durum, tür, parola, sahiplik ya da yetki denetimi yoktur. Böylece kendi taslağını önizleyebilen bir Katkıda Bulunan, kimliğe göre herhangi bir belgeyi işleyebilir.

3.2 Ne nonce'u ne de yetki denetimi olan, durum değiştiren bir işleyici

wp_ajax_aep_module olarak kaydedilen save_modules işleyicisi, $_POST['moduleData'] değerini update_option üzerinden aep_modules ayarına yazar. Ne check_ajax_referer ne de current_user_can çağırır:

php
// Kusurlu kalıbı temsili olarak gösterir (save_modules).add_action( 'wp_ajax_aep_module', 'save_modules' );
function save_modules() {    // Burada check_ajax_referer(...) yok ve current_user_can(...) yok.    // (Eklentinin kendi phpcs:ignore NonceVerification.Missing satırı eksikliği doğrular.)    update_option( 'aep_modules', $_POST['moduleData'] ); // site genelinde özellik bayrakları    wp_die();}

Kardeş işleyici save_config'in doğru biçimde nonce ile korunuyor olması bu eksikliği iyice göze batırır: yetkilendirme biliniyor ve aynı kod tabanının başka yerinde uygulanmış, yalnızca burada atlanmış. Yazılan değerler boolean'a zorlandığı için pratik etki, CSRF yoluyla erişilebilen ayar ve özellik-bayrağı kurcalamasıdır; depolanmış XSS ya da kod çalıştırma değil. Yine de yetkisiz bir aktörün gerçekleştirdiği, site genelinde bir durum değişikliğidir.

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

Mekanizma eğitim düzeyinde basittir ve ağda özel bir konum istemez.

Kimlik doğrulamasız IDOR (A, B, F). İşleyicilerin dayandığı kapı bir nonce'tur ve bu nonce, eklentinin sıradan ön yüz sayfalarında her ziyaretçiye gönderdiği HTML'de yayımlanır. Dolayısıyla "geçerli bir nonce'a sahip olmak" bir ayrıcalık değildir; herhangi bir ziyaretçinin sayfayı açar açmaz zaten elinde olan bir şeydir. İstek nonce denetimini geçtiği anda işleyici, yalnızca sayısal bir kimlikle adreslenen içeriği işler ya da döndürür; çağıranın o nesneyi görmeye izinli olup olmadığını hiç sormaz. Taslağa, özel bir yazıya ya da başka yazarın belgesine işaret eden bir kimlik, herkese açık bir kimlikmiş gibi işlenir ve hiç herkese açık olması amaçlanmamış içerik geri döner.

Kısa kod (C). Yalnızca Katkıda Bulunan olan bir kullanıcı kendi taslağını meşru biçimde oluşturup önizleyebilir. O taslaktan çağrılan işleyici, verilen kimliği çözer ve yalnızca ona karşılık gelen bir yazının var olup olmadığını denetler. Kimliğin, Katkıda Bulunanın görmeye izinli olduğu bir belgeye ait olup olmadığını denetlemez; bu yüzden taslağı önizlemek, atıfta bulunulan belgeyi eksiksiz işler.

Ayar yazma (D). Eklentinin modül bayraklarını saklayan işleyici, ne nonce ne de yetki denetimiyle çalışır. En düşük kimlik doğrulamalı rol — bir Abone — buna doğrudan ulaşabilir; nonce bulunmadığı için, oturum açmış bir yöneticiye yönelen siteler arası istek sahteciliği (CSRF) üzerinden de ulaşılabilir.

Hepsini tek bir çizgi birbirine bağlar: kod, bir isteğin düzgün biçimlendiğini doğrular ama çağıranın bu nesne üzerinde bu eylemi yapmaya yetkili olduğunu asla doğrulamaz. Gerçek istek dizisini, parametre değerlerini ve çalıştırılabilir hiçbir komutu bilinçli olarak yayımlamıyoruz. Bir savunmacının riski anlamak ya da kapatmak için bunlara ihtiyacı yok.

5. Etki değerlendirmesi

Bir bütün olarak küme, eklentinin AJAX katmanında sistemik bir bozuk erişim denetimidir.

  • Gizlilik. Herkese açık olmayan Elementor içeriğinin (A, C), ACF yineleyici değerlerinin (B), ACF alan şemasının ve keyfi yazı/terim önizlemelerinin (E), ayrıca herkese açık olmayan taksonomiler dahil taksonomi terimlerinin (F) kimlik doğrulamasız ya da düşük yetkiyle ifşası. Pratikte bu, yayımlanmamış pazarlama sayfalarını, iç şablonları, ACF alanlarında saklanan müşteri verilerini ve bir sitenin içerik yapısını sızdırabilir.
  • Bütünlük. Bir Abone ya da CSRF ile vurulan bir yönetici, eklentinin modül-etkinleştirme bayraklarını site genelinde değiştirebilir (D). Değerler boolean olduğundan bu, kod çalıştırma değil, ayar ve özellik-bayrağı kurcalamasıdır; yine de yetkisiz bir aktör eklentinin her ziyaretçi için nasıl davrandığını değiştirebilir.
  • Erişilebilirlik. Doğrudan etkilenmez.

Hiçbir sorun tek başına kritik değil; dürüst sorun-başına önem bu yüzden en etkili uçlar için (A, C, D) Medium, kalanlar için (B, E, F) Low. CVSS puanı atamıyoruz; yayımlanmış bir puan yok ve uydurmak dürüstlük dışı olur. Asıl mesele birleşimde: tek bir bileşende, her birine az ya da hiç yetkiyle ulaşılabilen birkaç bağımsız yetkilendirme boşluğu.

6. Düzeltme

Düzeltme, yetkilendirme için herkese açık bir nonce'a güvenmeyi bırakmak ve kullanıcı denetimli bir kimliğin nesneyi seçtiği her yere gerçek, nesne düzeyinde denetim eklemektir:

php
// Önerilen düzeltme — işleme / IDOR işleyicileri (A, B, C, E, F):function ajax_post_data() {    // 1) Yalnızca nonce değil, gerçek bir yetki kapısı.    if ( ! current_user_can( 'edit_posts' ) ) {        wp_send_json_error( 'forbidden', 403 );    }    $id = (int) $_POST['post_id'];    // 2) BU nesne için nesne düzeyinde yetkilendirme.    if ( ! current_user_can( 'edit_post', $id ) ) {        wp_send_json_error( 'forbidden', 403 );    }    // 3) Herkese açık olmayan / kitaplık belgelerine Elementor'un kendi görüntüleme ilkesini uygula.    echo get_builder_content( $id );    wp_die();}
// Önerilen düzeltme — durum değiştiren işleyici (D):function save_modules() {    if ( ! current_user_can( 'manage_options' ) ) {        wp_send_json_error( 'forbidden', 403 );    }    check_ajax_referer( 'aep_ajax_nonce' ); // yetki denetimine EK OLARAK CSRF belirteci    // ... anahtarları doğrula/beyaz listele, sonra update_option( 'aep_modules', ... );    wp_die();}

Somut olarak üretici şunları yapmalı:

  1. İşleme/IDOR işleyicilerinde tek kapı olan herkese açık sayfa nonce'unu bırakıp yetki-başına denetimler eklemeli (current_user_can('edit_posts') ve nesne düzeyinde edit_post/durum denetimleri).
  2. save_modules üzerinde current_user_can('manage_options') ve check_ajax_referer zorunlu kılmalı.
  3. Elementor'un kendi görüntüleme ilkesini — elementor_library ve herkese açık olmayan belgeleri kısıtlayarak — hem kısa kodda hem de ae_post_data'da uygulamalı.

Site sahipleri, üretici bir düzeltme yayımlar yayımlamaz düzeltilmiş sürüme geçmeli. Yazım anında düzeltilmiş bir sürüm yok.

7. Site sahipleri için tespit ve sıkılaştırma

Düzeltilmiş bir sürüm çıkana dek, aşağıdaki önlemler doğrudan yukarıdaki mekanizmadan çıkar ve hiçbiri var olmayan bir ürün özelliğini varsaymaz:

  • En az ayrıcalık. Abone, Katkıda Bulunan ve Yazar rollerinin kimlerde olduğunu gözden geçirin. Açık kayıt açıksa, güvenilmeyen tarafların düşük yetkili bir hesap edinebileceğini varsayın; gerekmeyen yerlerde kendi kendine kaydı kapatın (Ayarlar → Genel → Üyelik).
  • Kullanmadığınızı kapatın. Site, eklentinin herkese açık olmayan içeriği AJAX/kısa kodla işlemesine ihtiyaç duymuyorsa, düzeltme çıkana dek eklentiyi ya da o özelliği devre dışı bırakın.
  • Sanal yama / WAF. Bir web uygulaması güvenlik duvarı; etkilenen action değerlerini taşıyan admin-ajax.php isteklerinde kimlik doğrulaması isteyecek — ya da bunları hız sınırlayıp inceleyecek — ve durum değiştiren action'ı kimlik doğrulamasız veya düşük yetkili oturumlardan engelleyecek biçimde yapılandırılabilir. Bunu kod düzeltmesinin yerine değil, geçici bir önlem olarak görün.
  • Belirtileri izleyin. Erişim günlüklerinde çok sayıda ardışık sayısal kimlik arasında dolaşan admin-ajax.php istek yığınlarına ve beklemediğiniz oturumlardan eklenti ayarlarını değiştiren admin-ajax.php isteklerine bakın. Eklentinin modül/ayar seçeneğindeki beklenmeyen bir değişiklik tek başına bir sinyaldir.
  • Herkese açık olmayan içeriği koruyun. Eklenti etkin ve yamasızken taslakları, özel yazıları ve ACF alan değerlerini erişilebilir sayın; açık bir sitede ACF alanlarında sır tutmayın.
  • Güncel kalın. Eklentinin değişiklik günlüğünü takip edin ve güvenlik sürümü çıkar çıkmaz uygulayın.

8. Daha geniş ders

Bütün bunların dibindeki ilke, web güvenliğinin en eski ve hâlâ en çok ihlal edilenlerinden:

Bir CSRF belirteci yetkilendirme kararı değildir. Kimlik doğrulama yetkilendirme değildir. "Nesne var" demek, "çağıran bu nesneyi görebilir" demek değildir.

Buradaki her uç bu üç noktadan birinde çöker. Bir nonce, isteğin kasıtlı olduğunu kanıtlar; isteyenin izinli olduğuna dair hiçbir şey söylemez. Oturum açmamış ziyaretçiler için bir işleyici kaydetmek (nopriv), kodu tüm internet için güvenli kılma sorumluluğu yükler; yani herkese dağıttığı bir belirtece değil, kendi yetkilendirmesine ihtiyacı vardır. Ve kullanıcı denetimli bir kimlik bir nesneyi seçtiğinde (CWE-639), kod yalnızca kimliğin bir şeye çözümlendiğini değil, o belirli nesne üzerindeki izni (CWE-862) doğrulamalıdır. Her wp_ajax_ / wp_ajax_nopriv_ işleyicisini herkese açık bir API ucu gibi ele alın ve istek veriye değmeden önce her biri için sorun: Bunu kim çağırabilir ve hangi nesneler üzerinde?

9. Sorumlu açıklama

Bu araştırma eşgüdümlü zafiyet açıklamasını izler. Bulgular eklentinin bakımcısına özel olarak bildirildi; tam operasyonel örnek — tam istek dizileri, parametre değerleri ve yeniden üretim komutları — bir düzeltme çıkana dek bu herkese açık yazıdan bilinçli olarak tutuldu. Daha ileri teknik yayınların zamanlamasını üreticiyle eşgüdümleyeceğiz.

Tüm testler, yalıtılmış ve localhost'a bağlı bir laboratuvarda, herkese açık GPL lisanslı eklentiye karşı yapıldı. Hiçbir üçüncü taraf ya da üretim sistemine erişilmedi ve herhangi bir üçüncü tarafa ait herkese açık olmayan hiçbir veri toplanmadı.

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 düzeltme çıkana dek saklanır.

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

ElementsKit Lite 4.0.7: Kimlik Doğrulamasız Şablon İfşası