手把手教你用Vulhub复现 superset CVE-2023-27524漏洞(附完整POC)

4 阅读5分钟

创作声明

AI创作声明

本文由AI辅助创作,经作者人工审核与修订。内容旨在技术交流与学习,如有疏漏或错误,欢迎指正。

免责声明

本文内容仅供学习与研究用途,不保证完全准确或适用于所有环境。读者依据本文操作所产生的一切后果,作者及平台不承担任何法律责任。请遵守法律法规,勿将技术用于非法目的。

版权声明

本文为原创内容,版权归作者所有。未经授权,禁止商业用途转载。非商业转载请注明出处并保留本声明。

准备工作

Docker的常用命令

docker compose pull #将远程镜像拉取到本地

docker compose up -d #启动容器,并且不包含下载日志

docker ps            #查看开放端口

docker compose logs  #查看日志

docker compose down  #销毁容器

docker compose build #重启容器

docker compose exec web bash  #进入名为web的服务容器并打开 Bash 终端的命令

漏洞原理分析

CVE-2023-27524 是一个 默认配置导致的身份验证绕过(Session Validation)漏洞,存在于 Apache Superset ≤ 2.0.1 中。该漏洞主要是由于使用了 不安全的默认 SECRET_KEY,攻击者利用这一默认密钥可以伪造有效的 session cookie,从而绕过认证、访问未授权资源甚至可能远程执行代码

关键本质

  • Apache Superset 使用 SECRET_KEY签名 session cookies加密敏感数据
  • 默认生成的 SECRET_KEY 在代码中是静态的或极弱的,且很多安装未修改默认值。
  • 攻击者知道或猜出该 SECRET_KEY 时,可以伪造合法管理员 session,从而远程登录并控制系统。 攻击场景总体流程图

DFD 数据流图 DFD Level 0(系统上下文图)

        ┌────────────┐
        │  Attacker  │
        └─────┬──────┘
              │ HTTP Request
              │ (Forged Session)
              ▼
┌──────────────────────────┐
│  Apache Superset Server  │
│                          │
│  ┌────────────────────┐ │
│  │ Auth / Session     │ │
│  │ Validation Module  │ │
│  └────────────────────┘ │
│            │              │
│            ▼              │
│  ┌────────────────────┐ │
│  │ Application Logic  │ │
│  └────────────────────┘ │
└────────────┬─────────────┘
             │
             ▼
       ┌──────────┐
       │ Database │
       └──────────┘


DFD Level 1(漏洞相关细化)

[External Entity]
 Attacker
    |
    | Forged Session Cookie
    v
[Process P1]
 Session Verification
 (uses SECRET_KEY)
    |
    | Valid Session (mistaken)
    v
[Process P2]
 Authorization Check
 (skipped / bypassed)
    |
    v
[Process P3]
 Sensitive API / Admin Ops
    |
    v
[Data Store]
 Superset Metadata DB


STRIDE 威胁建模分析

STRIDE 类别是否存在在本漏洞中的体现
S – Spoofing✅ 是攻击者伪造合法用户 session
T – Tampering⚠️ 间接可通过 API 修改系统配置
R – Repudiation⚠️ 是日志显示为“合法用户操作”
I – Information Disclosure✅ 是未授权访问仪表盘、数据源
D – Denial of Service❌ 否非主要攻击目标
E – Elevation of Privilege✅ 是未登录 → 管理员权限

基于 STRIDE 威胁模型分析,CVE-2023-27524 主要涉及身份伪造(Spoofing)和权限提升(Elevation of Privilege)威胁。攻击者通过伪造会话标识绕过认证机制,使系统错误地将未授权请求识别为合法用户操作,从而导致权限边界被破坏。

漏洞复现原理图示说明

下面是该漏洞的简化流程图示:

1)正常认证流程

Client              Superset Server
  │                     │
  │  Login (user+pass)  │
  │ ──────────────────> │
  │                     │
  │ Session cookie      │
  │ signed with         │
  │ SECRET_KEY          │
  │ <─────────────────  │
  │                     │
  │ Authenticated       │
  │ request with cookie │
  │ ──────────────────> │
  │ Process request

2)有默认 SECRET_KEY 时漏洞利用流程

Attacker
  │
  │ Knows default SECRET_KEY
  │ 
  │ Generate fake cookie
  │ with known KEY
  │
  ▼
Superset Server
  │
  │ Accepts forged session
  │ (believes user authenticated)
  │
  ▼
Unauthenticated access
to admin/dashboard
executes arbitrary actions


简述:由于默认 SECRET_KEY 被公开或可推测,攻击者无需凭据即可制造有效 session 并绕过所有访问控制。

漏洞复现

用官方大佬的EXP。

Snipaste_2026-01-09_16-42-13.png 将得到的硬编码发送到burpsuite修改,修改session的值,得到响应数据包。该session由于使用固定密钥,给了攻击者可乘之机。

Snipaste_2026-01-09_16-42-53.png


HTTP/1.1 200 OK
Server: gunicorn
Date: Fri, 09 Jan 2026 08:39:24 GMT
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Content-Length: 1479
Vary: Accept-Encoding, Cookie
Set-Cookie: session=eyJfZnJlc2giOmZhbHNlLCJfdXNlcl9pZCI6MSwibG9jYWxlIjoiZW4iLCJ1c2VyX2lkIjoxfQ.aWC-vA.rtOXvorlRtpZnhQUQIiGTa00BbY; HttpOnly; Path=/; SameSite=Lax

{"count":0,"description_columns":{},"ids":[],"label_columns":{"allow_ctas":"Allow Ctas","allow_cvas":"Allow Cvas","allow_dml":"Allow Dml","allow_file_upload":"Allow File Upload","allow_multi_schema_metadata_fetch":"Allow Multi Schema Metadata Fetch","allow_run_async":"Allow Run Async","allows_cost_estimate":"Allows Cost Estimate","allows_subquery":"Allows Subquery","allows_virtual_table_explore":"Allows Virtual Table Explore","backend":"Backend","changed_on":"Changed On","changed_on_delta_humanized":"Changed On Delta Humanized","created_by.first_name":"Created By First Name","created_by.last_name":"Created By Last Name","database_name":"Database Name","disable_data_preview":"Disable Data Preview","explore_database_id":"Explore Database Id","expose_in_sqllab":"Expose In Sqllab","extra":"Extra","force_ctas_schema":"Force Ctas Schema","id":"Id"},"list_columns":["allow_file_upload","allow_ctas","allow_cvas","allow_dml","allow_multi_schema_metadata_fetch","allow_run_async","allows_cost_estimate","allows_subquery","allows_virtual_table_explore","backend","changed_on","changed_on_delta_humanized","created_by.first_name","created_by.last_name","database_name","explore_database_id","expose_in_sqllab","extra","force_ctas_schema","id","disable_data_preview"],"list_title":"List Database","order_columns":["allow_file_upload","allow_dml","allow_run_async","changed_on","changed_on_delta_humanized","created_by.first_name","database_name","expose_in_sqllab"],"result":[]}

疑问:我在api/v1/database相关端口找到test_connection,除了这个方法外。安全研究员是怎么发现这个接口的,我用dirsearch和dirb、ffuf都扫不出这个目录。

Snipaste_2026-01-09_17-03-22.png

修复建议

修复措施

  1. 官方根本修复(强烈推荐) 升级到 Apache Superset ≥ 2.1.0 或更高版本 —— 官方补丁会:
  • 禁止使用默认 SECRET_KEY 启动服务
  • 强制用户 配置独特、安全的随机 SECRET_KEY
  • 如果未配置则服务无法启动或拒绝运行
  1. 临时缓解措施(无法升级时)

更改 SECRET_KEY 配置,在 superset_config.py 中写入:

import secrets

SECRET_KEY = "<YOUR_SECURE_RANDOM_KEY>"

或通过环境变量:

export SUPERSET_SECRET_KEY=$(python - << 'EOF'
import secrets
print(secrets.token_urlsafe(48))
EOF
)


确保 SECRET_KEY 是高熵随机字符串,不使用默认值。

伪代码级修复示例

下面是一个简化伪代码,演示如何 在初始化时拒绝默认 SECRET_KEY

❌ 旧版初始化 (不安全默认)

# insecure: default SECRET_KEY included
SECRET_KEY = os.environ.get("SUPERSET_SECRET_KEY", "CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET")


安全初始化 (拒绝默认)

import os, sys

def load_secret_key():
    key = os.environ.get("SUPERSET_SECRET_KEY")
    if not key:
        print("ERROR: SUPERSET_SECRET_KEY must be configured!")
        sys.exit(1)
    return key

SECRET_KEY = load_secret_key()


✔ 强制用户提供随机密钥
✔ 启动前验证密钥合法性

这种方式在工程上保证了不使用默认值。

基于该漏洞的安全检测与防护规则

因为该漏洞本质是 伪造 session cookie,设计检测策略应关注:

  1. 非预期 session cookie 行为
  2. 重放/伪造 session 模式
  3. 异常登录行为

1) WAF 检测策略 🔹 拦截伪造 Signed Cookies

如果请求带有未由当前 SECRET_KEY 能验证的 session cookie,则触发阻断。

示例规则(ModSecurity):

SecRule REQUEST_COOKIES:session ".*" \
    "chain,deny,status:403,\
    msg:'Potential Superset forged session - CVE-2023-27524',\
    severity:CRITICAL"
SecRule &REQUEST_COOKIES:session "@gt 0" \
    "validateServerSignature:SESSION,skipAfter:END"


✔ 匹配 session cookie
✔ 验证其签名(需扩展 WAF 支持签名检查)

  1. IDS/Suricata 规则

因为攻击者会发送带伪造 session 的请求访问 admin API,可以写如下规则:

alert http any any -> any any (
    msg:"Apache Superset forged session detected (CVE-2023-27524)";
    http.cookie;
    content:"session=";
    pcre:"/[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+/";
    classtype:authentication-failure;
    sid:202327524;
    rev:1;
)


匹配典型 JWT / Flask session cookie 格式,并可进一步结合行为分析。 3) SIEM 日志规则

在 SIEM(如 Splunk/ELK)中可统计:

index=web_logs superset
| search cookie=session*
| stats count by src_ip, user_agent, uri
| where count > 10 AND uri contains "/api/v1/"


异常登录失败次数和未知 UA 是高风险指标。

检测与防护体系架构 我们设计多层次的检测与防护方案:

  • 应用层(Flask中间件):实时验证会话签名并监控异常行为。
  • 异常检测(TensorFlow模型):基于用户行为特征识别伪造会话。
  • 边界防护(ModSecurity WAF):拦截明显攻击特征并限流。

基于 Flask 的实时检测与防护

  1. 强密钥配置与会话验证 确保 Superset 使用环境变量注入的强随机 SECRET_KEY,并在 Flask 应用中正确验证。
# config.py (Superset 配置)
import os
SECRET_KEY = os.environ.get('SUPERSET_SECRET_KEY', os.urandom(32).hex())
  1. Flask 中间件检测伪造会话 部署一个中间件,检查每个请求的 cookie 签名是否有效,并监控异常模式(如短时间内大量不同用户登录尝试)。
# middleware.py
from flask import request, abort, current_app
import logging
import time
from collections import defaultdict

# 简单的内存速率限制和异常记录
class SupersetSecurityMiddleware:
    def __init__(self, app):
        self.app = app
        self.ip_failed_attempts = defaultdict(list)
        self.threshold = 5   # 5分钟内允许失败次数
        self.window = 300    # 5分钟窗口

    def __call__(self, environ, start_response):
        request = self.app.request_class(environ)
        
        # 提取 session cookie (Superset 默认 cookie 名为 'session')
        session_cookie = request.cookies.get('session')
        client_ip = request.remote_addr

        # 1. 基础签名验证(Flask 内部使用itsdangerous)
        from flask.sessions import SecureCookieSessionInterface
        si = SecureCookieSessionInterface()
        try:
            # 尝试解析并验证签名,若失败则引发异常
            session = si.loads(current_app.secret_key, session_cookie)
        except Exception as e:
            # 签名无效,记录可疑行为
            self.record_failed_attempt(client_ip)
            if self.is_ip_blocked(client_ip):
                return self.forbidden_response(environ, start_response)
            # 可记录日志但继续,或直接返回403
            # 此处为示例,返回403阻止访问
            return self.forbidden_response(environ, start_response)

        # 2. 可选:基于用户行为的异常检测(如异地登录、非常用浏览器等)
        if self.detect_anomaly(session, request):
            logging.warning(f"Anomaly detected for user {session.get('user_id')} from IP {client_ip}")
            # 可采取行动,如要求二次认证

        return self.app(environ, start_response)

    def record_failed_attempt(self, ip):
        now = time.time()
        self.ip_failed_attempts[ip] = [t for t in self.ip_failed_attempts[ip] if now - t < self.window]
        self.ip_failed_attempts[ip].append(now)

    def is_ip_blocked(self, ip):
        return len(self.ip_failed_attempts.get(ip, [])) >= self.threshold

    def forbidden_response(self, environ, start_response):
        start_response('403 Forbidden', [('Content-Type', 'text/plain')])
        return [b'Invalid session']
    
    def detect_anomaly(self, session, request):
        # 可集成TensorFlow模型或规则
        return False

# 在Superset应用启动时注册中间件
# from superset import app
# app.wsgi_app = SupersetSecurityMiddleware(app.wsgi_app)
  1. 日志监控脚本(Python) 实时分析访问日志,发现异常会话模式。
# log_monitor.py
import re
import sys
from datetime import datetime, timedelta

# 假设日志格式: [IP] - [timestamp] "GET /path" session_cookie_hash ...
LOG_PATTERN = re.compile(r'(?P<ip>[\d\.]+).*?"(?P<method>\w+) (?P<path>[^"]+)".*?session=(?P<session>[^ ]+)')

def analyze_log(logfile, window_minutes=5, threshold=10):
    attempts = {}
    with open(logfile, 'r') as f:
        for line in f:
            match = LOG_PATTERN.search(line)
            if not match:
                continue
            ip = match.group('ip')
            timestamp_str = extract_timestamp(line)  # 需根据实际格式提取
            # 简化:假设日志包含ISO时间
            timestamp = datetime.fromisoformat(timestamp_str)
            # 清理窗口外的记录
            attempts[ip] = [t for t in attempts.get(ip, []) if timestamp - t < timedelta(minutes=window_minutes)]
            attempts[ip].append(timestamp)
            
            if len(attempts[ip]) >= threshold:
                print(f"[!] 异常IP {ip}{window_minutes}分钟内请求{len(attempts[ip])}次,可能扫描或攻击")
                # 可触发告警

if __name__ == '__main__':
    analyze_log(sys.argv[1])

基于 TensorFlow 的异常行为检测

构建一个简单的神经网络模型,基于用户会话历史特征识别异常登录行为。训练数据可从正常用户行为中提取,特征包括:

  • 请求频率(单位时间内的请求数)
  • 访问的敏感路径比例(如 /api/v1/dataset/superset/dashboard 等)
  • 用户历史登录IP的地理位置(需配合GeoIP)
  • 浏览器User-Agent的一致性
  • 会话持续时间(若已知)
  • 请求的时间分布(是否在工作时间)
  1. 特征工程示例
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler

def extract_features(session_logs):
    """从用户会话日志中提取特征向量"""
    features = []
    for log in session_logs:
        # 假设每条log包含字段:user_id, timestamp, path, ip, user_agent, is_sensitive
        features.append([
            log['request_count_last_hour'],
            log['sensitive_ratio'],
            log['ip_risk_score'],      # 预先计算的IP信誉分(如是否代理)
            log['ua_consistent'],       # 用户代理与历史一致吗?0/1
            log['is_night'],            # 是否夜间访问
            log['failed_attempts']      # 最近失败次数
        ])
    return np.array(features)
  1. 模型训练(二分类:正常/异常)
import tensorflow as tf
from tensorflow.keras import layers, models
from sklearn.model_selection import train_test_split

# 假设 X 为特征矩阵,y 为标签 (0正常,1异常)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

model = models.Sequential([
    layers.Dense(64, activation='relu', input_shape=(X.shape[1],)),
    layers.Dropout(0.3),
    layers.Dense(32, activation='relu'),
    layers.Dropout(0.3),
    layers.Dense(1, activation='sigmoid')
])

model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])

history = model.fit(X_train, y_train, epochs=20, batch_size=32, validation_split=0.1)

# 保存模型
model.save('superset_anomaly_model.h5')
  1. 集成到 Flask 中间件 加载模型,对每个请求进行实时评分,若异常概率高于阈值则触发警报或强制登出。
import numpy as np
from tensorflow.keras.models import load_model

model = load_model('superset_anomaly_model.h5')

class AnomalyDetectionMiddleware:
    def __init__(self, app):
        self.app = app
        self.model = model
        self.threshold = 0.8  # 阈值

    def __call__(self, environ, start_response):
        request = self.app.request_class(environ)
        # 提取实时特征(需根据请求和用户历史构建)
        features = self.extract_real_time_features(request)
        prob = self.model.predict(features.reshape(1, -1))[0][0]
        if prob > self.threshold:
            logging.warning(f"Anomaly score {prob:.2f} for user from {request.remote_addr}")
            # 可触发告警或返回403
            return self.forbidden_response(environ, start_response)
        return self.app(environ, start_response)

    def extract_real_time_features(self, request):
        # 这里需结合数据库和缓存获取用户历史行为
        # 简化示例
        user_id = self.get_user_id_from_session(request)
        if user_id:
            # 从Redis获取最近1小时请求计数
            req_count = redis_client.get(f"user:{user_id}:count") or 0
            # 获取该用户历史IP等
            return np.array([req_count, 0.5, 0, 0, 0, 0])  # 伪代码
        return np.zeros(6)  # 未登录用户

基于 ModSecurity 的 WAF 规则 在 Apache/NGINX 中配置 ModSecurity,拦截明显利用默认密钥的尝试。

  1. 检测默认 SECRET_KEY 特征 攻击者可能通过构造特定 cookie 来测试,我们可以检测 cookie 中是否包含常见默认密钥的签名特征。
# modsecurity_crs_65_superset_cve_2023_27524.conf

# 规则1:检测请求中的 cookie 是否包含已知弱密钥的签名模式(示例)
SecRule REQUEST_COOKIES:session "@rx ^(?!.*[A-Za-z0-9+/]{32,})" \
    "id:1002001,\
    phase:1,\
    block,\
    capture,\
    t:none,\
    msg:'Superset CVE-2023-27524 - Potential forged cookie (weak key pattern)',\
    tag:'attack-superset',\
    tag:'cve-2023-27524',\
    severity:'CRITICAL'"

# 规则2:对 /login 等接口进行频率限制
SecRule REQUEST_URI "@beginsWith /login" \
    "id:1002002,\
    phase:1,\
    block,\
    ver:'OWASP_CRS/4.0',\
    msg:'Login Rate Limiting',\
    severity:'WARNING',\
    t:none,\
    setvar:'tx.login_attempt_counter_%{REQUEST_HEADERS:X-Forwarded-For|REMOTE_ADDR}=+1',\
    expirevar:'tx.login_attempt_counter_%{REQUEST_HEADERS:X-Forwarded-For|REMOTE_ADDR}=60',\
    skipAfter:END_RATE_LIMIT"

SecRule TX:login_attempt_counter_%{REQUEST_HEADERS:X-Forwarded-For|REMOTE_ADDR} "@gt 5" \
    "id:1002003,\
    phase:1,\
    block,\
    msg:'Too many login attempts',\
    severity:'WARNING',\
    t:none"

# 规则3:检测访问敏感路径(如 /api/v1/database)时是否携带了异常 cookie
SecRule REQUEST_URI "@beginsWith /api/v1/database" \
    "id:1002004,\
    phase:2,\
    chain,\
    block,\
    msg:'Superset CVE-2023-27524 - Sensitive path with suspicious cookie'"
    SecRule REQUEST_COOKIES:session "@rx ^[a-zA-Z0-9._-]{32,}$" \
        "setvar:'tx.anomaly_score=+%{tx.critical_anomaly_score}'"
  1. 部署示例(NGINX)
location / {
    ModSecurityEnabled on;
    ModSecurityConfig modsecurity.conf;
    proxy_pass http://superset:8088;
    proxy_set_header Host $host;
}

总结:通过组合应用层验证(Flask中间件)、行为异常检测(TensorFlow)和边界防护(ModSecurity),可有效防御针对 CVE-2023-27524 的攻击。本方案不仅检测已知攻击模式,还能通过机器学习发现未知的伪造会话行为,提供纵深防御。