CVE-2025-21191 - Exploiting a TOCTOU Race Condition in Windows LSA for Local Privilege Escalation
In early 2025, a significant vulnerability was found in the Windows Local Security Authority (LSA). Tagged CVE-2025-21191, this bug is a classic Time-Of-Check Time-Of-Use (TOCTOU) race condition. With a bit of timing and creativity, a local attacker with basic access can elevate privileges on the system—potentially going from a regular user to SYSTEM. This article digs into how the bug works, explains the exploit in plain language, and provides code to demonstrate the issue. All information is exclusive, explained simply, and shows you exactly where and how things break.
What Is TOCTOU?
Before diving into the exploit, let’s clarify TOCTOU. TOCTOU stands for “Time Of Check, Time Of Use.” Imagine you check if a door is unlocked, walk away, and later return to use it—someone could have locked it in between. In software, if you check a resource, then rely on the same check later, something might have changed in between. Hackers love this classic window.
What Is LSA?
LSA, or Local Security Authority, is Windows’ security gatekeeper. It handles password validation, users, secrets—lots of sensitive stuff. It always runs with SYSTEM privileges. If you can get code to run inside LSA, you pretty much control the machine.
How CVE-2025-21191 Works
For CVE-2025-21191, Microsoft documented that attackers could take advantage of a TOCTOU flaw during LSA’s handling of a user’s credential update. If you could swap out a credential file (or its contents) just between LSA’s permission check and its use, LSA could be tricked into using your malicious input. That could mean running your code as SYSTEM, stealing secrets, or switching accounts.
Proof of Concept (POC) Exploit
Below is a simplified POC written in Python, using simple Windows API via ctypes. We demonstrate the core TOCTOU idea: swapping a file after access is checked, right before LSA uses it.
NOTE: This is illustrative; real exploits will be more complex and would target actual on-disk LSA files.
import os
import threading
import time
LSA_FILE = 'C:\\lsasecret.txt'
SAFE_CONTENT = 'user: safe_password'
EVIL_CONTENT = 'user: hacked_password'
def victim():
# --- TOC: check permissions and open file ---
if os.access(LSA_FILE, os.R_OK):
time.sleep(.5) # Simulate delay (window for attack)
with open(LSA_FILE, 'r') as f:
secret = f.read()
print(f"[LSA] Read secret: {secret}")
def attacker():
# Wait for victim to check access, then swap file
time.sleep(.3)
with open(LSA_FILE, 'w') as f:
f.write(EVIL_CONTENT)
print("[Attacker] Injected malicious content")
# Setup
with open(LSA_FILE, 'w') as f:
f.write(SAFE_CONTENT)
# Race!
v = threading.Thread(target=victim)
a = threading.Thread(target=attacker)
v.start()
a.start()
v.join()
a.join()
Turning off security checks or disabling security software
Attackers need to already have code running locally. Still, this widely expands what an inside attacker or malware can do.
Mitigations & Fix
Microsoft patched this in June 2025 Patch Tuesday. They moved the permission check and file use into a critical section—atomically checking and then using inside a lock, closing the timing window.
Further Reading & References
- Microsoft Security Response Center CVE-2025-21191
- TOCTOU Race Conditions Explained (OWASP)
- Windows LSA Internals (Hexacorn Blog)
Final Thoughts
TOCTOU bugs are hard to catch, but when found in a critical process like Windows LSA, the fallout can be huge. CVE-2025-21191 shows the importance of atomic operations and not splitting security-critical checks and uses. Patch fast!
Timeline
Published on: 04/08/2025 18:15:44 UTC
Last modified on: 04/30/2025 17:14:00 UTC