Tuesday, November 25, 2008

Preventing DoS (Denial of Service) attacks on WCF services

WCF services are the most attractive target for hackers because even an unsophisticated hacker can bring down a server by repeatedly calling the WCF service. WCF uses mechanisms like Throttling and Quotas to prevent DoS attacks. Throttling allows you to "smooth" out the load on the server. WCF handles throttling through the ServiceThrottlingBehavior class. This represents a behavior that can be applied to a service.
The ServiceThrottlingBehaviour class contains three properties
  • MaxConcurrentCalls bounds the total number of simultaneous calls that we will process (default == 16). Each call corresponds to a Message received from the top of the server-side channel stack. If you set this high then you are saying that you have the resources to handle that many calls simultaneously. Increase this value if you want your service to be able to process a larger message load.
  • MaxConcurrentSessions bounds the total number of sessionful channels that we will accept (default == 10). When we hit this throttle then new channels will not be accepted/opened. Note that this throttle is effectively disabled for non-sessionful channels (such as default BasicHttpBinding).
  • MaxConcurrentInstances bounds the total number of instances created. This throttle provides added protection in the case that you have an instance lifetime that is not tied to a call or a session (in which case it would already be bounded by the other two throttles).
These properties can be applied either programmatically or by configuring the behavior in your web.config or app.config file.

<system.serviceModel>

<services>

<service behaviorConfiguration="TradeService.ExchangeService.ServiceBehavior" name="TradeService.ExchangeService.TradeService">

<endpoint binding="wsHttpBinding" contract="TradeService.ExchangeService.ITradeService"/>

service>

<service behaviorConfiguration="TradeServiceBehavior" name="TradeService">

<endpoint address="" binding="wsHttpBinding" contract="ITradeService">

<identity>

<dns value="localhost"/>

identity>

endpoint>

<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

service>

services>

<behaviors>

<serviceBehaviors>

<behavior name="TradeService.ExchangeService.ServiceBehavior">

<serviceMetadata httpGetEnabled="true"/>

<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="false" />

<serviceThrottling maxConcurrentCalls="16" maxConcurrentInstances="1000" maxConcurrentSessions="10"/>

behavior>

<behavior name="TradeServiceBehavior">

<serviceMetadata httpGetEnabled="true"/>

<serviceDebug includeExceptionDetailInFaults="false"/>

behavior>

serviceBehaviors>

behaviors>

system.serviceModel>


In the example given above I have set the maxConcurrentCalls to 16, maxConcurrentInstances to 1000 and maxConcurrenctSessions to 10.

Quotas can be used in situations where the client may force the server to allocate a significant amount of memory over what should be used. When a quota is exceeded a QuotaExceededException is thrown. Without Quotas a malicious message could attempt to access all available memory can create an OutOfMemoryException, or access all available stacks to cause a StackOverflowException.
By setting the maxRecievedMessageSize on the binding you can mitigate DoS attacks. This setting restricts the maximum messages size so that a client can’t send messages that are too large and flood the system.

<bindings>

<wsHttpBinding>

<binding name="WSHttpBinding_TradeService" closeTimeout="00:01:00"

openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"

bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"

maxBufferPoolSize="524288" maxReceivedMessageSize="65536"

messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"

allowCookies="false">

<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"

maxBytesPerRead="4096" maxNameTableCharCount="16384" />

<reliableSession ordered="true" inactivityTimeout="00:10:00"

enabled="false" />

<security mode="Message">

<transport clientCredentialType="Windows" proxyCredentialType="None"

realm="" />

<message clientCredentialType="Windows" negotiateServiceCredential="true"

algorithmSuite="Default" establishSecurityContext="true" />

security>

binding>

wsHttpBinding>

bindings>

Friday, November 21, 2008

Provider design pattern implementation in .NET

The provider design pattern allows developers to define a well-documented, easy-to-understand API, with complete control over the internals of what occurs when those APIs are called. The pattern itself is exceedingly simple and is given the name "provider" since it provides the functionality for an API. Defined, a provider is simply a contract between an API and the Business Logic/Data Abstraction Layer. The provider is the implementation of the API separate from the API itself.

In short the pattern allows the developers to create a pluggable abstraction layer. For example, Commerce Server supports a pluggable layer for its personalization system, requiring developers to write a component implementing OleDb; something only a handful of people truly can accomplish, or for that matter desire to accomplish. The difference with the provider pattern is that it is a simple and approachable pattern for abstracting the APIs themselves.

The provider pattern introduced in ASP.NET 2.0 is merely a set of rules dictating one way to build pluggable software. The process of creating a provider model involves the creation of 4 main classes.
  • Main data provider class: The abstract base class has all the abstract methods and properties required to implement the public API it supports. For example, the new ASP.NET 2.0 Membership feature defines an abstract base class, MembershipProvider. This class mirrors the methods and properties defined in the Membership API. The MembershipProvider derives from another base class, ProviderBase. ProviderBase is a class common to all providers. Developers create their own classes, derive from the MembershipProvider, and override methods and properties with their own implementation. This resulting class is known as the provider.
  • Data provider collection class: The data provider collection class is the portion of your implementation that takes care of provider configuration. Here you implement the behavior of your configuration elements for a list of providers.
  • Data provider configuration class: This class contains the logic to manage the configuration of your provider and to get user's parameters and pass them to your provider. Data providers work based on the configuration files of your applications.
  • Data provider manager class: This is a singleton class with the main purpose to initialize a concrete provider and load user configuration settings in memory. During initialization, you need to retrieve the configuration section for your data provider and check its correctness. Once an implementation of the feature provider class is created, it must be described in the configuration section. For a given feature, an unlimited number of providers may be defined. The appropriate provider is instantiated at run time from information defined in the configuration file. It is possible to change providers at run time too, allowing for a dynamic change between, say, a SQL Server provider and an Oracle provider.
The class diagram given below describes the components in the provider model and show the relationships between them.


[Click on the image to enlarge it]

As you can see I have created a sample provider model for Sql, Oracle data access.

Main Data provider implementation

public abstract class DataAccessProvider : ProviderBase

{

public abstract IDataReader ExecuteReader(string storedProcedureName, IDataParameterCollection dbParameterCollection);

public abstract IDataReader ExecuteReader(string sql);

public abstract void ExecuteNonQuery(string storedProcedureName, IDataParameterCollection dbParameterCollection);

public abstract void ExecuteNonQuery(string sql);

}

The Data Provider Collection implementation

public class DataAccessProviderCollection : ProviderCollection

{

new public DataAccessProvider this[string name]

{

get { return (DataAccessProvider)base[name]; }

}

}

The Data Provider Configuration implementation

public class DataAccessProviderConfiguration : ConfigurationSection

{

[ConfigurationProperty("providers")]

public ProviderSettingsCollection Providers

{

get

{

return (ProviderSettingsCollection)base["providers"];

}

}

[ConfigurationProperty("default", DefaultValue = "SqlDataAccessProvider")]

public string DefaultProviderName

{

get

{

return base["default"] as string;

}

}

}

The Data Provider Manager implementation

public class DataAccessProviderManager

{

static DataAccessProviderManager()

{

Initialize();

}

private static DataAccessProvider _default;

///

/// Returns the default configured data provider

///

public static DataAccessProvider Default

{

get { return _default; }

}

private static DataAccessProviderCollection _providerCollection;

///

/// .Returns the provider collection

///

public static DataAccessProviderCollection Providers

{

get { return _providerCollection; }

}

private static ProviderSettingsCollection _providerSettings;

public static ProviderSettingsCollection ProviderSettings

{

get { return _providerSettings; }

}

///

/// Reads the configuration related to the set of configured

/// providers and sets the default and collection of providers and settings.

///

private static void Initialize()

{

DataAccessProviderConfiguration configSection = (DataAccessProviderConfiguration)ConfigurationManager.GetSection("DataAccessProviderDataProvider");

if (configSection == null)

throw new ConfigurationErrorsException("Data provider section is not set.");

_providerCollection = new DataAccessProviderCollection();

ProvidersHelper.InstantiateProviders(configSection.Providers, _providerCollection, typeof(DataAccessProvider));

_providerSettings = configSection.Providers;

if (_providerCollection[configSection.DefaultProviderName] == null)

throw new ConfigurationErrorsException("Default data provider is not set.");

_default = _providerCollection[configSection.DefaultProviderName];

}

}

Now you can create concrete providers like

public class SqlDataAccessProvider : DataAccessProvider

{

public override void ExecuteNonQuery(string sql)

{

//Implement SQL based functionality here.

}

public override void ExecuteNonQuery(string storedProcedureName, IDataParameterCollection dbParameterCollection)

{

//Implement SQL based functionality here.

}

public override IDataReader ExecuteReader(string sql)

{

//Implement SQL based functionality here.

return null;

}

public override IDataReader ExecuteReader(string storedProcedureName, IDataParameterCollection dbParameterCollection)

{

//Implement SQL based functionality here.

return null;

}

}

You can use the Provider as

DataAccessProvider provider = DataAccessProviderManager.Default;

provider.ExecuteNonQuery(@"Update SampleTable set ColumnName = 'TEST' where Id = 1");


And finally the configuration file settings

<configuration>

<configSections>

<section name="DataAccessProviderDataProvider"

type="ProviderModel.DataAccessProvider.DataAccessProviderDataProviderConfiguration, ProviderModel" />

configSections>

<DataAccessProviderDataProvider default="SqlDataAccessProvider">

<providers>

<add name="SqlDataAccessProvider"

type="ProviderModel.DataAccessProvider.SqlDataAccessProvider, ProviderModel" />

providers>

DataAccessProviderDataProvider>

configuration>