|
Vulnerability vBulletin Affected vBulletin Description Jouko Pynnonen found following. vBulletin is a commonly used web forum system written in PHP. One of its key features is use of templates, which allow the board administrator to dynamically modify the look of the board. vBulletin templates are parsed with the eval() function. This could be somewhat safe as long as the parameters to eval() are under strict control. Unfortunately this is where vBulletin fails. With an URL crafted in a certain way, a remote user may control the eval() parameters and inject arbitrary PHP code to be executed. A remote user may thus execute any PHP code and programs as the web server user, typically "nobody", start an interactive shell and try to elevate their privilege. The configuration files are accessible for the web server so the user can in any case access the MySQL database containing the forums and user information. According to the authors the vulnerability exist in all versions of vBulletin up to 1.1.5 and 2.0 beta 2. The bug does not involve buffer overrun or other platform-dependant issues, so it's presumably exploitable under any OS or platform. vBulletin templates are implemented in the following way: the gettemplate() function in global.php is used to fetch a template from database. The code is then passed to eval(). If we take index.php for an example, there's this code: if ($action=="faq") { eval("echo dovars(\"".gettemplate("faq")."\");"); } The dovars() function does some variable replacing, such as replace <largefont> with <font size="10">. The gettemplate() function is defined in global.php: function gettemplate($templatename,$escape=1) { // gets a template from the db or from the local cache global $templatecache,$DB_site; if ($templatecache[$templatename]!="") { $template=$templatecache[$templatename]; } else { $gettemp=$DB_site->query_first("SELECT template FROM template WHERE title='". addslashes($templatename)."'"); $template=$gettemp[template]; $templatecache[$templatename]=$template; } if ($escape==1) { $template=str_replace("\"","\\\"",$template); } return $template; } For effectiveness the function implements a simple cache for template strings. After fetching them from the database they're stored in the templatecache[] array. This array is checked for the template before doing the SQL query. Unfortunately the array is never initialized, so a user can pass array contents in the URL, e.g. (for simplicity not %-escaped) http://www.site.url/index.php?action=faq&templatecache[faq]=hello+world With this URL, you won't get the FAQ page, but just a blank page with the words "hello world". The eval() call above will execute echo dovars("hello world"); As if this wouldn't be bad enough, a remote user may as well pass a value containing quotation marks and other symbols. Quotation marks aren't always escaped as seen in the code above, in which case index.php could end up executing code like echo dovars("hello"world"); This would produce a PHP error message due to unbalanced quotes. It doesn't take a rocket scientist to figure out how a remote user could execute arbitrary code from here, so further details about exploitation aren't necessary. If your vBulletin board produces an error message with an URL like the one above prefixed with a single quotation mark, it's definitely vulnerable. The above example works with the "Lite" version. The commercial versions are vulnerable too, but details may differ. After a little experimenting on the Jelsoft's test site we found some of the commercial versions also have an eval() problem with URL redirecting, e.g. http://www.site.url/member.php?action=login&username=myuser&password=mypass&url=hello"world and a similar one in the Lite version: http://www.site.url/search.php?action=simplesearch&query=searchthis&templatecache[standardredirect]=hello"world Solution The vendor (Jelsoft Enterprises Ltd) was contacted March 2nd, and has released fixed commercial versions 1.1.6 and 2.0 beta 3. The vendor hasn't fixed the free "Lite" version of the software so far and hasn't replied query concerning it, so here is a quick fix $templatecache=array(); Add that line to the beginning of global.php after the "<?php" line. It will initialize the template cache and override any values a remote user may have tried to pass in the URL. Fix for the redirect problem: replace global.php line 99 $url=$redirectloc; with this line: $url=addslashes($redirectloc);