译者:天鸽
预估稿费:130RMB
投稿方式:发送邮件至linwei#360.cn,或登陆网页版在线投稿
简介
在今天的 Defencely Lab 中,我们将详细介绍和演示 Python 对象注入攻击(Python Object Injection)的细节。整个演示将使用我们专门编写的易受攻击的应用程序和漏洞,源码可以在这里找到 – Github – Python Object Injection。
需要的基础知识
了解基本的 OOP 概念
Python 类和对象简介
什么是类?
类是一个模板,你可以在其中存储变量和方法。
什么是对象?
对象可以是任何东西,一个类的实例,一个变量或者一个类中的函数。
让我们来看一个实际的例子:
在这里,你可以看到我们创建了一个名为 Test 的类实例,并将它分配给了一个名为 simpleapp 的变量,将变量 rony 的值传递给了该实例。
输出如下:
simpleapp = Test(rony)
当执行此代码时,python 会创建一个对象,然后将我们的值传递给第一个参数。每当 python 创建一个对象时,__init__ 函数就会被调用。__init__ 像 python 中的构造函数一样工作。
伴随着我们的输出,打印出了一个随机的数字,这是因为我们直接打印出了实例分配的变量,以显示 python 是如何对待一个对象的。
什么是对象注入?
对象注入是一种应用程序级的安全漏洞,它允许攻击者根据上下文执行严重的攻击。
Python 专门将某原生模块命名为“Pickle”,它在特定情况下容易受到对象注入攻击。
危险发生在当用户控制的数据被传递时,Python 已经在其官方文档中指出 pickle 是一个存在风险的模块。
我们可以将“Pickle”模块与 PHP 中的 serialize/unserialize() 原生函数进行比较,当存在用户输入时该 PHP 函数也容易受到对象注入攻击。
在 Python 中,与 PHP 不同的是,我们不需要一个魔术方法作为注入到对象的条件。
在 python 中进行序列化和反序列化仅仅是对数据的 Pickling 和 Unpickling。
除非用户输入的数据被传递到 Unpickling 的过程中,否则,Python 中数据的 Unpickling 并不一定是危险的。
下面是 Python 中 Pickled 和 Unpickled 的数据的样子:
检测对象注入攻击
要实现对象注入,你必须在应用程序上执行一个白盒 Pentest。因为每当你在复杂对象上 pickling 时,Python 中的序列化数据都会带有类名、变量和值。
Pickle 模块提供了四种简单和快速 pickling 和 unpickling 的方法。
dump()
dumps()
load()
loads()
您可以在 Python 官方文档中找到它们各自的功能。
正如我已经提到的,Unpickling 数据并不一定是危险的,但如果你是在后端处理,那么 pickling 和 unpickling 用户输入的数据就是危险的。永远不要相信用户的输入。
如果所提供的数据是由用户控制的,那么很明显会被篡改。
因此,如果你看到 pickled 的数据正在通过 HTTP 方法传输,则可能存在对象注入。
了解易受攻击应用程序的工作流
文件名:pickle.py
我们将研究上述代码,并据此实现一个对象注入。
忽略上面代码上写的所有内容,让我们集中精力在三件事情上。
在这里,arg 变量是用户的输入。
类 simpleApp 中的 final_workout() 方法将运行一个 python 文件。
app.secureaApp() 方法用于 unpickling 输入的数据。
现在,让我们更深入地了解这些方法正在扮演的角色。
simpleApp() 类中的 secureApp() 方法:
我假设你已经阅读了 Python 的官方文档,并且知道了这篇文章使用的所有方法的输入输出。
方法:
dump()
dumps()
load()
loads()
secureApp() 方法所做的是将文件名作为参数。使用 pickle 模块的 load() 方法 Unpickling 文件中的数据,并将 unpickled 的数据赋予变量 workDone。之后该变量会作为 final_workout() 方法的参数。
我们看看 final_workout() 方法的内容。
simpleApp() 类中的 final_workout() 方法:
该方法创建一个名为 code.py 的 python 文件,将 unpickled 的数据写入文件并运行它。
我们来看看,当使用已经生成的序列化数据来运行易受攻击的应用程序 pickle.py 时,会发生什么。
正如我们看到的,它打印出了序列化数据的内容,并成功运行,打印出字符串。
下面我们将学习怎样构造自己的序列化数据,以在相同的应用程序上成功地进行对象注入。
编写漏洞利用
现在我们知道 pickle.py 正在使用序列化的数据,因此,我们将使用 dumps() 方法 pickle 我们构造的 payload。
文件名:exploit_pickle.py
我们将序列化一条包含了编码后系统命令的代码, 并在它工作时对其进行测试。
现在我们就成功地注入了自己精心构造的代码。
发表评论
您还未登录,请先登录。
登录