Security fix PSF-2005-001 for SimpleXMLRPCServer.py.

This commit is contained in:
Guido van Rossum 2005-02-03 15:01:24 +00:00
parent 0676dfdce0
commit d064142579
3 changed files with 50 additions and 7 deletions

View File

@ -55,7 +55,8 @@ simple, stand alone XML-RPC servers.
period character. period character.
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}[SimpleXMLRPCServer]{register_instance}{instance} \begin{methoddesc}[SimpleXMLRPCServer]{register_instance}{instance\optional{,
allow_dotted_names}}
Register an object which is used to expose method names which have Register an object which is used to expose method names which have
not been registered using \method{register_function()}. If not been registered using \method{register_function()}. If
\var{instance} contains a \method{_dispatch()} method, it is called \var{instance} contains a \method{_dispatch()} method, it is called
@ -67,12 +68,26 @@ simple, stand alone XML-RPC servers.
The return value from \method{_dispatch()} is returned to the client as The return value from \method{_dispatch()} is returned to the client as
the result. If the result. If
\var{instance} does not have a \method{_dispatch()} method, it is \var{instance} does not have a \method{_dispatch()} method, it is
searched for an attribute matching the name of the requested method; searched for an attribute matching the name of the requested method.
If the optional \var{allow_dotted_names} argument is true and the
instance does not have a \method{_dispatch()} method, then
if the requested method name contains periods, each component of the if the requested method name contains periods, each component of the
method name is searched for individually, with the effect that a method name is searched for individually, with the effect that a
simple hierarchical search is performed. The value found from this simple hierarchical search is performed. The value found from this
search is then called with the parameters from the request, and the search is then called with the parameters from the request, and the
return value is passed back to the client. return value is passed back to the client.
\begin{notice}[warning]
Enabling the \var{allow_dotted_names} option allows intruders to access
your module's global variables and may allow intruders to execute
arbitrary code on your machine. Only use this option on a secure,
closed network.
\end{notice}
\versionchanged[\var{allow_dotted_names} was added to plug a security hole;
prior versions are insecure]{2.3.5, 2.4.1}
\end{methoddesc} \end{methoddesc}
\begin{methoddesc}{register_introspection_functions}{} \begin{methoddesc}{register_introspection_functions}{}

View File

@ -106,14 +106,22 @@ import BaseHTTPServer
import sys import sys
import os import os
def resolve_dotted_attribute(obj, attr): def resolve_dotted_attribute(obj, attr, allow_dotted_names=True):
"""resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d """resolve_dotted_attribute(a, 'b.c.d') => a.b.c.d
Resolves a dotted attribute name to an object. Raises Resolves a dotted attribute name to an object. Raises
an AttributeError if any attribute in the chain starts with a '_'. an AttributeError if any attribute in the chain starts with a '_'.
If the optional allow_dotted_names argument is false, dots are not
supported and this function operates similar to getattr(obj, attr).
""" """
for i in attr.split('.'): if allow_dotted_names:
attrs = attr.split('.')
else:
attrs = [attr]
for i in attrs:
if i.startswith('_'): if i.startswith('_'):
raise AttributeError( raise AttributeError(
'attempt to access private attribute "%s"' % i 'attempt to access private attribute "%s"' % i
@ -155,7 +163,7 @@ class SimpleXMLRPCDispatcher:
self.funcs = {} self.funcs = {}
self.instance = None self.instance = None
def register_instance(self, instance): def register_instance(self, instance, allow_dotted_names=False):
"""Registers an instance to respond to XML-RPC requests. """Registers an instance to respond to XML-RPC requests.
Only one instance can be installed at a time. Only one instance can be installed at a time.
@ -173,9 +181,23 @@ class SimpleXMLRPCDispatcher:
If a registered function matches a XML-RPC request, then it If a registered function matches a XML-RPC request, then it
will be called instead of the registered instance. will be called instead of the registered instance.
If the optional allow_dotted_names argument is true and the
instance does not have a _dispatch method, method names
containing dots are supported and resolved, as long as none of
the name segments start with an '_'.
*** SECURITY WARNING: ***
Enabling the allow_dotted_names options allows intruders
to access your module's global variables and may allow
intruders to execute arbitrary code on your machine. Only
use this option on a secure, closed network.
""" """
self.instance = instance self.instance = instance
self.allow_dotted_names = allow_dotted_names
def register_function(self, function, name = None): def register_function(self, function, name = None):
"""Registers a function to respond to XML-RPC requests. """Registers a function to respond to XML-RPC requests.
@ -294,7 +316,8 @@ class SimpleXMLRPCDispatcher:
try: try:
method = resolve_dotted_attribute( method = resolve_dotted_attribute(
self.instance, self.instance,
method_name method_name,
self.allow_dotted_names
) )
except AttributeError: except AttributeError:
pass pass
@ -373,7 +396,8 @@ class SimpleXMLRPCDispatcher:
try: try:
func = resolve_dotted_attribute( func = resolve_dotted_attribute(
self.instance, self.instance,
method method,
self.allow_dotted_names
) )
except AttributeError: except AttributeError:
pass pass

View File

@ -47,6 +47,10 @@ Extension Modules
Library Library
------- -------
- Applied a security fix to SimpleXMLRPCserver (PSF-2005-001). This
disables recursive traversal through instance attributes, which can
be exploited in various ways.
- Bug #1110478: Revert os.environ.update to do putenv again. - Bug #1110478: Revert os.environ.update to do putenv again.
- Bug #1103844: fix distutils.install.dump_dirs() with negated options. - Bug #1103844: fix distutils.install.dump_dirs() with negated options.