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

Happy Addons for Elementor SSRF: API anahtarı temizleme hatası (CWE-918)

Happy Addons for Elementor 3.50.0'daki temizlenmemiş Mailchimp API anahtarı alanı, Katkıda Bulunan'ın sunucu taraflı istek tetiklemesine yol açıyor (CWE-918).

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

Özet. Happy Addons for Elementor 3.50.0 (400.000+ etkin kurulum), Katkıda Bulunan (Contributor) yetkisine sahip herkesin erişebildiği bir Sunucu Taraflı İstek Sahteciliği (SSRF) zafiyeti barındırıyor (CWE-918). Kök neden tanıdık: giden bir URL'nin içine girecek değer, URL meta karakterlerini olduğu gibi bırakan bir filtreyle temizleniyor; yani seçilen temizleyici, verinin aktığı bağlama uymuyor. Kusurlu kodu ve doğru düzeltmeyi güvenli kodlama örneği olarak ele alıyoruz. Eşgüdümlü açıklama gereği yeniden üretim adımları satıcıda kalıyor; bu metin savunma amaçlı — hata sınıfını nasıl tanıyacağınızı, önleyeceğinizi ve tespit edeceğinizi gösteriyor, nasıl çalıştıracağınızı değil.

Anahtar kelimeler: SSRF, CWE-918, girdi temizleme, WordPress eklenti güvenliği, Elementor, bulut meta veri, derinlemesine savunma, en az yetki.

1. Giriş

Happy Addons for Elementor, Elementor sayfa oluşturucu için bir pencere öğesi paketi ve 400.000'den fazla WordPress sitesinde kurulu. Bu büyüklükte bir rakam işin bahsini değiştiriyor: zayıf tek bir yapı taşı, eklentiyi ekleyen her siteye gidiyor, dolayısıyla tek bir kusur ölçekli biçimde devralınıyor.

Sunucu Taraflı İstek Sahteciliği (SSRF, CWE-918), en yıkıcı web zafiyetlerinden biridir; çünkü uygulama sunucusunu, güven sınırının içinden konuşan bir vekile çevirir. Bu vekili ele geçiren saldırgan, internete asla açılmaması gereken yerlere uzanabilir: dahili yönetim panelleri, veritabanları ve kısa ömürlü kimlik bilgileri dağıtan bulut meta veri uç noktaları. Bu vakayı incelemeye değer kılan şey, ne kadar sıradan göründüğü. Girdiyi temizleyen bir satır, geliştiricinin istediğini aynen yapıyor; ama işe yanlış temizleyici seçildiği için SSRF'yi durdurmak adına hiçbir şey yapmıyor.

2. Etkilenen bileşen

EklentiHappy Addons for Elementor — slug happy-elementor-addons
Test edilen sürüm3.50.0 (test sırasında güncel)
Etkin kurulum400.000+
Zafiyet türüSunucu Taraflı İstek Sahteciliği (SSRF)
CWECWE-918 Server-Side Request Forgery
Gereken yetkiKatkıda Bulunan (edit_posts yetkisi olan herhangi bir kullanıcı; Elementor düzenleyici nonce'unu alır)
CVSS 3.1~6.5 (Orta) AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L
DurumYeni; kodda doğrulandı. Yazım anında yama yok — eşgüdümlü açıklama sürüyor.

3. Teknik analiz

Kimlik doğrulamalı AJAX eylemi ha_process_dynamic_select (wp_ajax_ha_process_dynamic_select), kullanıcının verdiği bir API anahtarından Mailchimp listelerini çözümler. Bir nonce denetimi (wp_verify_nonce('ha_editor_nonce')) ve bir yetki denetimiyle (current_user_can('edit_posts')) korunur. Varsayılan — custom olmayan — dalda anahtar global_api istek alanından gelir ve sanitize_text_field() üzerinden geçer:

php
// classes/select2-handler.php  (process_mailchimp_list)$choose_api  = ... sanitize_text_field($_REQUEST['mailchimp_api_choose']) ...;$global_api  = ! empty($_REQUEST['global_api'])   ? sanitize_text_field($_REQUEST['global_api']) : '';$custom_api  = ! empty($_REQUEST['mailchimp_api']) ? sanitize_key($_REQUEST['mailchimp_api'])     : $global_api; // "custom" dalı sanitize_key kullanır (güvenli)$current_api = $global_api;if ($choose_api == 'custom') { $current_api = $custom_api; }...$options = Mailchimp_Api::get_mailchimp_lists($current_api);

Her şey hangi temizleyicinin çalıştığına bağlı. sanitize_text_field() etiketleri atar, boşlukları sadeleştirir ve /, :, . ya da @ gibi URL meta karakterlerini gönül rahatlığıyla yerinde bırakır. Serbest metin için bu sorun değil. Ama bu değer serbest metin değil — giden bir URL'nin parçası oluyor. Doğru cevabı zaten custom dalı gösteriyor: sanitize_key() yalnızca küçük harf alfanümerik karakterlere, tirelere ve alt çizgilere izin verir, bu da deliği kapatırdı. global_api dalı aynı muameleyi hiç görmüyor.

Akışın devamında get_mailchimp_lists(), istek host'unu doğrudan anahtarın "datacenter" bölümünden — ilk - işaretinden sonraki ne varsa — kurar ve sunucu taraflı bir HTTP isteği atar:

php
// widgets/mailchimp/mailchimp-api.php$server = explode('-', self::$api_key);if (!isset($server[1])) return 0;$url = 'https://' . $server[1] . '.api.mailchimp.com/3.0/lists';  // $server[1] saldırganın etkisinde$response = wp_remote_post($url, ...);

Host, saldırganın etkisindeki girdiden dize birleştirmeyle kuruluyor. Yukarıdaki temizleyici URL meta karakterlerini olduğu gibi bıraktığı için, bu datacenter bölümü, ortaya çıkan dizenin bir URL olarak nasıl ayrıştırılacağını değiştiren karakterler taşıyabilir — SSRF'nin klasik ön koşulu.

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

Mailchimp API anahtarı <gizli>-<datacenter> biçimindedir (örneğin ...-us5); eklenti ise datacenter bölümüne, doğrudan bir host adının içine yerleştirecek kadar güveniyor. Kod, o bölümün her zaman kısa bir alfanümerik bölge kodu olduğu ve nihai host'un her zaman .api.mailchimp.com ile biteceği varsayımıyla yazılmış.

Yukarı akıştaki temizleyici URL meta karakterlerini koruyunca iki varsayım da çöküyor. Datacenter bölümüne bir yol ayracı sızmasına izin verirseniz, URL'nin yetkili (authority) kısmı — istemcinin gerçekte bağlandığı host ve isteğe bağlı port — erkenden biter; kodun eklediği .api.mailchimp.com soneki artık host'a ait olmaz, URL yoluna indirgenir. Sunucu da anahtarı yazan kişinin işaret ettiği yere bağlanır; Mailchimp soneki ise yalnızca göstermelik bir yol metnine dönüşür.

İşleyiciye ulaşmak için Katkıda Bulunan erişiminden fazlası gerekmiyor. Bir Katkıda Bulunan, kendi taslağı üzerinde Elementor düzenleyicisini açabilir; eylemin beklediği düzenleyici nonce'u da tam burada verilir. Her iki kapı — geçerli bir nonce ve edit_posts yetkisi — sıradan, düşük yetkili bir yazarın zaten elinde olan şeyler. Yöneticiye de kurban etkileşimine de gerek yok. Üstüne, getirilen yanıtın bir kısmı Mailchimp liste verisi olarak geri ayrıştırıldığından, yanıtın bir bölümü çağırana yansıyabiliyor; bu da SSRF'yi tamamen kör değil, yarı kör kılıyor.

Birebir anahtar değerini, istek gövdesini ya da kopyala-yapıştır yapılabilecek bir komutu yayınlamıyoruz. Yukarıdaki mekanizma, sorunu anlamak ve ona karşı savunmak için yeterli; silaha dönüştürmek içinse değil.

5. Etki değerlendirmesi

Katkıda Bulunan düzeyindeki bir kullanıcı, sunucuyu kendi seçtiği dahili veya harici host ve portlara istek atmaya zorlayabilir. Pratikte bu şu anlama gelir:

  • Genel internetten güvenlik duvarıyla ayrılmış, yalnızca dahili servislere ulaşmak — yönetim arayüzleri, önbellekler, veritabanları.
  • Örnek kimlik bilgilerini ve yapılandırmayı ifşa edebilen bulut meta veri uç noktalarını (bağlantı-yerel meta veri servisleri) sorgulamak.
  • Dahili ağı güvenilir bir noktadan haritalamak ve port taraması yapmak.
  • Liste ayrıştırma yolundan yanıtın bir kısmını geri çekmek (yarı kör SSRF).

CVSS vektörü AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:L (≈6.5, Orta); ağ erişilebilirliğini, düşük saldırı karmaşıklığını, Katkıda Bulunan'ın düşük ama sıfır olmayan yetki gereksinimini, kullanıcı etkileşiminin yokluğunu ve gizlilik, bütünlük ve erişilebilirlik üzerindeki sınırlı ama gerçek etkiyi özetler. Puanı Yüksek'in altında, Orta'da tutan tek şey kimlik doğrulama koşulu — ki bu ince bir engel: birçok site Katkıda Bulunan kaydı kabul eder ya da bu tür hesapların sayıca bulunduğu çok yazarlı kurulumlar işletir.

6. Giderme

Anahtarı, URL meta karakterleri hayatta kalamayacak şekilde temizleyin ve ondan bir URL kurmadan önce datacenter bölümünü doğrulayın:

php
// Anahtarı "custom" dalının zaten yaptığı gibi ele al:$global_api = ! empty($_REQUEST['global_api']) ? sanitize_key($_REQUEST['global_api']) : '';
// Ve/veya URL'yi oluşturmadan önce datacenter bölümünü açıkça doğrula:$server = explode('-', $api_key);if (!isset($server[1]) || !preg_match('/^[a-z]+[0-9]+$/', $server[1])) {    return 0; // URL meta karakteri içeren herhangi bir datacenter'ı reddet}$url = 'https://' . $server[1] . '.api.mailchimp.com/3.0/lists';

Yamalı bir sürüm çıkana kadar site sahipleri için:

  • Satıcı bir yama yayınlar yayınlamaz güncelleyin ve eklenti değişiklik günlüğünü takip edin.
  • Hesap rollerini gözden geçirin. İhtiyacınız olmayan Katkıda Bulunan/yazar hesaplarını kaldırın, açık kaydı gerekmedikçe kapatın — zafiyete, kimlik doğrulamalı düşük yetkili bir oturum olmadan ulaşılamaz.
  • Eklentinin Mailchimp dinamik seçim özelliğini kullanmıyorsanız, eklentinin o sitede yerini hak edip etmediğini sorgulayın.

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

  • Çıkış (egress) filtreleme. SSRF'ye karşı en etkili tek önlem, web sunucusundan giden trafiği kısıtlamaktır. Web katmanının RFC 1918 aralıklarına, localhost'a ve özellikle bağlantı-yerel meta veri adresine ulaşmasını engelleyin; yalnızca sitenizin gerçekten kullandığı harici host'lara izin verin.
  • Bulut meta verisini sıkılaştırın. Bulut örneklerinde, tek bir kimlik doğrulamasız GET'in kimlik bilgisini alıp götürememesi için sıkılaştırılmış/oturum tabanlı meta veri modunu zorunlu kılın.
  • En az yetki. Her kullanıcıya işi gerçekten gören en düşük rolü verin ve edit_posts yetkisinin kimde olduğunu denetleyin.
  • Giden istekleri izleyin. WordPress sürecinden beklenmedik host'lara, dahili IP aralıklarına veya meta veri uç noktasına giden istekler için sunucu ve çıkış vekili günlüklerini izleyin.
  • Sanal yama / WAF. Zafiyetli AJAX eylemine URL meta karakterleri taşıyan bir API anahtarı alanıyla gelen istekleri reddeden bir kural, sanal yama olarak zaman kazandırır. Bu bir ara çözümdür, kod düzeltmesinin yerini tutmaz.
  • Eklentileri güncel tutun ve çalıştırdığınız bileşenler için zafiyet akışlarına abone olun.

8. Daha geniş ders

Tekrarlayan hata, temizlemeyi bağlama özgü tek bir adım yerine genel ve tek bir adım gibi görmek. sanitize_text_field(), bir sayfaya gidecek metin için doğrudur; bir URL'nin, dosya sistemi yolunun, kabuk komutunun ya da SQL tanımlayıcısının parçası olacak bir değer için yanlıştır. Güvenilir savunma, çıktı bağlamına duyarlı doğrulamadır: değerin ne için olduğuna karar verin, sonra o bağlamın izin verdiği dilbilgisini tam olarak zorunlu kılın — burada bir datacenter kodu için ^[a-z]+[0-9]+$ gibi bir izin listesi.

Daha genel olarak: kullanıcının etkisindeki bir girdi, sunucunun bağlanacağı bir hedefe birleştirildiği anda SSRF'yi olası sayın ve host bir izin listesine karşı doğrulanana, giden trafik kısıtlanana kadar öyle saymaya devam edin. URL'yi dize birleştirmeyle ayrıştırmak kırılgandır. Onu doğrulanmış bileşenlerden kurmak, bağlanmadan önce nihai host'u çözüp denetlemek ise sağlam duran yaklaşımdır.

9. Sorumlu açıklama

Bu sorunu eşgüdümlü açıklama kapsamında ele alıyoruz. Satıcı, kusuru doğrulayıp düzeltebilmesi için eksiksiz teknik ayrıntı ve yeniden üretim doğrudan kendisine verilerek, gizlice ve iyi niyetle bilgilendirildi. Standart uygulamaya uygun olarak, tam kavram kanıtı bir düzeltme çıkana ya da makul bir açıklama süresi dolana kadar bu kamuya açık metinden saklı tutuluyor. Yamalı sürüm yayınlandığında yazıyı güncelleyeceğiz.

Burada açıklanan tüm testler, Noroxi LLC tarafından, kamuya açık GPL eklentisine karşı, yalnızca localhost'a bağlı yalıtılmış bir laboratuvar ortamında gerçekleştirilmiştir. Hiçbir üçüncü taraf sisteme erişilmemiş ve eklenti sonrasında laboratuvardan kaldırılmıştır.

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ısı bir düzeltme yayınlanana kadar saklı tutulur.

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

Login LockDown 2.18: Yerleşik CAPTCHA Tekrar Oynatma Zafiyeti