Auditing and Logging

patterns & practices Developer Center

  • What WCF service security events should be logged?
  • How do I enable logging and auditing in WCF?
  • How do I stop my service if there has been an auditing failure?
  • How do I log important business events in WCF?
  • How do I implement log throttling in WCF?
  • How do I use the health monitoring feature with WCF?
  • How do I protect my log files?
  • How do I pass user identity information in a message for auditing purpose?

What WCF service security events should be logged?

In order to improve auditing and increase your chances of discovering an attack on your system, the following security events should be logged:

  • Use WCF auditing to log authentication successes and failures.
  • Use WCF auditing to log authorization successes and failures.
  • Use WCF message logging to log malformed Simple Object Access Protocol (SOAP) messages.
  • Use ASP.NET health monitoring in conjunction with your input and data validation routines to log malformed parameters and schema in incoming WCF messages.

How do I enable logging and auditing in WCF?

There are three key technologies you can use to audit and log operations in your WCF service:

  • Use WCF auditing to audit security events such as authentication and authorization failures.
  • Use WCF message logging to log malformed SOAP messages or to trace incoming messages.
  • Use ASP.NET health monitoring to provide custom logging; for instance, to log the occurrence of malformed input parameters or other significant occurrences.

Enable WCF Auditing in your config file with a serviceSecurityAudit service behavior as follows:

…
<behaviors>
  <serviceBehaviors>
    <behavior name="ServiceBehavior">
        <serviceSecurityAudit auditLogLocation="Application" serviceAuthorizationAuditLevel="SuccessOrFailure"
         messageAuthenticationAuditLevel="SuccessOrFailure" />
    </behavior>
  </serviceBehaviors>
</behaviors>
…

Enable message logging in your config file by creating a ServiceModelMessageLoggingListener and System.ServiceModel.MessageLogging source, and then add MessageLogging under the diagnostics node as follows:

…
<configuration>
<system.diagnostics>
  <sources>
   <source name="System.ServiceModel.MessageLogging" switchValue="Warning, ActivityTracing">
    <listeners>
     <add type="System.Diagnostics.DefaultTraceListener" name="Default">
      <filter type="" />
     </add>
     <add name="ServiceModelMessageLoggingListener">
      <filter type="" />
     </add>
    </listeners>
   </source>
  </sources>
  <sharedListeners>
   <add initializeData="c:\inetpub\wwwroot\WCFService\web_messages.svclog"
    type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
    name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp">
    <filter type="" />
   </add> 
  </sharedListeners>
</system.diagnostics>
</configuration>
…
…
<system.serviceModel>
  <diagnostics>
   <messageLogging logEntireMessage="false" logMalformedMessages="true"
    logMessagesAtServiceLevel="false" logMessagesAtTransportLevel="true" />
  </diagnostics>
…

Additional Resources

How do I stop my service if there has been an auditing failure?

If non-repudiation is more important to you than ensuring that your service is always running and providing service, you can set the SuppressAuditFailure element to false to throw an exception when there has been an auditing failure. By default, this property is set to true, which means your service can continue running even after auditing has failed and no additional events are being logged.

The following configuration code shows how to stop the service if there is an audit failure:

<configuration>
  <system.serviceModel>
    <behaviors>
      <behavior>
        <serviceSecurityAudit
                  auditLogLocation="Application"
                  suppressAuditFailure="false"
                  serviceAuthorizationAuditLevel="Failure"
                  messageAuthenticationAuditLevel="SuccessOrFailure" /> 
      </behavior>
    </behaviors>
  </system.serviceModel>
</configuration>

You can also shut down the Windows system immediately when there is a failure to audit events by enabling the following Windows Local Security Setting property:

Audit: Shut down system immediately if unable to log security audits

To set the property, open Control Panel and then under Administrative Tools, open the Local Security Settings dialog box. Click Local Policies and then click Security Options to find the above property.

Additional Resources

How do I log important business events in WCF?

You can use ASP.NET health monitoring to log sensitive operations. For instance, you could track usage of methods that relate to financial transactions or access to sensitive data.

To instrument your application with health monitoring

  1. Create a class library and a class that inherits from WebSuccessAuditEvent that displays some business information, such as bank account transactions.

    using System.Web.Management;
    
     public class MyAccountTransactions : WebSuccessAuditEvent
        {
    
            public MyAccountTransactions(string msg, object eventSource, int eventCode)
                : base(msg, eventSource, eventCode)
            {
    // Do some processing
            }
    
            public MyAccountTransactions(string msg, object eventSource, int eventCode, int eventDetailCode)
                : base(msg, eventSource, eventCode, eventDetailCode)
            {
    // Do some processing
            }
       public override void FormatCustomEventDetails(WebEventFormatter formatter)
            {
                base.FormatCustomEventDetails(formatter);
    
                // Display some transaction information
                formatter.AppendLine("Some Credit\Debit information");
    }
    
  2. Configure your WCF service for health monitoring.

    …
    <system.web>
    <healthMonitoring>
    <eventMappings>
    <add name="SomeTransactionInfo" type="MyEventLibrary.MyAccountTransactions, MyEventLibrary"/>
    </eventMappings>
    <rules>
    <add name="Custom event" eventName="SomeTransactionInfo" provider="EventLogProvider" minInterval="00:00:01"/>
    </rules>
    </healthMonitoring>
    </system.web>
    …
    
  3. Instrument the WCF service by raising the custom event in a service contract.

    public string InvokeBusinessEvent()
        {
            MyAccountTransactions obj = new MyAccountTransactions("Invoking some business operation", this, WebEventCodes.WebExtendedBase + 1);
            obj.Raise();
            return "Displaying some transaction details";
        }
    
  4. Verify the service events in the Event Log after calling the service method from a test client.

Additional Resources

How do I implement log throttling in WCF?

If you are using WCF message logging, you can specify the maximum number of messages to log as well as the maximum size of the messages to be logged. These attributes can be found in the <messagelogging> element:

  • maxMessagesToLog. Allows you to limit the size of the log file, by reducing the total number of messages in the log. This setting can be used to reduce the chances of a denial of service (DoS) attack on your log but can be used by an attacker to fill up the log and conceal their intrusion.
  • maxSizeOfMessagesToLog. Allows you to limit the size of the log file, by restricting very large messages from being logged. This setting can be used to reduce the chances of a DoS attack on your log but could potentially be used by an attacker to conceal their intrusion by ensuring that certain messages are not logged.

When the message limit is reached, a trace at the Information level is produced, and all message logging activities stop.

Additional Resources

How do I use the health monitoring feature with WCF?

To use the health monitoring feature with WCF, configure your WCF service by performing the following steps:

  1. Create a custom health monitoring event.
  2. Configure your WCF service for health monitoring.
  3. Instrument an application to raise a custom event.

The following example shows how to implement the above steps for health monitoring in a WCF service:

  1. Create a custom user management Web event, by creating a class library and then creating a class that inherits from WebAuditEvent.

    using System.Web.Management;
    
     public class MyEvent : WebAuditEvent
     {
            public MyEvent(string msg, object eventSource, int eventCode)
                : base(msg, eventSource, eventCode)
            {
            }
    
            public MyEvent(string msg, object eventSource, int eventCode, int eventDetailCode)
                : base(msg, eventSource, eventCode, eventDetailCode)
            {
            }
        public override void FormatCustomEventDetails(WebEventFormatter formatter)
            {
                base.FormatCustomEventDetails(formatter);
    
                // Display some custom event message
                formatter.AppendLine("Some Critical Event Fired");
      }
    }
    
  2. Configure your WCF service for health monitoring.

    …
    <system.web>
    <healthMonitoring>
    <eventMappings>
    <add name="Some Custom Event" type="MyEventLibrary.MyEvent, MyEventLibrary"/>
    </eventMappings>
    <rules>
    <add name="Custom event" eventName="Some Custom Event" provider="EventLogProvider" minInterval="00:00:01"/>
    </rules>
    </healthMonitoring>
    </system.web>
    …
    
  3. Instrument the WCF service by raising the custom event in a service contract.

    [OperationContract]
    string InvokeCriticalEvent();
    
    public string InvokeCriticalEvent()
        {
            MyEvent obj = new MyEvent("Invoking Some Custom Event", this, WebEventCodes.WebExtendedBase + 1);
            obj.Raise();
            return "Critical event invoked";
        }
    
  4. Verify the service events in the Event Log after calling the service method from a test client.

Additional Resources

How do I protect my log files?

Protect your log files using Microsoft Windows® access control lists (ACLs) with restricted access. If you log events to Microsoft SQL Server® or to a custom event sink, use appropriate access controls to limit access to the event data. For example, grant write access to the account or accounts used by your application, grant full control to administrators, and grant read-only access to operators.

How to I pass user identity information in a message for auditing purpose?

You might want to pass user identity information in a message in cases where you are not impersonating the caller. This could be useful when auditing business-critical operations such as financial transactions.

To pass user identity information in a custom event for auditing

  1. Create a custom user management Web event, by creating a class library and then creating a class that inherits from WebAuditEvent.

    using System.Web.Management;
    
     public class MyEvent : WebAuditEvent
        {
    
            public MyEvent(string msg, object eventSource, int eventCode)
                : base(msg, eventSource, eventCode)
            {
      // Obtain the HTTP Context and store authentication details
    
      userID = HttpContext.Current.User.Identity.Name;
            authType = HttpContext.Current.User.Identity.AuthenticationType;
            isAuthenticated = HttpContext.Current.User.Identity.IsAuthenticated;
            }
    
            public MyEvent(string msg, object eventSource, int eventCode, int eventDetailCode)
                : base(msg, eventSource, eventCode, eventDetailCode)
            {
      // Obtain the HTTP Context and store authentication details
    
      userID = HttpContext.Current.User.Identity.Name;
            authType = HttpContext.Current.User.Identity.AuthenticationType;
            isAuthenticated = HttpContext.Current.User.Identity.IsAuthenticated;
            }
       public override void FormatCustomEventDetails(WebEventFormatter formatter)
            {
                base.FormatCustomEventDetails(formatter);
    
                // Display user identity information in the event message
    formatter.AppendLine("User ID: " + userID);
    formatter.AppendLine("Authentication Type: " + authType);
    formatter.AppendLine("User Authenticated: " + isAuthenticated.ToString());
    }
    
  2. Configure your WCF service for health monitoring.

    …
    <system.web>
    <healthMonitoring>
    <eventMappings>
    <add name="Some Custom Event" type="MyEventLibrary.MyEvent, MyEventLibrary"/>
    </eventMappings>
    <rules>
    <add name="Custom event" eventName="Some Custom Event" provider="EventLogProvider" minInterval="00:00:01"/>
    </rules>
    </healthMonitoring>
    </system.web>
    …
    
  3. Instrument the WCF service by raising the custom event in a service contract.

    [OperationContract]
    string InvokeEvent();
    
    public string InvokeEvent()
        {
            MyEvent obj = new MyEvent("Invoking Custom Event — User Info", this, WebEventCodes.WebExtendedBase + 1);
            obj.Raise();
            return "Event showing User information";
        }
    
  4. Verify the service events in the Event Log after calling the service method from a test client.

    Event code: 100001
    Event message: Invoking Custom Event — User Info
    …
    Application information:
        Application domain: /LM/w3svc/1/ROOT/HealthMonitoring-7-127656015969887178
    …
    Custom event details:     
    User ID: DomainName\UserName
        Authentication Type: Negotiate
        User Authenticated: True
    

Additional Resources