3

In the python docs of python SimpleXMLRPC Server, it is mentioned:

Warning Enabling the 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.

Now I have a Server With the following code:

from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.server import SimpleXMLRPCRequestHandler


server = SimpleXMLRPCServer(("localhost", 8000),
                            requestHandler=RequestHandler)
server.register_introspection_functions()

server.register_function(pow)

def adder_function(x,y):
    return x + y
server.register_function(adder_function, 'add')

class MyFuncs:
    def mul(self, x, y):
        return x * y

server.register_instance(MyFuncs(), allow_dotted_names=True)

server.serve_forever()

Please explain how the vulnerability can be exploited to inject arbitrary code onto the server? If my above code is not vulnerable, then give example of one which can be exploited and the client code to do so.

Nehal J Wani
  • 16,071
  • 3
  • 64
  • 89

1 Answers1

0

MyFuncs().mul is not just a callable function, it is (like all Python functions) a first-class object with its own properties.

Apart from a load of __xxx__ magic methods (which you can't access because SimpleXMLRPCServer blocks access to anything beginning with _), there are internal method members im_class (pointing to the class object), im_self (pointing to the MyFuncs() instance) and im_func (pointing to the function definition for mul). That function object itself has a number of accessible properties - most notably including func_globals which give access to the variable scope dictionary for the containing file.

So, by calling mul.im_func.func_globals.get an attacker would be able to read arbitrary global variables you had set in your script, or use update() on the dictionary to alter them. In the above example that's not exploitable because you have nothing sensitive in the global variables. But that's probably not something you want to rely on always staying true.

Full 'execute arbitrary code' is pretty unlikely, but you might imagine a writable global codeToExecute variable that gets evaled later, for example, or someone registering a whole module with register_instance, allowing all the modules it imported to be accessible (typical example: os and os.system).

In Python 3 this particular attack is no longer reachable because the function/method internal properties were renamed to double-underline versions, where they get blocked. But in general it seems like a bad idea to 'default open' and allow external access to any property on an instance just based on name - there is no guarantee that no other non-underline names will ever exist in the future, or that properties won't be added to the accessible built-in types (tuple, dict) of those properties that could be exploited in some way.

If you really need nested property access, it would seem safer to come up with a version of SimpleXMLRPCServer that requires something like a @rpc_accessible decoration to define what should be visible.

bobince
  • 528,062
  • 107
  • 651
  • 834