Commit 622f1441 authored by Andrew M. Kuchling's avatar Andrew M. Kuchling

[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.
parent bc09e108
......@@ -111,6 +111,15 @@ simple, stand alone XML-RPC servers.
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}
......
......@@ -227,6 +227,10 @@ class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
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)
......
......@@ -423,6 +423,17 @@ class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
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 @@ class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
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 @@ class SimpleXMLRPCRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
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."""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment