[Python-checkins] r46578 - in python/trunk: Doc/lib/libsimplexmlrpc.tex Lib/DocXMLRPCServer.py Lib/SimpleXMLRPCServer.py

andrew.kuchling python-checkins at python.org
Wed May 31 16:08:49 CEST 2006


Author: andrew.kuchling
Date: Wed May 31 16:08:48 2006
New Revision: 46578

Modified:
   python/trunk/Doc/lib/libsimplexmlrpc.tex
   python/trunk/Lib/DocXMLRPCServer.py
   python/trunk/Lib/SimpleXMLRPCServer.py
Log:
[Bug #1473048] 
SimpleXMLRPCServer and DocXMLRPCServer don't look at
the path of the HTTP request at all; you can POST or
GET from / or /RPC2 or /blahblahblah with the same results.
Security scanners that look for /cgi-bin/phf will therefore report
lots of vulnerabilities.

Fix: add a .rpc_paths attribute to the SimpleXMLRPCServer class, 
and report a 404 error if the path isn't on the allowed list.

Possibly-controversial aspect of this change: the default makes only
'/' and '/RPC2' legal.  Maybe this will break people's applications
(though I doubt it).  We could just set the default to an empty tuple,
which would exactly match the current behaviour.


Modified: python/trunk/Doc/lib/libsimplexmlrpc.tex
==============================================================================
--- python/trunk/Doc/lib/libsimplexmlrpc.tex	(original)
+++ python/trunk/Doc/lib/libsimplexmlrpc.tex	Wed May 31 16:08:48 2006
@@ -111,6 +111,15 @@
   Registers the XML-RPC multicall function system.multicall.
 \end{methoddesc}
 
+\begin{memberdesc}[SimpleXMLRPCServer]{rpc_paths}
+An attribute value that must be a tuple listing valid path portions of
+the URL for receiving XML-RPC requests.  Requests posted to other
+paths will result in a 404 ``no such page'' HTTP error.  If this
+tuple is empty, all paths will be considered valid.
+The default value is \code{('/', '/RPC2')}.
+  \versionadded{2.5}
+\end{memberdesc}
+
 Example:
 
 \begin{verbatim}

Modified: python/trunk/Lib/DocXMLRPCServer.py
==============================================================================
--- python/trunk/Lib/DocXMLRPCServer.py	(original)
+++ python/trunk/Lib/DocXMLRPCServer.py	Wed May 31 16:08:48 2006
@@ -227,6 +227,10 @@
         Interpret all HTTP GET requests as requests for server
         documentation.
         """
+        # Check that the path is legal
+        if not self.is_rpc_path_valid():
+            self.report_404()
+            return
 
         response = self.server.generate_html_documentation()
         self.send_response(200)

Modified: python/trunk/Lib/SimpleXMLRPCServer.py
==============================================================================
--- python/trunk/Lib/SimpleXMLRPCServer.py	(original)
+++ python/trunk/Lib/SimpleXMLRPCServer.py	Wed May 31 16:08:48 2006
@@ -423,6 +423,17 @@
     XML-RPC requests.
     """
 
+    # Class attribute listing the accessible path components;
+    # paths not on this list will result in a 404 error.
+    rpc_paths = ('/', '/RPC2')
+
+    def is_rpc_path_valid(self):
+        if self.rpc_paths:
+            return self.path in self.rpc_paths
+        else:
+            # If .rpc_paths is empty, just assume all paths are legal
+            return True
+
     def do_POST(self):
         """Handles the HTTP POST request.
 
@@ -430,6 +441,11 @@
         which are forwarded to the server's _dispatch method for handling.
         """
 
+        # Check that the path is legal
+        if not self.is_rpc_path_valid():
+            self.report_404()
+            return
+            
         try:
             # Get arguments by reading body of request.
             # We read this in chunks to avoid straining
@@ -468,6 +484,18 @@
             self.wfile.flush()
             self.connection.shutdown(1)
 
+    def report_404 (self):
+            # Report a 404 error
+            self.send_response(404)
+            response = 'No such page'
+            self.send_header("Content-type", "text/plain")
+            self.send_header("Content-length", str(len(response)))
+            self.end_headers()
+            self.wfile.write(response)
+            # shut down the connection
+            self.wfile.flush()
+            self.connection.shutdown(1)
+
     def log_request(self, code='-', size='-'):
         """Selectively log an accepted request."""
 


More information about the Python-checkins mailing list