If a client calls an RPC method but supplies a parameter count that
does not match any of the method's signatures as defined in the
dispatch map, the function verifySignature()
of XML_RPC_Server
will
cause PHP undefined variable notices if PHP notices have not been
disabled.
This is a security issue because it exposes the script path to the client. Also, having the server's XML response prepended with PHP notices will cause many clients to reject the return payload as invalid during parsing.
To demonstrate this bug, we can use slightly modified versions of the server and client examples from the end-user documentation.
This bug exists in the class XML_RPC_Server
, and the class XML_RPC_Client
can be used to demonstrate it.
First, create a create a simple XML-RPC server script with XML_RPC_Server
and place it on the test webserver:
<?php require_once('XML/RPC/Server.php'); $server = new XML_RPC_Server(array(), 1, 1); ?>
We will use XML_RPC_Server
's built-in system.methodSignature()
RPC method to demonstrate the bug, so no
dispatch map or test functions need to be created.
XML_RPC_Server
occurs when an RPC method is called
with a bad parameter count, i.e. too few or too many parameters than are defined by the signature(s) of the method in the server's dispatch map.
The method system.methodSignature()
takes only one parameter, an XML-RPC string.
To demonstrate the bug, we will use a modified version of the end-user documentation's client script, and we'll incorrectly call
system.methodSignature()
with an extra parameter (two instead of one). In practice, it's quite easy to call a method with incorrect
or extra parameters, especially when working with a new API or typing quickly on languages with an interactive mode.
<?php require_once('XML/RPC.php'); $p = new XML_RPC_Value('system.methodSignature', 'string'); $params = array($p, $p); /** * Call system.methodSignature() with a bad parameter count. This method takes only one * parameter, and supplying an extra bogus parameter will demonstrate the bug in the server. */ $msg = new XML_RPC_Message('system.methodSignature', $params); $cli = new XML_RPC_Client('/demo-server.php', 'localhost'); $cli->setDebug(1); $resp = $cli->send($msg); if (!$resp) { die('Communication error: ' . $cli->errstr); } if ($resp->faultCode()) { echo('Fault Code: ' . $resp->faultCode() . "\n"); echo('Fault Reason: ' . $resp->faultString() . "\n"); } ?>
faultCode
and faultString
. The latter behavior is preferred, since the client should be alerted that it is calling the
method incorrectly.
The client should have shown a faultCode 3
returned by the server:
Content-type: text/html X-Powered-By: PHP/5.0.3 <PRE>---GOT--- HTTP/1.1 200 OK Date: Thu, 05 May 2005 03:17:30 GMT Server: Apache (Unix) Content-Length: 565 Connection: close Content-Type: text/xml; charset=UTF-8 <?xml version="1.0" encoding="UTF-8"?> <!-- PEAR XML_RPC SERVER DEBUG INFO: 0 - new XML_RPC_Value("system.methodSignature", 'string') 1 - new XML_RPC_Value("system.methodSignature", 'string') --> <methodResponse> <fault> <value> <struct> <member> <name>faultCode</name> <value><int>3</int></value> </member> <member> <name>faultString</name> <value><string>Incorrect parameters passed to method: Bad parameter count</string></value> </member> </struct> </value> </fault> </methodResponse> ---END--- </PRE>Fault Code: 3 Fault Reason: Incorrect parameters passed to method: Bad parameter count
The actual result of running the example code above is that faultCode 3
is indeed produced, however the verifySignature()
function in XML_RPC_Server
can also cause PHP undefined variable notices if they have not been turned off. The line number
shown in the notices will vary depending on the version of the XML_RPC
package used, however the bug is present in all versions up to and
including 1.3.0RC1.
Content-type: text/html X-Powered-By: PHP/5.0.3 <PRE>---GOT--- HTTP/1.1 200 OK Date: Thu, 05 May 2005 03:43:08 GMT Server: Apache (Unix) Content-Length: 963 Connection: close Content-Type: text/xml; charset=UTF-8 <br /> <b>Notice</b>: Undefined variable: wanted in <b>/your/path/here/PEAR/XML/RPC/Server.php</b> on line <b>354</b><br /> <br /> <b>Notice</b>: Undefined variable: got in <b>/your/path/here/PEAR/XML/RPC/Server.php</b> on line <b>354</b><br /> <br /> <b>Notice</b>: Undefined variable: pno in <b>/your/path/here/XML/RPC/Server.php</b> on line <b>354</b><br /> <?xml version="1.0" encoding="UTF-8"?> <!-- PEAR XML_RPC SERVER DEBUG INFO: 0 - new XML_RPC_Value("system.methodSignature", 'string') 1 - new XML_RPC_Value("system.methodSignature", 'string') --> <methodResponse> <fault> <value> <struct> <member> <name>faultCode</name> <value><int>3</int></value> </member> <member> <name>faultString</name> <value><string>Incorrect parameters passed to method: Wanted , got at param )</string></value> </member> </struct> </value> </fault> </methodResponse> ---END--- </PRE>Fault Code: 2 Fault Reason: Invalid return payload: enable debugging to examine incoming payload
The return payload from the server shows that faultCode 3
was produced, however the XML was prepended by the PHP notices. Most
XML-RPC clients will reject the payload as invalid when they encounter the notices during XML parsing. This is true of XML_RPC
's client
XML_RPC_Client
, which reports its own faultCode 2
as shown above.
verifySignature()
of XML_RPC_Server
. The function could be rewritten to detect
these cases, however the least invasive way to fix the bug is to replace the last line of verifySignature()
:
return array(0, "Wanted ${wanted}, got ${got} at param ${pno})");
with this simple check:
if (isset($pno)) { return array(0, "Wanted ${wanted}, got ${got} at param ${pno})"); } else { return array(0, 'Bad parameter count'); }
Last page update: 4 May 2005.