You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将SOAP反序列化失败的默认错误消息替换为自定义消息?

SOAP反序列化失败时替换自定义错误消息

当SOAP请求的数据成员反序列化失败时,服务默认返回的错误消息会暴露内部敏感信息(如类型名称、序列化细节),存在被攻击者利用的安全风险,需要将完整的fault string替换为自定义的通用消息。

请求示例

HTTP头

POST https://abc/xyz.svc HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/109.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
SOAPAction: http://abc/action
Content-Type: text/xml;charset=UTF-8
Host: 127.0.0.1
Content-Length: 933

SOAP体

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:abc="http://action" 
xmlns:abc1="http://schemas.datacontract.org/2004/07/action.ServiceLibrary">

<soapenv:Header/>

<soapenv:Body>

<abc:Recon>

<abc:employeeID>1231456</abc:employeeID>

<abc:token>agthjknghrdfgbnhgevq</abc:token>

<abc:request>

<abc1:CurrencyCode><![CDATA[ <<!ENTITY % file SYSTEM "file:///etc/fstab">

<abc:Issuer></abc:Issuer>

<abc:Reference>per auras</abc:Reference>

</abc:request>

</abc:Recon>

</soapenv:Body> 

</soapenv:Envelope>

响应示例

HTTP/1.1 500 Internal Server Error
Date: Tue, 23 May 2023 09:55:54 GMT
Content-Type: text/xml; charset=utf-8
Content-Length: 703
Connection: close
Access-Control-Expose-Headers: Request-Context
Request-Context: appId=cid-v1:f2c7dfc0-df3b-4c74-a4d9-5fc744b61509
X-Content-Type-Options: nosniff
X-Robots-Tag: noindex
X-XSS-Protection: 1; mode=block
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><s:Fault><faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:DeserializationFailed</faultcode><faultstring xml:lang="en-US">The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://abc:request. The InnerException message was 'There was an error deserializing the object of type abc.ServiceLibrary.Request. The token '[CDATA[' was expected but found 'ENTITY '. Line 14, position 3.'. Please see InnerException for more your text details.</faultstring></s:Fault></s:Body></s:Envelope>

解决方案(针对WCF服务)

从响应的错误码命名空间可判断这是WCF服务,通过以下步骤替换自定义错误消息:

  1. 实现自定义错误处理器
    创建实现IErrorHandler接口的类,捕获反序列化异常并替换为自定义消息:

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.Runtime.Serialization;
    
    public class CustomDeserializationErrorHandler : IErrorHandler
    {
        // 标记异常已处理
        public bool HandleError(Exception error)
        {
            return error is SerializationException || error.InnerException is SerializationException;
        }
    
        // 生成自定义Fault消息
        public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            if (error is SerializationException || error.InnerException is SerializationException)
            {
                var faultReason = new FaultReason("请求格式无效,请检查请求参数后重试");
                var faultCode = FaultCode.CreateSenderFaultCode(
                    "DeserializationFailed", 
                    "http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher"
                );
                fault = Message.CreateMessage(version, faultCode, faultReason, null);
            }
        }
    }
    
  2. 创建自定义服务行为
    实现IServiceBehavior接口,将错误处理器注入到服务运行时:

    using System;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    using System.Collections.ObjectModel;
    
    public class CustomErrorBehavior : IServiceBehavior
    {
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints)
                {
                    endpointDispatcher.DispatchRuntime.ErrorHandlers.Add(new CustomDeserializationErrorHandler());
                }
            }
        }
    
        // 空实现其他接口方法
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
    }
    
    // 定义行为特性,方便代码中直接标注
    [AttributeUsage(AttributeTargets.Class)]
    public class CustomErrorBehaviorAttribute : Attribute, IServiceBehavior
    {
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            new CustomErrorBehavior().ApplyDispatchBehavior(serviceDescription, serviceHostBase);
        }
    
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
    }
    
  3. 启用自定义行为

    • 代码方式:在服务类上添加特性
      [CustomErrorBehavior]
      public class YourService : IYourService
      {
          // 服务实现代码
      }
      
    • 配置文件方式:注册行为扩展并应用到服务
      <system.serviceModel>
        <extensions>
          <behaviorExtensions>
            <add name="customErrorBehavior" type="YourNamespace.CustomErrorBehavior, YourAssemblyName"/>
          </behaviorExtensions>
        </extensions>
        <behaviors>
          <serviceBehaviors>
            <behavior name="ServiceWithCustomError">
              <serviceDebug includeExceptionDetailInFaults="false"/>
              <customErrorBehavior/>
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <services>
          <service name="YourNamespace.YourService" behaviorConfiguration="ServiceWithCustomError">
            <endpoint address="" binding="basicHttpBinding" contract="YourNamespace.IYourService"/>
          </service>
        </services>
      </system.serviceModel>
      

注意:确保serviceDebug的includeExceptionDetailInFaults设置为false,避免暴露内部异常细节。

内容的提问来源于stack exchange,提问作者user2361697

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 01:19:51