Tuesday, 15 November 2011

Basics of WCF Security – Part 3

Series : Part-1  Part-2  Part-3
In last edition of Basics of WCF Security series, we discussed ProtectionLevel Security Setting in WCF. Today’s WCF corner is a continuation on the same topic. As usual, this article assumes that you have a fair understanding of basics of WCF and you have at least written or seen a simple WCF application in action.
In this article we will cover Impersonation/Delegation:
Impersonation is a common technique that services use to restrict client access to a service domain's resources. Service domain resources can either be machine resources, such as local files (impersonation), or a resource on another machine, such as a file share (delegation). In short, WCF services use Impersonation to assume the original caller’s identity in order to authorize access to service resources (such as files or database tables)
By default, impersonation is disabled and resources are accessed by using the WCF service’s process identity. You can enable impersonation either programmatically or by applying appropriate attributes at operation or service levels.
Impersonation can be done imperatively or declaratively. 
1.       Imperative impersonation is performed programmatically at run time and can vary depending on business logic or other conditions. 
2.       Declarative impersonation is applied with a static attribute that can be associated with an operation or an entire interface.
 In general, you should use imperative impersonation when you need the fine granularity made possible by writing the impersonation logic into your code. If you do not need such fine granularity, you can use declarative impersonation. 
Delegation allows you to use an impersonation token to access network resources. Your ability to use delegation depends on the authentication mechanism in use and appropriate account configuration.

Impersonation Methods

There are three methods used for impersonation: 

  • Impersonate the Original Caller Declaratively on Specific Operations

You can impersonate declaratively on an operation when you want to impersonate the original caller for the entire duration of a specific operation. Use impersonation selectively and only on the operations that need it, since by nature it increases the potential attack surface of your application. 
You can impersonate declaratively by applying the OperationBehavior attribute on any operation that requires client impersonation. The following example shows how to impersonate for a specific operation. 
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetData(int value)
{
   return “test”;
}
  • Impersonate the Original Caller Declaratively for the Entire Service

Impersonate declaratively on a service when you want to impersonate the original caller for all of the operations in your service. However, you should be careful with this option because it can significantly increase the attack surface of your application by running all of your code under a higher-privileged account. 
You can impersonate the entire service by applying the impersonateCallerForAllOperations attribute to "true" in the WCF configuration file. The following example shows how to impersonate for entire service: 
...
<behaviors>
  <serviceBehaviors>
    <behavior name="ServiceBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
      <serviceAuthorization impersonateCallerForAllOperations="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>
...

If you are impersonating all operations in the service, the Impersonation property of the OperationBehaviorAttribute applied to each operation will be overriden. Therefore if the property on the operation is set to something other than Allowed or Required, impersonation will be turned off for that operation.
Note: When a service has higher credentials than the remote client, the credentials of the service are used if the Impersonation property is set to Allowed. That is, if a low-privileged user provides its credentials, a higher-privileged service executes the method with the credentials of the service, and can use resources that the low-privileged user would otherwise not be able to use.
 
  • Impersonate the Original Caller Programmatically Within an Operation

Impersonate programmatically when you want to impersonate the original caller for a short duration in a service operation. You can impersonate programmatically by calling the Impersonate() method on the Windows identity that you want to impersonate, as follows:

public string GetData(int value)
{       
 using (ServiceSecurityContext.Current.WindowsIdentity.Impersonate())
 {
  // return the impersonated user (original users identity)
  return string.Format("Hi, {0}, you have entered: {1}",
  WindowsIdentity.GetCurrent().Name, value);
 }   
}

Note: It is important to revert to impersonation. Failure to do so can form the basis for denial of service (DoS) or elevation of privilege attacks. In the example above, the using statement ensures that the impersonation is reverted after execution of the using block.

Controlling Impersonation on the Service Side

You can control impersonation on the service side by using declarative impersonation. You can use the ImpersonationOption enumeration along with theOperationBehaviorAttribute attribute to control impersonation. The following impersonation options are available:
1.       NotAllowed – Impersonation is not performed in a particular operation.
2.       Allowed – Impersonation is performed if the original Windows token is available and the service is configured to impersonate on all operations using theImpersonateCallerForAllOperations in the ServiceAuthorizationBehavior attribute.
3.       Required – Impersonation is performed; the Windows identity token is required to be available.
The following example uses declarative impersonation to control impersonation on the service side:

[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetData(int value)
{
   return “test”;
}

Controlling Impersonation on the Client Side

You can control impersonation on the client side and prevent WCF services from using client identities to access local resources. Windows credentials have an AllowedImpersonationLevel property that is set to one of the following TokenImpersonationLevel options in order to control the impersonation level:
  1. None – The WCF service cannot authenticate or impersonate the user.
  2. Anonymous – The WCF service authenticates clients as anonymous, but cannot obtain information for identification or impersonation.
  3. Identification – The WCF service can authenticate clients and get information for identification, but cannot impersonate the clients. This is the default value.
  4. Impersonation – The WCF service can authenticate, get information for identification, and impersonate clients on local systems.
  5. Delegation – The WCF service can authenticate, get information for identification, and impersonate clients on local as well as remote systems.
The following example shows how to configure the impersonation level on the client side:
<behaviors>
    <endpointBehaviors>
        <behavior name="NewBehavior">
            <clientCredentials>
                <windows allowedImpersonationLevel="Impersonation" />
            </clientCredentials>
        </behavior>
    </endpointBehaviors>
</behaviors>

Note: The impersonation level obtained by the server when it impersonates the client token is not solely a function of this setting. It is also a function of the associated privileges and domain settings for the account in which the service is running.

To conclude:  Clients call a service to have the service perform some action on the client’s behalf and it allows the service to act as the client while performing the action. Both Impersonation and Delegation are powerful tools that one should use very cautiously and selectively. Improper use may result into security vulnerabilities.

Reference:

Friday, 14 October 2011

Basics of WCF Security – Part 2

Series : Part-1  Part-2  Part-3
In last Article of Basics of WCF Security series, we discussed Core Security Concepts, Transport and Message level security basics and started discussion about Security Settings in WCF.  As usual, this article assumes that you have a fair understanding of basics of WCF and you have at least written or seen a simple WCF application in action.
To refresh it, following is the list of available security settings in WCF
  • Security mode (covered in previous article)
  • Protection level
  • Client and service credentials
  • Impersonation
  • Credential negotiation
  • Secure sessions
  • Authentication and authorization behaviors
In this article we will cover ProtectionLevel :

Protection Levels
Following statements will help in understanding protection level feature of WCF.

1.    Three basic levels of protection exist for any part of a message

Mode
Description
None
Disables message protection.
Sign
Signs but does not encrypt the message
EncryptAndSign
Signs and encrypts the message.

2.    When the security mode is set to Transport, the entire message is protected by the transport mechanism. Therefore, setting a separate protection level for different parts of a message has no effect. All application data will be secured according to the capabilities of the transport.

3.    If you select a binding that enables security and you do not set the ProtectionLevel property anywhere on the contract, then default ProtectionLevel for that binding will be applied to all application data (table is given below for default ProtectionLevel for each WCF binding)

4.    If you are using Message security, you can configure message protection to sign but not encrypt each message. This allows you to verify the integrity of a message without the overhead of encryption in case there is no sensitive data requiring protection.

5.    The ProtectionLevel is a way for the developer to set the minimum level that a binding must comply with.

6.    If you set the ProtectionLevel explicitly to either Sign or EncryptAndSign, then you must use a binding with security enabled or an exception will be thrown.

7.    The ProtectionLevel can be set at different scoping levels. There is a hierarchy associated with scoping.

ProtectionLevel at various levels

When programming at the Service Model layer, ProtectionLevel can be set at various levels. The hierarchy is as follows. Attributes at the same level are peers
1.            ServiceContractAttribute level: all messages/faults of a service contract will have same protection level
2.            OperationContractAttribute level: An operation can override the protection level specified at the contract level. So messages/faults of an operation can have different protection requirements.
3.            MessageContractAttribute/FaultContractAttribute level: Individual messages/faults can also specify their own protection level, overriding the one specified at higher level.

How to: Set the ProtectionLevel Property

You can set the protection level by applying an appropriate attribute and setting the property. You can set protection at the service level to affect all parts of every message, or you can set protection at increasingly granular levels, from methods to message parts

     ' Set the ProtectionLevel on the whole service to Sign.
<ServiceContract(ProtectionLevel:=ProtectionLevel.Sign)> _
Public Interface ICalculator

     ' Set the ProtectionLevel on this operation to Sign.
    <OperationContract(ProtectionLevel:=ProtectionLevel.Sign)> _
    Function Add(ByVal a As Double, ByVal b As Double) As Double
End Interface

Public Interface ICalculator
    ' Set the ProtectionLevel on a FaultContractAttribute.
   <OperationContract(ProtectionLevel := ProtectionLevel.EncryptAndSign), _
FaultContract(GetType(MathFault), ProtectionLevel := ProtectionLevel.EncryptAndSign)>  _
Function Add(ByVal a As Double, ByVal b As Double) As Double

End Interface
Default ProtectionLevel for Standard Bindings

Binding
ProtectionLevel
BasicHttpBinding
 None
NetNamedPipeBinding
 EncryptAndSign
NetPeerTcpBinding
 None
NetTcpBinding
 EncryptAndSign
NetMsmqBinding
 Sign
WSDualHttpBinding
 EncryptAndSign
WSFederationHttpBinding
 EncryptAndSign
WSHttpBinding
 EncryptAndSign


Limitation
Protection levels can be set only in code, not in configuration.
If your requirement is to be able to set protection level from config file, then a simple option could be to access the description object model and update the contract protection level there before opening the service host or proxy.
ServiceHost svc = new ServiceHost(typeof(CalculatorService));
svc.Description.Endpoints[0].Contract.ProtectionLevel = GetProtectionLevelFromConfig();
If however, you want to set different protection level for different endpoints, then you have to do some more work.
Specifically you have to create an endpoint behavior, from which you will access the ChannelProtectionRequirements parameter to specify endpoint specific protection requirements. Here is step by step procedure to do this: http://fukyo-it.blogspot.com/2011/08/setting-protectionlevel-from-config.html

We will continue with the other WCF security settings in the next Article.

Reference:

Basics of WCF Security – Part 1

Series : Part-1  Part-2  Part-3

Getting started with WCF security
In WCF, messages are transmitted over a variety of supported protocols including IPC (named pipes), TCP, HTTP and MSMQ. So you must establish security policies for protecting messages and for authenticating and authorizing calls.
WCF security is a huge topic by itself, but we are sure with this article you will get a quick start of how to go about WCF security.


Core Security Concepts: There are four core security features that WCF addresses:-

  • Authentication: Process of identifying the message sender.
    • Mutual Authentication –a means for sender and receiver to identity one another, to prevent possible „man-in-the-middle‟ attacks.
  • Authorization: Determining the rights of the authenticated party. Like what features & functionality, an authenticated message senders, are entitled to execute.
  • Integrity: Messages should be digitally signed to ensure they have not been altered between sender and receiver.
  • Confidentiality: Sensitive messages or specific message parts should be encrypted to ensure they cannot be openly viewed on the wire.

Figure 1: - Core WCF Security Concepts



Transport and Message Level Security

There are two main aspects of WCF security, the first is the data and the second is the medium on which the data travels. The security which is applied at data level is called Message level security and the one which is applied at the protocol level is called Transport level security


Figure 2: - Transport and Message level security

Transport level security happens at the channel level. Transport level security is the easiest to implement as it happens at the communication level. WCF uses transport protocols like TCP, HTTP, MSMQ etc. and each of these protocols have their own security mechanisms. One of the common implementation of transport level security is HTTPS. HTTPS is implemented over HTTP protocols with SSL providing the security mechanism. No coding change is required; it‟s more of using the existing security mechanism provided by the protocol. Message level security is implemented with message data itself. Due to this, it is independent of the protocol. Some of the common ways of implementing message level security is by encrypting data using some standard encryption algorithm.


Figure 3: - Binding vs. Security levels
The above table shows for which binding what mode is supported. Mixed mode is the combination of transport and Message mode. For instance data encrypted and passed over WsHttp using HTTPS is a mixed mode of security. Encryption is using message security and HTTPS in the transport mode. In a combination they form mixed mode.


Security Settings in WCF

The below are some of the available security settings in Windows Communication Foundation (WCF)
  • Security mode (in this article, we‟ll discuss this part alone)
  • Protection level
  • Client and service credentials
  • Impersonation
  • Credential negotiation
  • Secure sessions
  • Authentication and authorization behaviors
The first step to securing a WCF service is defining the “Security Policy”. Once you have established requirements for Authentication, Authorization, and Message protection it is a matter of service configuration to enforce it. In WCF the binding selection process will influence/control the available configuration options for the “Service Security Policy”. Each binding has a default set of security settings defined.
For example: NetTcpBinding
  1. is secure, by default.
  2. Specifically, callers must provide “Windows credentials”, for authentication
  3. and all message packets are “Signed and Encrypted” over TCP protocol
Beyond Bindings, Behaviors also provide information about client and service credentials, and affect how authorization is handled.


Security Modes

Below are the 5 possible “Security Modes” across all “Service Bindings”.
  1. None - Turns security off.
  2. Transport - Uses “Transport security” for mutual authentication and message protection.
  3. Message - Uses “Message security” for mutual authentication and message protection.
  4. Both - Allows you to supply settings for transport and message-level security (only MSMQ supports this).
  5. TransportWithMessageCredential - Credentials are passed with the message and message protection and server authentication are provided by the transport layer.
  6. TransportCredentialOnly - Client credentials are passed with the transport layer and no message protection is applied.

Client Credential Type

It specifies the type of credential that the client must supply to communicate with your service. The choice of “clientCredentialType” depends on the “Security Mode” used.

Let us look at different modes of Transport & Message Client Credentials types:

Transport credential type


Setting
Description
None
Specifies that the client does not need to present any credential. This translates to an anonymous client.
Basic
Specifies basic authentication for the client.
Digest
Specifies digest authentication for the client.
Ntlm
Specifies NT LAN Manager (NTLM) authentication. This is used when you cannot use Kerberos authentication for some reason.
Windows
Specifies Windows authentication.
Certificate
Performs client authentication using an X.509 certificate.
Password
User must supply a user name and password. Validate the user name/password pair using Windows authentication or another custom solution.


Message Client Credential Types


Setting
Description
None
Specifies that the client does not need to present a credential. This translates to an anonymous client.
Windows
Allows SOAP message exchanges to occur under the security context established with a Windows credential.
Username
Allows the service to require that the client be authenticated with a user name credential.
Certificate
Allows the service to require that the client be authenticated using an X.509 certificate.
Issued Token
A custom token type configured according to a security policy. The default token type is Security Assertions Markup Language (SAML). The token is issued by a secure token service.

Note: The choice of “Credential Type” affects other Configuration settings for the service. For example, Username credential requires either a “Transport message” protection or “Service Certificate” to protect the exchange.

There‟s more about WCF security model. We will continue with some of the other WCF security settings in the next Article.


References
http://msdn.microsoft.com/en-us/library/ms731925.aspx
http://msdn.microsoft.com/en-us/library/ms733836.aspx