在python SimpleXMLRPC Server的python文档中,提到了:
警告启用allow_dotted_names选项允许入侵者访问模块的全局变量,并允许入侵者在您的计算机上执行任意代码。仅在安全,封闭的网络上使用此选项。
现在我有一个服务器使用以下代码:
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()
请解释如何利用漏洞将任意代码注入服务器?如果上面的代码不容易受到攻击,那么举一个可以被利用的例子和客户端代码这样做。
答案 0 :(得分:0)
MyFuncs().mul
不仅仅是一个可调用函数,它(就像所有Python函数一样)是一个具有自己属性的第一类对象。
除了加载__xxx__
魔术方法(由于SimpleXMLRPCServer阻止访问以_
开头的任何内容而无法访问),还有内部方法成员im_class
(指向类对象),im_self
(指向MyFuncs()
实例)和im_func
(指向mul
的函数定义)。该函数对象本身具有许多可访问的属性 - 最值得注意的是包括func_globals
,它们可以访问包含文件的变量范围字典。
因此,通过调用mul.im_func.func_globals.get
,攻击者将能够读取您在脚本中设置的任意全局变量,或者使用字典上的update()
来更改它们。在上面的示例中,由于全局变量中没有任何敏感内容,因此无法利用。但是,这可能不是你想要依赖的事情。
完全“执行任意代码”的可能性很小,但您可能会想象一个可写的全局codeToExecute
变量,例如稍后会eval
编辑,或者某人使用{{1}注册整个模块},允许导入的所有模块都可访问(典型示例:register_instance
和os
)。
在Python 3中,此特定攻击不再可访问,因为函数/方法内部属性已重命名为双下划线版本,并且会被阻止。但总的来说,“默认打开”似乎是一个坏主意,只允许基于名称允许外部访问实例上的任何属性 - 不能保证将来不会存在其他非下划线名称,或者属性不会被添加到可以以某种方式利用的那些属性的可访问内置类型(元组,字典)中。
如果您确实需要嵌套属性访问,那么想出一个需要os.system
装饰之类的SimpleXMLRPCServer版本来定义应该可见的内容似乎更安全。