zycoder0day/CVE-2026-5076
GitHub: zycoder0day/CVE-2026-5076
该项目是 CVE-2026-5076 的 PoC,通过串联 ARMember 插件中的密码重置密钥明文存储漏洞和 SQL 注入漏洞,实现未认证条件下的完整管理员账户接管。
Stars: 0 | Forks: 0
# ☠️ CVE-2026-5076
### ARMember Premium <= 7.3.1
### Insecure Password Reset Mechanism → Full Admin Account Takeover





**Plaintext Password Reset Keys Stored in Database + SQL Injection = Complete Admin Takeover**
## 📋 Informasi Kerentanan
| Item | Detail |
|---|---|
| **CVE ID** | CVE-2026-5076 |
| **Plugin** | ARMember – Membership Plugin & Content Restriction |
| **Versi Terpengaruh** | Premium <= 7.3.1 |
| **Versi Patched** | 7.3.2 |
| **CVSS Score** | 9.8 Critical |
| **CWE** | CWE-640: Weak Password Recovery |
| **Tipe** | Insecure Password Reset Mechanism → Plaintext Key Storage |
| **Vektor Serangan** | Network / Remote / Unauthenticated (via SQLi chain) |
| **Instalasi Aktif** | 30,000+ (Premium) |
| **Penemu** | Wordfence Threat Intelligence |
| **Tanggal Publikasi** | 3 Juni 2026 |
### CVE Terkait (Same Advisory)
| CVE | Tipe | Severity |
|---|---|---|
| **CVE-2026-5076** | Insecure Password Reset — Plaintext Key Storage | 9.8 Critical |
| **CVE-2026-5073** | Unauthenticated SQL Injection (ORDER BY) | 9.8 Critical |
| **CVE-2026-5074** | Unauthenticated SQL Injection (WHERE) | 9.8 Critical |
## 🎯 Ringkasan
Tiga kerentanan kritis pada plugin WordPress **ARMember Premium <= 7.3.1** yang jika dirantai bersama memungkinkan **pengambilalihan akun administrator secara penuh tanpa autentikasi**:
1. **CVE-2026-5076** — Password reset key disimpan dalam **plaintext** di `wp_usermeta` (`arm_reset_password_key`), bukan di-hash seperti standar WordPress
2. **CVE-2026-5073** — SQL Injection pada parameter `order` di AJAX handler `arm_directory_paging_action()`
3. **CVE-2026-5074** — SQL Injection pada parameter `filter` di AJAX handler `arm_directory_paging_action()`
**Konsekuensi langsung CVE-2026-5076**: Siapapun dengan akses baca ke database (via SQLi, backup exposure, dll) dapat membaca password reset key dalam bentuk plaintext dan langsung menggunakannya untuk mereset password akun manapun — tanpa perlu cracking.
## 🔬 Analisis Teknis
### Root Cause #1: Plaintext Key Storage (CVE-2026-5076)
WordPress standar menyimpan password reset key di kolom `user_activation_key` dalam bentuk **hashed** menggunakan `wp_hash()`. ARMember menyimpan salinan key yang sama di `wp_usermeta` dengan meta_key `arm_reset_password_key` — namun dalam bentuk **PLAINTEXT**:
// FILE: armember-membership/core/class.arm_member_forms.php
// Fungsi: arm_lost_password_action()
// WordPress menyimpan HASHED key (aman)
$key = wp_generate_password(20, false);
$wp_key = $wpdb->get_var(
$wpdb->prepare("SELECT user_activation_key FROM $wpdb->users
WHERE user_login=%s", $user_login)
);
// ARMember menyimpan PLAINTEXT key (VULNERABLE!)
update_user_meta($user_id, 'arm_reset_password_key', $wp_key);
// ^^^^^^
// Ini adalah key ASLI yang bisa langsung dipakai
**Masalah kritis**: `$wp_key` di sini adalah key yang dihasilkan oleh `wp_generate_password(20, false)` — 20 karakter alfanumerik. WordPress meng-hash key ini sebelum menyimpan di `user_activation_key`, tapi ARMember menyimpannya **sebelum hashing** atau menyimpan salinan terpisah yang **tidak di-hash**.
### Root Cause #2: Key Persistence Bug
Ketika `get_password_reset_key()` dipanggil (WordPress core), key baru di-generate dan di-hash. Namun fungsi ini **TIDAK mengupdate** `arm_reset_password_key`:
// WordPress core: get_password_reset_key($user)
// - Generate key baru
// - Hash key → simpan di user_activation_key
// - Return key plaintext
// - TAPI: arm_reset_password_key TIDAK diupdate!
Akibatnya, **key plaintext lama tetap tersimpan selamanya** di `arm_reset_password_key` bahkan setelah user melakukan password reset. Key ini bisa digunakan berulang kali sampai meta key secara eksplisit dihapus.
### Root Cause #3: SQL Injection (CVE-2026-5073/5074)
AJAX handler `arm_directory_paging_action()` memiliki nonce check via `arm_check_user_cap()`, tapi parameter `order` dan `filter` langsung masuk ke SQL query tanpa sanitasi:
// FILE: armember-membership/core/class.arm_member_forms.php
// Fungsi: arm_directory_paging_action()
// Nonce check (dibutuhkan nonce valid)
$nonce_check = $this->arm_check_user_cap();
// ORDER BY injection — langsung ke SQL tanpa sanitasi!
$orderby = "u.{$arm_member} {$order_dir}";
// $order_dir dari $_POST['order'] → LANGSUNG ke ORDER BY
// WHERE injection via filter
if (!empty($filter)) {
$where .= " AND " . $filter; // ← LANGSUNG concatenation!
}
**Eksploitasi ORDER BY**: Parameter `order` dimasukkan ke klausa `ORDER BY` SQL. Karena tidak ada sanitasi, attacker bisa inject subquery:
-- Payload SQLi via parameter order
ORDER BY u.ID ASC, IF(COND, 1, EXP(710))
-- COND = TRUE → IF returns 1 → ORDER BY 1 → response normal (besar)
-- COND = FALSE → IF returns EXP(710) → MySQL overflow ERROR → response 90B
**Oracle ini immune terhadap network latency** karena membedakan TRUE/FALSE berdasarkan error vs success, bukan waktu respons.
## ⛓️ Attack Chain Roadmap
╔══════════════════════════════════════════════════════════════════════════════════╗
║ CVE-2026-5076 FULL CHAIN ATTACK ROADMAP ║
║ ARMember Premium <= 7.3.1 → Unauthenticated Admin Takeover ║
╚══════════════════════════════════════════════════════════════════════════════════╝
┌─────────────────────────────────────────────────────────────────────────────────┐
│ PHASE 1: RECONNAISSANCE │
│ "Identifikasi target, versi, dan attack surface" │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1a. Deteksi ARMember │
│ ├─ GET / → cari string: "arm_", "armember", "ARMember" │
│ ├─ GET /wp-json/ → cari armember di response │
│ ├─ Cookie: arm_* indicates ARMember active │
│ └─ Version fingerprint: arm_css_version, arm_js_version │
│ │
│ 1b. Temukan Directory Page (MUST have arm_directory_form_container) │
│ ├─ Method 1: WP Search → GET /?s=members → parse links │
│ │ └─ Filter: skip /feed/, /rss2/, .xml, /atom/ │
│ ├─ Method 2: Direct Path Probe → /directory/, /members/, /community/ │
│ ├─ Method 3: Sitemap → /sitemap.xml → parse URLs │
│ └─ Method 4: REST API → /wp-json/wp/v2/pages → search ARM shortcode │
│ │
│ 1c. Ekstrak nonce + template_id (BERPASANGAN di form yang sama) │
│ ├─ 标签:ARMember Premium, CISA项目, CVE-2026-5076, CVSS 9.8, CWE-640, PoC, Web安全, WordPress安全, WordPress插件漏洞, 不安全密码重置, 操作系统监控, 文件完整性监控, 明文密码存储, 暴力破解, 未授权访问, 概念验证, 漏洞利用链, 管理员账户接管, 编程工具, 蓝队分析, 身份验证绕过, 远程代码执行