Lucene search

K
attackerkbAttackerKBAKB:8E9F0DC4-BC72-4340-B70E-5680CA968D2B
HistoryMar 03, 2021 - 12:00 a.m.

CVE-2021-26857

2021-03-0300:00:00
attackerkb.com
558
microsoft exchange server
remote code execution
unified messaging service
admin access
chaining
vulnerability
system account
authentication bypass

CVSS2

7.5

Attack Vector

NETWORK

Attack Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

CVSS3

9.1

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

NONE

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N

AI Score

8.5

Confidence

High

EPSS

0.975

Percentile

100.0%

Microsoft Exchange Server Remote Code Execution Vulnerability

Recent assessments:

wvu-r7 at March 03, 2021 6:59pm UTC reported:

As per Microsoft’s blog post on Exchange Server 0day use by the HAFNIUM actors, CVE-2021-26857 is a deserialization vulnerability in Exchange Server’s Unified Messaging (voicemail) service. Exploiting the vulnerability reportedly requires admin access or chaining with another vuln (likely CVE-2021-26855), but successful exploitation results in RCE as the SYSTEM account. This vulnerability would ideally be combined with an auth bypass, which CVE-2021-26855 may very well provide.

I took a look at CVE-2021-26857 last night and came up with the following patch diff:

--- exchange.unpatched/Microsoft.Exchange.UM.UMCore/UMCore/PipelineContext.cs	2021-03-02 19:54:18.000000000 -0600
+++ exchange.patched/Microsoft.Exchange.UM.UMCore/UMCore/PipelineContext.cs	2021-03-02 19:55:19.000000000 -0600
@@ -1,742 +1,886 @@
 using System;
+using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
+using System.Runtime.Serialization;
+using Microsoft.Exchange.Compliance.Serialization.Formatters;
+using Microsoft.Exchange.Data;
+using Microsoft.Exchange.Data.Common;
 using Microsoft.Exchange.Data.Directory;
 using Microsoft.Exchange.Data.Directory.Recipient;
 using Microsoft.Exchange.Data.Directory.SystemConfiguration;
 using Microsoft.Exchange.Data.Storage;
 using Microsoft.Exchange.Diagnostics;
 using Microsoft.Exchange.Diagnostics.Components.UnifiedMessaging;
 using Microsoft.Exchange.ExchangeSystem;
 using Microsoft.Exchange.TextProcessing.Boomerang;
 using Microsoft.Exchange.UM.UMCommon;
+using Microsoft.Mapi;

 namespace Microsoft.Exchange.UM.UMCore
 {
 	internal abstract class PipelineContext : DisposableBase, IUMCreateMessage
 	{
 		internal PipelineContext()
 		{
 		}

 		internal PipelineContext(SubmissionHelper helper)
 		{
 			bool flag = false;
 			try
 			{
 				this.helper = helper;
 				this.cultureInfo = new CultureInfo(helper.CultureInfo);
 				flag = true;
 			}
 			finally
 			{
 				if (!flag)
 				{
 					this.Dispose();
 				}
 			}
 		}

 		public MessageItem MessageToSubmit
 		{
 			get
 			{
 				return this.messageToSubmit;
 			}
 			protected set
 			{
 				this.messageToSubmit = value;
 			}
 		}

 		public string MessageID
 		{
 			get
 			{
 				return this.messageID;
 			}
 			protected set
 			{
 				this.messageID = value;
 			}
 		}

 		internal abstract Pipeline Pipeline { get; }

 		internal Microsoft.Exchange.UM.UMCommon.PhoneNumber CallerId
 		{
 			get
 			{
 				return this.helper.CallerId;
 			}
 		}

 		internal Guid TenantGuid
 		{
 			get
 			{
 				return this.helper.TenantGuid;
 			}
 		}

 		internal int ProcessedCount
 		{
 			get
 			{
 				return this.processedCount;
 			}
 		}

 		internal ExDateTime SentTime
 		{
 			get
 			{
 				return this.sentTime;
 			}
 			set
 			{
 				this.sentTime = value;
 			}
 		}

 		internal CultureInfo CultureInfo
 		{
 			get
 			{
 				return this.cultureInfo;
 			}
 		}

 		protected internal string HeaderFileName
 		{
 			get
 			{
 				if (string.IsNullOrEmpty(this.headerFileName))
 				{
 					Guid guid = Guid.NewGuid();
 					this.headerFileName = Path.Combine(Utils.VoiceMailFilePath, guid.ToString() + ".txt");
 				}
 				return this.headerFileName;
 			}
 			protected set
 			{
 				this.headerFileName = value;
 			}
 		}

 		protected internal string CallerAddress
 		{
 			get
 			{
 				return this.helper.CallerAddress;
 			}
 			protected set
 			{
 				this.helper.CallerAddress = value;
 			}
 		}

 		protected internal string CallerIdDisplayName
 		{
 			get
 			{
 				return this.helper.CallerIdDisplayName;
 			}
 			protected set
 			{
 				this.helper.CallerIdDisplayName = value;
 			}
 		}

 		protected internal string MessageType
 		{
 			internal get
 			{
 				return this.messageType;
 			}
 			set
 			{
 				this.messageType = value;
 			}
 		}

 		public virtual void PrepareUnProtectedMessage()
 		{
 			CallIdTracer.TraceDebug(ExTraceGlobals.VoiceMailTracer, this.GetHashCode(), "PipelineContext:PrepareUnProtectedMessage.", Array.Empty<object>());
 			using (DisposeGuard disposeGuard = default(DisposeGuard))
 			{
 				this.messageToSubmit = MessageItem.CreateInMemory(StoreObjectSchema.ContentConversionProperties);
 				disposeGuard.Add<MessageItem>(this.messageToSubmit);
 				this.SetMessageProperties();
 				disposeGuard.Success();
 			}
 		}

 		public virtual void PrepareProtectedMessage()
 		{
 			throw new InvalidOperationException();
 		}

 		public virtual void PrepareNDRForFailureToGenerateProtectedMessage()
 		{
 			throw new InvalidOperationException();
 		}

 		public virtual PipelineDispatcher.WIThrottleData GetThrottlingData()
 		{
 			return new PipelineDispatcher.WIThrottleData
 			{
 				Key = this.GetMailboxServerId(),
 				RecipientId = this.GetRecipientIdForThrottling(),
 				WorkItemType = PipelineDispatcher.ThrottledWorkItemType.NonCDRWorkItem
 			};
 		}

 		public virtual void PostCompletion()
 		{
 			CallIdTracer.TraceDebug(ExTraceGlobals.VoiceMailTracer, 0, "PipelineContext - Deleting header file '{0}'", new object[]
 			{
 				this.headerFileName
 			});
 			Util.TryDeleteFile(this.headerFileName);
 		}

 		internal static PipelineContext FromHeaderFile(string headerFile)
 		{
 			PipelineContext pipelineContext = null;
 			PipelineContext result;
 			try
 			{
 				ContactInfo contactInfo = null;
 				string text = null;
 				int num = 0;
 				ExDateTime exDateTime = default(ExDateTime);
 				string text2 = null;
 				SubmissionHelper submissionHelper = new SubmissionHelper();
 				uint num2;
 				using (StreamReader streamReader = File.OpenText(headerFile))
 				{
 					string text3;
 					while ((text3 = streamReader.ReadLine()) != null)
 					{
 						string[] array = text3.Split(" : ".ToCharArray(), 2, StringSplitOptions.RemoveEmptyEntries);
 						if (array != null && array.Length == 2)
 						{
 							string text4 = array[0];
 							num2 = <PrivateImplementationDetails>.ComputeStringHash(text4);
 							if (num2 <= 872212143U)
 							{
 								if (num2 <= 134404218U)
 								{
 									if (num2 != 77294025U)
 									{
 										if (num2 != 111122938U)
 										{
-											if (num2 == 134404218U)
+											if (num2 != 134404218U)
 											{
-												if (text4 == "ProcessedCount")
-												{
-													num = Convert.ToInt32(array[1], CultureInfo.InvariantCulture) + 1;
-													continue;
-												}
+												goto IL_409;
+											}
+											if (!(text4 == "ProcessedCount"))
+											{
+												goto IL_409;
 											}
+											num = Convert.ToInt32(array[1], CultureInfo.InvariantCulture) + 1;
+											continue;
 										}
-										else if (text4 == "RecipientObjectGuid")
+										else
 										{
+											if (!(text4 == "RecipientObjectGuid"))
+											{
+												goto IL_409;
+											}
 											submissionHelper.RecipientObjectGuid = new Guid(array[1]);
 											continue;
 										}
 									}
-									else if (text4 == "CallerNAme")
+									else
 									{
+										if (!(text4 == "CallerNAme"))
+										{
+											goto IL_409;
+										}
 										submissionHelper.CallerName = array[1];
 										continue;
 									}
 								}
 								else if (num2 <= 507978139U)
 								{
 									if (num2 != 152414519U)
 									{
-										if (num2 == 507978139U)
+										if (num2 != 507978139U)
 										{
-											if (text4 == "RecipientName")
-											{
-												submissionHelper.RecipientName = array[1];
-												continue;
-											}
+											goto IL_409;
 										}
+										if (!(text4 == "RecipientName"))
+										{
+											goto IL_409;
+										}
+										submissionHelper.RecipientName = array[1];
+										continue;
 									}
-									else if (text4 == "ContactInfo")
+									else
 									{
-										contactInfo = (CommonUtil.Base64Deserialize(array[1]) as ContactInfo);
-										continue;
+										if (!(text4 == "ContactInfo"))
+										{
+											goto IL_409;
+										}
+										Exception ex = null;
+										try
+										{
+											try
+											{
+												using (MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(array[1])))
+												{
+													contactInfo = (ContactInfo)TypedBinaryFormatter.DeserializeObject(memoryStream, PipelineContext.contactInfoDeserializationAllowList, null, true);
+												}
+											}
+											catch (ArgumentNullException ex)
+											{
+											}
+											catch (SerializationException ex)
+											{
+											}
+											catch (Exception ex)
+											{
+											}
+											continue;
+										}
+										finally
+										{
+											if (ex != null)
+											{
+												CallIdTracer.TraceDebug(ExTraceGlobals.VoiceMailTracer, 0, "Failed to get contactInfo from header file {0} with Error={1}", new object[]
+												{
+													headerFile,
+													ex
+												});
+											}
+										}
 									}
 								}
 								else if (num2 != 707084238U)
 								{
-									if (num2 == 872212143U)
+									if (num2 != 872212143U)
 									{
-										if (text4 == "CallerId")
-										{
-											submissionHelper.CallerId = Microsoft.Exchange.UM.UMCommon.PhoneNumber.Parse(array[1]);
-											continue;
-										}
+										goto IL_409;
 									}
+									if (!(text4 == "CallerId"))
+									{
+										goto IL_409;
+									}
+									submissionHelper.CallerId = Microsoft.Exchange.UM.UMCommon.PhoneNumber.Parse(array[1]);
+									continue;
 								}
-								else if (text4 == "SentTime")
+								else
 								{
+									if (!(text4 == "SentTime"))
+									{
+										goto IL_409;
+									}
 									DateTime dateTime = Convert.ToDateTime(array[1], CultureInfo.InvariantCulture);
 									exDateTime = new ExDateTime(ExTimeZone.CurrentTimeZone, dateTime);
 									continue;
 								}
 							}
 							else if (num2 <= 2593661420U)
 							{
 								if (num2 <= 1526417836U)
 								{
 									if (num2 != 978885386U)
 									{
-										if (num2 == 1526417836U)
+										if (num2 != 1526417836U)
 										{
-											if (text4 == "MessageType")
-											{
-												text = array[1];
-												continue;
-											}
+											goto IL_409;
+										}
+										if (!(text4 == "MessageType"))
+										{
+											goto IL_409;
 										}
+										text = array[1];
+										continue;
 									}
-									else if (text4 == "CallerAddress")
+									else
 									{
+										if (!(text4 == "CallerAddress"))
+										{
+											goto IL_409;
+										}
 										submissionHelper.CallerAddress = array[1];
 										continue;
 									}
 								}
 								else if (num2 != 1850847732U)
 								{
-									if (num2 == 2593661420U)
+									if (num2 != 2593661420U)
 									{
-										if (text4 == "CallId")
-										{
-											submissionHelper.CallId = array[1];
-											continue;
-										}
+										goto IL_409;
 									}
+									if (!(text4 == "CallId"))
+									{
+										goto IL_409;
+									}
+									submissionHelper.CallId = array[1];
+									continue;
 								}
-								else if (text4 == "CallerIdDisplayName")
+								else
 								{
+									if (!(text4 == "CallerIdDisplayName"))
+									{
+										goto IL_409;
+									}
 									submissionHelper.CallerIdDisplayName = array[1];
 									continue;
 								}
 							}
 							else if (num2 <= 3342616108U)
 							{
 								if (num2 != 2975106116U)
 								{
-									if (num2 == 3342616108U)
+									if (num2 != 3342616108U)
 									{
-										if (text4 == "TenantGuid")
-										{
-											submissionHelper.TenantGuid = new Guid(array[1]);
-											continue;
-										}
+										goto IL_409;
 									}
+									if (!(text4 == "TenantGuid"))
+									{
+										goto IL_409;
+									}
+									submissionHelper.TenantGuid = new Guid(array[1]);
+									continue;
 								}
-								else if (text4 == "SenderAddress")
+								else
 								{
+									if (!(text4 == "SenderAddress"))
+									{
+										goto IL_409;
+									}
 									string text5 = array[1];
 									continue;
 								}
 							}
 							else if (num2 != 3581765001U)
 							{
-								if (num2 == 4186841001U)
+								if (num2 != 4186841001U)
 								{
-									if (text4 == "CultureInfo")
-									{
-										submissionHelper.CultureInfo = array[1];
-										continue;
-									}
+									goto IL_409;
+								}
+								if (!(text4 == "CultureInfo"))
+								{
+									goto IL_409;
 								}
+								submissionHelper.CultureInfo = array[1];
+								continue;
 							}
-							else if (text4 == "MessageID")
+							else if (!(text4 == "MessageID"))
 							{
-								text2 = array[1];
-								continue;
+								goto IL_409;
 							}
+							text2 = array[1];
+							continue;
+							IL_409:
 							submissionHelper.CustomHeaders[array[0]] = array[1];
 						}
 					}
 				}
 				num2 = <PrivateImplementationDetails>.ComputeStringHash(text);
 				if (num2 <= 894870128U)
 				{
 					if (num2 <= 360985808U)
 					{
 						if (num2 != 356120169U)
 						{
 							if (num2 == 360985808U)
 							{
 								if (text == "Fax")
 								{
 									pipelineContext = new FaxPipelineContext(submissionHelper);
-									goto IL_62E;
+									goto IL_694;
 								}
 							}
 						}
 						else if (text == "IncomingCallLog")
 						{
 							pipelineContext = new IncomingCallLogPipelineContext(submissionHelper);
-							goto IL_62E;
+							goto IL_694;
 						}
 					}
 					else if (num2 != 438908515U)
 					{
 						if (num2 != 466919760U)
 						{
 							if (num2 == 894870128U)
 							{
 								if (text == "CDR")
 								{
 									pipelineContext = CDRPipelineContext.Deserialize((string)submissionHelper.CustomHeaders["CDRData"]);
-									goto IL_62E;
+									goto IL_694;
 								}
 							}
 						}
 						else if (text == "MissedCall")
 						{
 							pipelineContext = new MissedCallPipelineContext(submissionHelper);
-							goto IL_62E;
+							goto IL_694;
 						}
 					}
 					else if (text == "OCSNotification")
 					{
 						pipelineContext = OCSPipelineContext.Deserialize((string)submissionHelper.CustomHeaders["OCSNotificationData"]);
 						text2 = pipelineContext.messageID;
 						exDateTime = pipelineContext.sentTime;
-						goto IL_62E;
+						goto IL_694;
 					}
 				}
 				else if (num2 <= 1086454342U)
 				{
 					if (num2 != 995233564U)
 					{
 						if (num2 == 1086454342U)
 						{
 							if (text == "XSOVoiceMail")
 							{
 								pipelineContext = new XSOVoiceMessagePipelineContext(submissionHelper);
-								goto IL_62E;
+								goto IL_694;
 							}
 						}
 					}
 					else if (text == "PartnerTranscriptionRequest")
 					{
 						pipelineContext = new PartnerTranscriptionRequestPipelineContext(submissionHelper);
-						goto IL_62E;
+						goto IL_694;
 					}
 				}
 				else if (num2 != 1356218075U)
 				{
 					if (num2 != 2525024257U)
 					{
 						if (num2 == 3974407582U)
 						{
 							if (text == "SMTPVoiceMail")
 							{
 								if (num < PipelineWorkItem.ProcessedCountMax - 1)
 								{
 									pipelineContext = new VoiceMessagePipelineContext(submissionHelper);
-									goto IL_62E;
+									goto IL_694;
 								}
 								pipelineContext = new MissedCallPipelineContext(submissionHelper);
-								goto IL_62E;
+								goto IL_694;
 							}
 						}
 					}
 					else if (text == "HealthCheck")
 					{
 						pipelineContext = new HealthCheckPipelineContext(Path.GetFileNameWithoutExtension(headerFile));
-						goto IL_62E;
+						goto IL_694;
 					}
 				}
 				else if (text == "OutgoingCallLog")
 				{
 					pipelineContext = new OutgoingCallLogPipelineContext(submissionHelper);
-					goto IL_62E;
+					goto IL_694;
 				}
 				throw new HeaderFileArgumentInvalidException(string.Format(CultureInfo.InvariantCulture, "{0}: {1}", "MessageType", text));
-				IL_62E:
+				IL_694:
 				if (text2 == null)
 				{
 					text2 = Guid.NewGuid().ToString();
 					exDateTime = ExDateTime.Now;
 				}
 				pipelineContext.HeaderFileName = headerFile;
 				pipelineContext.processedCount = num;
 				if (contactInfo != null)
 				{
 					IUMResolveCaller iumresolveCaller = pipelineContext as IUMResolveCaller;
 					if (iumresolveCaller != null)
 					{
 						iumresolveCaller.ContactInfo = contactInfo;
 					}
 				}
 				pipelineContext.sentTime = exDateTime;
 				pipelineContext.messageID = text2;
 				pipelineContext.WriteHeaderFile(headerFile);
 				result = pipelineContext;
 			}
-			catch (IOException ex)
+			catch (IOException ex2)
 			{
 				CallIdTracer.TraceDebug(ExTraceGlobals.VoiceMailTracer, 0, "Failed to parse the header file {0} because its not closed by thread creating the file.  Error={1}", new object[]
 				{
 					headerFile,
-					ex
+					ex2
 				});
 				if (pipelineContext != null)
 				{
 					pipelineContext.Dispose();
 					pipelineContext = null;
 				}
 				result = null;
 			}
-			catch (InvalidObjectGuidException ex2)
+			catch (InvalidObjectGuidException ex3)
 			{
 				CallIdTracer.TraceWarning(ExTraceGlobals.VoiceMailTracer, 0, "Couldn't find the recipient for this message. Error={0}", new object[]
 				{
-					ex2
+					ex3
 				});
 				if (pipelineContext != null)
 				{
 					pipelineContext.Dispose();
 					pipelineContext = null;
 				}
 				throw;
 			}
-			catch (InvalidTenantGuidException ex3)
+			catch (InvalidTenantGuidException ex4)
 			{
 				CallIdTracer.TraceWarning(ExTraceGlobals.VoiceMailTracer, 0, "Couldn't find the tenant for this message. Error={0}", new object[]
 				{
-					ex3
+					ex4
 				});
 				if (pipelineContext != null)
 				{
 					pipelineContext.Dispose();
 					pipelineContext = null;
 				}
 				throw;
 			}
-			catch (NonUniqueRecipientException ex4)
+			catch (NonUniqueRecipientException ex5)
 			{
 				CallIdTracer.TraceWarning(ExTraceGlobals.VoiceMailTracer, 0, "Multiple objects found for the recipient. Error={0}", new object[]
 				{
-					ex4
+					ex5
 				});
 				if (pipelineContext != null)
 				{
 					pipelineContext.Dispose();
 					pipelineContext = null;
 				}
 				throw;
 			}
 			return result;
 		}

 		internal abstract void WriteCustomHeaderFields(StreamWriter headerStream);

 		public abstract string GetMailboxServerId();

 		public abstract string GetRecipientIdForThrottling();

 		internal virtual void SaveMessage()
 		{
 			this.WriteHeaderFile(this.HeaderFileName);
 		}

 		protected override void InternalDispose(bool disposing)
 		{
 			if (disposing)
 			{
 				CallIdTracer.TraceDebug(ExTraceGlobals.VoiceMailTracer, this.GetHashCode(), "PipelineContext.Dispose() called", Array.Empty<object>());
 			}
 		}

 		protected override DisposeTracker InternalGetDisposeTracker()
 		{
 			return DisposeTracker.Get<PipelineContext>(this);
 		}

 		protected virtual void SetMessageProperties()
 		{
 			IUMResolveCaller iumresolveCaller = this as IUMResolveCaller;
 			if (iumresolveCaller != null)
 			{
 				ExAssert.RetailAssert(iumresolveCaller.ContactInfo != null, "ResolveCallerStage should always set the ContactInfo.");
 				UMSubscriber umsubscriber = ((IUMCAMessage)this).CAMessageRecipient as UMSubscriber;
 				UMDialPlan dialPlan = (umsubscriber != null) ? umsubscriber.DialPlan : null;
 				Microsoft.Exchange.UM.UMCommon.PhoneNumber pstnCallbackTelephoneNumber = this.CallerId.GetPstnCallbackTelephoneNumber(iumresolveCaller.ContactInfo, dialPlan);
 				this.messageToSubmit.From = iumresolveCaller.ContactInfo.CreateParticipant(pstnCallbackTelephoneNumber, this.CultureInfo);
 				XsoUtil.SetVoiceMessageSenderProperties(this.messageToSubmit, iumresolveCaller.ContactInfo, dialPlan, this.CallerId);
 				this.messageToSubmit.InternetMessageId = BoomerangHelper.FormatInternetMessageId(this.MessageID, Utils.GetHostFqdn());
 				this.messageToSubmit[ItemSchema.SentTime] = this.SentTime;
 			}
 			this.messageToSubmit.AutoResponseSuppress = AutoResponseSuppress.All;
 			this.messageToSubmit[MessageItemSchema.CallId] = this.helper.CallId;
 			IUMCAMessage iumcamessage = this as IUMCAMessage;
 			if (iumcamessage != null)
 			{
 				this.MessageToSubmit.Recipients.Add(new Participant(iumcamessage.CAMessageRecipient.ADRecipient));
 				IADSystemConfigurationLookup iadsystemConfigurationLookup = ADSystemConfigurationLookupFactory.CreateFromOrganizationId(iumcamessage.CAMessageRecipient.ADRecipient.OrganizationId);
 				this.MessageToSubmit.Sender = new Participant(iadsystemConfigurationLookup.GetMicrosoftExchangeRecipient());
 			}
 		}

 		protected void WriteHeaderFile(string headerFileName)
 		{
 			using (FileStream fileStream = File.Open(headerFileName, FileMode.Create, FileAccess.Write, FileShare.None))
 			{
 				using (StreamWriter streamWriter = new StreamWriter(fileStream))
 				{
 					if (this.MessageType != null)
 					{
 						streamWriter.WriteLine("MessageType : " + this.MessageType);
 					}
 					streamWriter.WriteLine("ProcessedCount : " + this.processedCount.ToString(CultureInfo.InvariantCulture));
 					if (this.messageID != null)
 					{
 						streamWriter.WriteLine("MessageID : " + this.messageID);
 					}
 					if (this.sentTime.Year != 1)
 					{
 						streamWriter.WriteLine("SentTime : " + this.sentTime.ToString(CultureInfo.InvariantCulture));
 					}
 					this.WriteCommonHeaderFields(streamWriter);
 					this.WriteCustomHeaderFields(streamWriter);
 				}
 			}
 		}

 		protected virtual void WriteCommonHeaderFields(StreamWriter headerStream)
 		{
 			if (!this.CallerId.IsEmpty)
 			{
 				headerStream.WriteLine("CallerId : " + this.CallerId.ToDial);
 			}
 			if (this.helper.RecipientName != null)
 			{
 				headerStream.WriteLine("RecipientName : " + this.helper.RecipientName);
 			}
 			if (this.helper.RecipientObjectGuid != Guid.Empty)
 			{
 				headerStream.WriteLine("RecipientObjectGuid : " + this.helper.RecipientObjectGuid.ToString());
 			}
 			if (this.helper.CallerName != null)
 			{
 				headerStream.WriteLine("CallerNAme : " + this.helper.CallerName);
 			}
 			if (!string.IsNullOrEmpty(this.helper.CallerIdDisplayName))
 			{
 				headerStream.WriteLine("CallerIdDisplayName : " + this.helper.CallerIdDisplayName);
 			}
 			if (this.CallerAddress != null)
 			{
 				headerStream.WriteLine("CallerAddress : " + this.CallerAddress);
 			}
 			if (this.helper.CultureInfo != null)
 			{
 				headerStream.WriteLine("CultureInfo : " + this.helper.CultureInfo);
 			}
 			if (this.helper.CallId != null)
 			{
 				headerStream.WriteLine("CallId : " + this.helper.CallId);
 			}
 			IUMResolveCaller iumresolveCaller = this as IUMResolveCaller;
 			if (iumresolveCaller != null && iumresolveCaller.ContactInfo != null)
 			{
 				headerStream.WriteLine("ContactInfo : " + CommonUtil.Base64Serialize(iumresolveCaller.ContactInfo));
 			}
 			headerStream.WriteLine("TenantGuid : " + this.helper.TenantGuid.ToString());
 		}

 		protected UMRecipient CreateRecipientFromObjectGuid(Guid objectGuid, Guid tenantGuid)
 		{
 			return UMRecipient.Factory.FromADRecipient<UMRecipient>(this.CreateADRecipientFromObjectGuid(objectGuid, tenantGuid));
 		}

 		protected ADRecipient CreateADRecipientFromObjectGuid(Guid objectGuid, Guid tenantGuid)
 		{
 			if (objectGuid == Guid.Empty)
 			{
 				throw new HeaderFileArgumentInvalidException("ObjectGuid is empty");
 			}
 			ADRecipient adrecipient = ADRecipientLookupFactory.CreateFromTenantGuid(tenantGuid).LookupByObjectId(new ADObjectId(objectGuid));
 			if (adrecipient == null)
 			{
 				CallIdTracer.TraceDebug(ExTraceGlobals.VoiceMailTracer, 0, "Could not find recipient {0}", new object[]
 				{
 					objectGuid.ToString()
 				});
 				throw new InvalidObjectGuidException(objectGuid.ToString());
 			}
 			return adrecipient;
 		}

 		protected UMDialPlan InitializeCallerIdAndTryGetDialPlan(UMRecipient recipient)
 		{
 			UMDialPlan umdialPlan = null;
 			if (this.CallerId.UriType == UMUriType.E164 && recipient.ADRecipient.UMRecipientDialPlanId != null)
 			{
 				umdialPlan = ADSystemConfigurationLookupFactory.CreateFromADRecipient(recipient.ADRecipient).GetDialPlanFromId(recipient.ADRecipient.UMRecipientDialPlanId);
 				if (umdialPlan != null && umdialPlan.CountryOrRegionCode != null)
 				{
 					this.helper.CallerId = this.helper.CallerId.Clone(umdialPlan);
 				}
 			}
 			return umdialPlan;
 		}

 		protected string GetMailboxServerIdHelper()
 		{
 			IUMCAMessage iumcamessage = this as IUMCAMessage;
 			if (iumcamessage != null)
 			{
 				UMMailboxRecipient ummailboxRecipient = iumcamessage.CAMessageRecipient as UMMailboxRecipient;
 				if (ummailboxRecipient != null)
 				{
 					return ummailboxRecipient.ADUser.ServerLegacyDN;
 				}
 			}
 			return "af360a7e-e6d4-494a-ac69-6ae14896d16b";
 		}

 		protected string GetRecipientIdHelper()
 		{
 			IUMCAMessage iumcamessage = this as IUMCAMessage;
 			if (iumcamessage != null)
 			{
 				UMMailboxRecipient ummailboxRecipient = iumcamessage.CAMessageRecipient as UMMailboxRecipient;
 				if (ummailboxRecipient != null)
 				{
 					return ummailboxRecipient.ADUser.DistinguishedName;
 				}
 			}
 			return "455e5330-ce1f-48d1-b6b1-2e318d2ff2c4";
 		}

 		private MessageItem messageToSubmit;

 		private SubmissionHelper helper;

 		private string messageType;

 		private CultureInfo cultureInfo;

 		private string headerFileName;

 		private int processedCount;

 		private string messageID;

 		private ExDateTime sentTime;
+
+		private static Type[] contactInfoDeserializationAllowList = new Type[]
+		{
+			typeof(Version),
+			typeof(Guid),
+			typeof(PropTag),
+			typeof(ContactInfo),
+			typeof(ADContactInfo),
+			typeof(FoundByType),
+			typeof(ADUser),
+			typeof(ADPropertyBag),
+			typeof(ValidationError),
+			typeof(ADPropertyDefinition),
+			typeof(ADObjectId),
+			typeof(ExchangeObjectVersion),
+			typeof(ExchangeBuild),
+			typeof(MultiValuedProperty<string>),
+			typeof(LocalizedString),
+			typeof(ProxyAddressCollection),
+			typeof(SmtpAddress),
+			typeof(RecipientDisplayType),
+			typeof(RecipientTypeDetails),
+			typeof(ElcMailboxFlags),
+			typeof(UserAccountControlFlags),
+			typeof(ObjectState),
+			typeof(DirectoryBackendType),
+			typeof(MServPropertyDefinition),
+			typeof(MbxPropertyDefinition),
+			typeof(MbxPropertyDefinitionFlags),
+			typeof(OrganizationId),
+			typeof(PartitionId),
+			typeof(SmtpProxyAddress),
+			typeof(SmtpProxyAddressPrefix),
+			typeof(ByteQuantifiedSize),
+			typeof(Unlimited<ByteQuantifiedSize>),
+			typeof(List<ValidationError>),
+			typeof(ADMultiValuedProperty<TextMessagingStateBase>),
+			typeof(ADMultiValuedProperty<ADObjectId>),
+			typeof(StoreObjectId),
+			typeof(StoreObjectType),
+			typeof(EntryIdProvider),
+			typeof(SimpleContactInfoBase),
+			typeof(MultipleResolvedContactInfo),
+			typeof(CallerNameDisplayContactInfo),
+			typeof(PersonalContactInfo),
+			typeof(DefaultContactInfo),
+			typeof(UMDialPlan),
+			typeof(UMEnabledFlags),
+			Type.GetType("Microsoft.Exchange.Data.ByteQuantifiedSize+QuantifierProvider, Microsoft.Exchange.Data"),
+			Type.GetType("System.UnitySerializationHolder, mscorlib"),
+			Type.GetType("Microsoft.Exchange.Data.ByteQuantifiedSize+Quantifier,Microsoft.Exchange.Data"),
+			Type.GetType("Microsoft.Exchange.Data.PropertyBag+ValuePair, Microsoft.Exchange.Data"),
+			Type.GetType("System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"),
+			typeof(DialByNamePrimaryEnum),
+			typeof(DialByNameSecondaryEnum),
+			typeof(AudioCodecEnum),
+			typeof(UMUriType),
+			typeof(UMSubscriberType),
+			typeof(UMGlobalCallRoutingScheme),
+			typeof(UMVoIPSecurityType),
+			typeof(SystemFlagsEnum),
+			typeof(EumProxyAddress),
+			typeof(EumProxyAddressPrefix)
+		};
 	}
 }

The patch appears to add and use a typed allowlist for deserialization of a voicemail’s contact info, which is found in a header file alongside the voicemail itself. Other seemingly unprotected deserializations can be seen in the same class. (I think it’s just XML parsing.) My suspicion is that CVE-2021-26858 or CVE-2021-27065 could be used to write a malicious header file to C:\Program Files\Microsoft\Exchange Server\V15\UnifiedMessaging\voicemail, but it’s entirely possible a crafted voicemail could be sent instead. While I haven’t developed a PoC yet, I do have a good idea how to, assuming the patch analysis is correct. Better-resourced attackers should be able to exploit this issue in considerably less time.

The specifically patched code can be seen below:

[snip]
									else
									{
										if (!(text4 == "ContactInfo"))
										{
											goto IL_409;
										}
										Exception ex = null;
										try
										{
											try
											{
												using (MemoryStream memoryStream = new MemoryStream(Convert.FromBase64String(array[1])))
												{
													contactInfo = (ContactInfo)TypedBinaryFormatter.DeserializeObject(memoryStream, PipelineContext.contactInfoDeserializationAllowList, null, true);
												}
											}
											catch (ArgumentNullException ex)
											{
											}
											catch (SerializationException ex)
											{
											}
											catch (Exception ex)
											{
											}
											continue;
										}
										finally
										{
											if (ex != null)
											{
												CallIdTracer.TraceDebug(ExTraceGlobals.VoiceMailTracer, 0, "Failed to get contactInfo from header file {0} with Error={1}", new object[]
												{
													headerFile,
													ex
												});
											}
										}
									}
[snip]



[snip]
		private static Type[] contactInfoDeserializationAllowList = new Type[]
		{
			typeof(Version),
			typeof(Guid),
			typeof(PropTag),
			typeof(ContactInfo),
			typeof(ADContactInfo),
			typeof(FoundByType),
			typeof(ADUser),
			typeof(ADPropertyBag),
			typeof(ValidationError),
			typeof(ADPropertyDefinition),
			typeof(ADObjectId),
			typeof(ExchangeObjectVersion),
			typeof(ExchangeBuild),
			typeof(MultiValuedProperty<string>),
			typeof(LocalizedString),
			typeof(ProxyAddressCollection),
			typeof(SmtpAddress),
			typeof(RecipientDisplayType),
			typeof(RecipientTypeDetails),
			typeof(ElcMailboxFlags),
			typeof(UserAccountControlFlags),
			typeof(ObjectState),
			typeof(DirectoryBackendType),
			typeof(MServPropertyDefinition),
			typeof(MbxPropertyDefinition),
			typeof(MbxPropertyDefinitionFlags),
			typeof(OrganizationId),
			typeof(PartitionId),
			typeof(SmtpProxyAddress),
			typeof(SmtpProxyAddressPrefix),
			typeof(ByteQuantifiedSize),
			typeof(Unlimited<ByteQuantifiedSize>),
			typeof(List<ValidationError>),
			typeof(ADMultiValuedProperty<TextMessagingStateBase>),
			typeof(ADMultiValuedProperty<ADObjectId>),
			typeof(StoreObjectId),
			typeof(StoreObjectType),
			typeof(EntryIdProvider),
			typeof(SimpleContactInfoBase),
			typeof(MultipleResolvedContactInfo),
			typeof(CallerNameDisplayContactInfo),
			typeof(PersonalContactInfo),
			typeof(DefaultContactInfo),
			typeof(UMDialPlan),
			typeof(UMEnabledFlags),
			Type.GetType("Microsoft.Exchange.Data.ByteQuantifiedSize+QuantifierProvider, Microsoft.Exchange.Data"),
			Type.GetType("System.UnitySerializationHolder, mscorlib"),
			Type.GetType("Microsoft.Exchange.Data.ByteQuantifiedSize+Quantifier,Microsoft.Exchange.Data"),
			Type.GetType("Microsoft.Exchange.Data.PropertyBag+ValuePair, Microsoft.Exchange.Data"),
			Type.GetType("System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"),
			typeof(DialByNamePrimaryEnum),
			typeof(DialByNameSecondaryEnum),
			typeof(AudioCodecEnum),
			typeof(UMUriType),
			typeof(UMSubscriberType),
			typeof(UMGlobalCallRoutingScheme),
			typeof(UMVoIPSecurityType),
			typeof(SystemFlagsEnum),
			typeof(EumProxyAddress),
			typeof(EumProxyAddressPrefix)
		};
[snip]

Assessed Attacker Value: 5
Assessed Attacker Value: 5Assessed Attacker Value: 3

CVSS2

7.5

Attack Vector

NETWORK

Attack Complexity

LOW

Authentication

NONE

Confidentiality Impact

PARTIAL

Integrity Impact

PARTIAL

Availability Impact

PARTIAL

AV:N/AC:L/Au:N/C:P/I:P/A:P

CVSS3

9.1

Attack Vector

NETWORK

Attack Complexity

LOW

Privileges Required

NONE

User Interaction

NONE

Scope

UNCHANGED

Confidentiality Impact

HIGH

Integrity Impact

HIGH

Availability Impact

NONE

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N

AI Score

8.5

Confidence

High

EPSS

0.975

Percentile

100.0%