DCSIMG
August 2009 - Posts - Manu Cohen-Yashar's Blog

Manu Cohen-Yashar's Blog

August 2009 - Posts

The Live Framework CTP is going down

If you haven't heard already : As of September 8th, the Live Framework CTP will be unavailable. For more details see the live framework home page

Hope it will be up soon…

Manu

Flat WSDL for WCF services

In my last post I motioned that working with more than one XML namespace will cause problems when a flat WSDL is a requirement. I was asked many questions about flat WSDL so I would like to explain here about creating flat WSDL for WCF services.

As you have all seen the WSDL created by WCF is very different than the WSDL asmx web services used to expose. The content is similar but the structure is different. WCF uses references to other links (for example the XSDs are found using the reference : <xsd:import schemaLocation="http://localhost:8080/?xsd=xsd0 ...

There are systems that fail to read this WSDL and that create an interoperability problem.

To make WCF expose the WSDL in a asmx like form or in other words in a flat manner – no references etc , a special endpoint behavior should be used.

Here is the code of the FlatWSDL endpointBehavior:

namespace FlatWSDL

{

    public class FlatWsdlBefavior : BehaviorExtensionElement,

        IWsdlExportExtension, IEndpointBehavior

    {

        public void ExportContract(WsdlExporter exporter,

            WsdlContractConversionContext context)

        {

        }

 

        public void ExportEndpoint(WsdlExporter exporter,

            WsdlEndpointConversionContext context)

        {

            XmlSchemaSet schemaSet = exporter.GeneratedXmlSchemas;

 

            foreach (System.Web.Services.Description.ServiceDescription wsdl

                in exporter.GeneratedWsdlDocuments)

            {

                List<XmlSchema> importsList =

                                new List<XmlSchema>();

 

                foreach (XmlSchema schema in wsdl.Types.Schemas)

                {

                    AddImportedSchemas(schema,

                                       schemaSet, importsList);

                }

 

                wsdl.Types.Schemas.Clear();

 

                foreach (XmlSchema schema in importsList)

                {

                    RemoveXsdImports(schema);

                    wsdl.Types.Schemas.Add(schema);

                }

            }

        }

 

        private void AddImportedSchemas(XmlSchema schema,

            XmlSchemaSet schemaSet, List<XmlSchema> importsList)

        {

            foreach (XmlSchemaImport import in schema.Includes)

            {

                ICollection realSchemas =

                    schemaSet.Schemas(import.Namespace);

 

                foreach (XmlSchema ixsd in realSchemas)

                {

                    if (!importsList.Contains(ixsd))

                    {

                        importsList.Add(ixsd);

                        AddImportedSchemas(ixsd,

                            schemaSet,

                            importsList);

                    }

                }

            }

        }

 

        private void RemoveXsdImports(XmlSchema schema)

        {

            for (int i = 0; i < schema.Includes.Count; i++)

            {

                if (schema.Includes[i] is XmlSchemaImport)

                    schema.Includes.RemoveAt(i--);

            }

        }

 

        public void AddBindingParameters(ServiceEndpoint endpoint,

            BindingParameterCollection bindingParameters)

        {

        }

 

        public void ApplyClientBehavior(ServiceEndpoint endpoint,

            ClientRuntime clientRuntime)

        {

        }

 

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint,

            EndpointDispatcher endpointDispatcher)

        {

        }

 

        public void Validate(ServiceEndpoint endpoint)

        {

        }

 

        //To enable using configuration extention to use this behavior

        public override Type BehaviorType

        {

            get { return this.GetType(); }

        }

 

        //To enable using configuration extention to use this behavior

        protected override object CreateBehavior()

        {

            return new FlatWsdlBefavior();

        }

    }

}

Here is the service I will use to demonstrate the behavior

 

[ServiceContract(Namespace="http://manu.com")]

    public interface ICalc

    {

        [OperationContract]

        int Add(int a, int b);

        [OperationContract]

        int Sub(int a, int b);

        [OperationContract]

        int Mul(int a, int b);

        [OperationContract]

        int Div(int a, int b);

    }

 

[ServiceBehavior(Namespace="http://manu.com")]

    public class Calc : ICalc

    {

        #region ICalc Members

 

        public int Add(int a, int b)

        {

            return a+b;

        }

 

        public int Sub(int a, int b)

        {

            return a - b;

        }

 

        public int Mul(int a, int b)

        {

            return a * b;

        }

 

        public int Div(int a, int b)

        {

            return a / b;

        }

 

        #endregion

    }

To use this behavior I will a wcf configuration extension.

This behavior derive from BehaviorExtensionElement So I can create an extension in my configuration file and use it in config:

 

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

  <system.serviceModel>

    <extensions>

       <behaviorExtensions>

          <add name="FlatWSDL" type="FlatWSDL.FlatWsdlBefavior, FlatWSDL, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>

       </behaviorExtensions>

    </extensions>

    <behaviors>

      <serviceBehaviors>

        <behavior name="ShowMetadata">

          <serviceMetadata  httpGetEnabled="true"/>

        </behavior>

      </serviceBehaviors>

      <endpointBehaviors>

        <behavior name="ExposeFlatWSDL">

          <FlatWSDL/>

        </behavior>

      </endpointBehaviors>

    </behaviors>

 

    <services>

      <service name="FlatWSDL.Calc"

              behaviorConfiguration="ShowMetadata">

        <host>

          <baseAddresses>

            <add baseAddress="http://localhost:8080"/>

          </baseAddresses>

        </host>

        <endpoint address="Calc"

                  binding="basicHttpBinding"

                  contract="FlatWSDL.ICalc"

                  behaviorConfiguration="ExposeFlatWSDL">         

        </endpoint>

      </service>

    </services>

  </system.serviceModel>

</configuration>

Look at the the Extension element in the top of the config file. As you can see I have to use the full qualified name of the assembly. It just does not work otherwise. (known bug…)

Now I will open the host, load the service and look at its WSDL and here is the results:

<?xml version="1.0" encoding="utf-8" ?>
- <wsdl:definitions name="Calc" targetNamespace="http://manu.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsam="http://www.w3.org/2007/05/addressing/metadata" xmlns:tns="http://manu.com" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:i0="http://tempuri.org/" xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa10="http://www.w3.org/2005/08/addressing" xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex">
  <wsdl:import namespace="http://tempuri.org/" location="http://localhost:8080/?wsdl=wsdl0" />
- <wsdl:types>
- <xsd:schema elementFormDefault="qualified" targetNamespace="http://manu.com">
- <xsd:element name="Add">
- <xsd:complexType>
- <xsd:sequence>
  <xsd:element minOccurs="0" name="a" type="xsd:int" />
  <xsd:element minOccurs="0" name="b" type="xsd:int" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
- <xsd:element name="AddResponse">
- <xsd:complexType>
- <xsd:sequence>
  <xsd:element minOccurs="0" name="AddResult" type="xsd:int" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
- <xsd:element name="Sub">
- <xsd:complexType>
- <xsd:sequence>
  <xsd:element minOccurs="0" name="a" type="xsd:int" />
  <xsd:element minOccurs="0" name="b" type="xsd:int" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
- <xsd:element name="SubResponse">
- <xsd:complexType>
- <xsd:sequence>
  <xsd:element minOccurs="0" name="SubResult" type="xsd:int" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
- <xsd:element name="Mul">
- <xsd:complexType>
- <xsd:sequence>
  <xsd:element minOccurs="0" name="a" type="xsd:int" />
  <xsd:element minOccurs="0" name="b" type="xsd:int" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
- <xsd:element name="MulResponse">
- <xsd:complexType>
- <xsd:sequence>
  <xsd:element minOccurs="0" name="MulResult" type="xsd:int" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
- <xsd:element name="Div">
- <xsd:complexType>
- <xsd:sequence>
  <xsd:element minOccurs="0" name="a" type="xsd:int" />
  <xsd:element minOccurs="0" name="b" type="xsd:int" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
- <xsd:element name="DivResponse">
- <xsd:complexType>
- <xsd:sequence>
  <xsd:element minOccurs="0" name="DivResult" type="xsd:int" />
  </xsd:sequence>
  </xsd:complexType>
  </xsd:element>
  </xsd:schema>
- <xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://schemas.microsoft.com/2003/10/Serialization/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://schemas.microsoft.com/2003/10/Serialization/">
  <xs:element name="anyType" nillable="true" type="xs:anyType" />
  <xs:element name="anyURI" nillable="true" type="xs:anyURI" />
  <xs:element name="base64Binary" nillable="true" type="xs:base64Binary" />
  <xs:element name="boolean" nillable="true" type="xs:boolean" />
  <xs:element name="byte" nillable="true" type="xs:byte" />
  <xs:element name="dateTime" nillable="true" type="xs:dateTime" />
  <xs:element name="decimal" nillable="true" type="xs:decimal" />
  <xs:element name="double" nillable="true" type="xs:double" />
  <xs:element name="float" nillable="true" type="xs:float" />
  <xs:element name="int" nillable="true" type="xs:int" />
  <xs:element name="long" nillable="true" type="xs:long" />
  <xs:element name="QName" nillable="true" type="xs:QName" />
  <xs:element name="short" nillable="true" type="xs:short" />
  <xs:element name="string" nillable="true" type="xs:string" />
  <xs:element name="unsignedByte" nillable="true" type="xs:unsignedByte" />
  <xs:element name="unsignedInt" nillable="true" type="xs:unsignedInt" />
  <xs:element name="unsignedLong" nillable="true" type="xs:unsignedLong" />
  <xs:element name="unsignedShort" nillable="true" type="xs:unsignedShort" />
  <xs:element name="char" nillable="true" type="tns:char" />
- <xs:simpleType name="char">
  <xs:restriction base="xs:int" />
  </xs:simpleType>
  <xs:element name="duration" nillable="true" type="tns:duration" />
- <xs:simpleType name="duration">
- <xs:restriction base="xs:duration">
  <xs:pattern value="\-?P(\d*D)?(T(\d*H)?(\d*M)?(\d*(\.\d*)?S)?)?" />
  <xs:minInclusive value="-P10675199DT2H48M5.4775808S" />
  <xs:maxInclusive value="P10675199DT2H48M5.4775807S" />
  </xs:restriction>
  </xs:simpleType>
  <xs:element name="guid" nillable="true" type="tns:guid" />
- <xs:simpleType name="guid">
- <xs:restriction base="xs:string">
  <xs:pattern value="[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}" />
  </xs:restriction>
  </xs:simpleType>
  <xs:attribute name="FactoryType" type="xs:QName" />
  <xs:attribute name="Id" type="xs:ID" />
  <xs:attribute name="Ref" type="xs:IDREF" />
  </xs:schema>
  </wsdl:types>
- <wsdl:message name="ICalc_Add_InputMessage">
  <wsdl:part name="parameters" element="tns:Add" />
  </wsdl:message>
- <wsdl:message name="ICalc_Add_OutputMessage">
  <wsdl:part name="parameters" element="tns:AddResponse" />
  </wsdl:message>
- <wsdl:message name="ICalc_Sub_InputMessage">
  <wsdl:part name="parameters" element="tns:Sub" />
  </wsdl:message>
- <wsdl:message name="ICalc_Sub_OutputMessage">
  <wsdl:part name="parameters" element="tns:SubResponse" />
  </wsdl:message>
- <wsdl:message name="ICalc_Mul_InputMessage">
  <wsdl:part name="parameters" element="tns:Mul" />
  </wsdl:message>
- <wsdl:message name="ICalc_Mul_OutputMessage">
  <wsdl:part name="parameters" element="tns:MulResponse" />
  </wsdl:message>
- <wsdl:message name="ICalc_Div_InputMessage">
  <wsdl:part name="parameters" element="tns:Div" />
  </wsdl:message>
- <wsdl:message name="ICalc_Div_OutputMessage">
  <wsdl:part name="parameters" element="tns:DivResponse" />
  </wsdl:message>
- <wsdl:portType name="ICalc">
- <wsdl:operation name="Add">
  <wsdl:input wsaw:Action="http://manu.com/ICalc/Add" message="tns:ICalc_Add_InputMessage" />
  <wsdl:output wsaw:Action="http://manu.com/ICalc/AddResponse" message="tns:ICalc_Add_OutputMessage" />
  </wsdl:operation>
- <wsdl:operation name="Sub">
  <wsdl:input wsaw:Action="http://manu.com/ICalc/Sub" message="tns:ICalc_Sub_InputMessage" />
  <wsdl:output wsaw:Action="http://manu.com/ICalc/SubResponse" message="tns:ICalc_Sub_OutputMessage" />
  </wsdl:operation>
- <wsdl:operation name="Mul">
  <wsdl:input wsaw:Action="http://manu.com/ICalc/Mul" message="tns:ICalc_Mul_InputMessage" />
  <wsdl:output wsaw:Action="http://manu.com/ICalc/MulResponse" message="tns:ICalc_Mul_OutputMessage" />
  </wsdl:operation>
- <wsdl:operation name="Div">
  <wsdl:input wsaw:Action="http://manu.com/ICalc/Div" message="tns:ICalc_Div_InputMessage" />
  <wsdl:output wsaw:Action="http://manu.com/ICalc/DivResponse" message="tns:ICalc_Div_OutputMessage" />
  </wsdl:operation>
  </wsdl:portType>
- <wsdl:service name="Calc">
- <wsdl:port name="BasicHttpBinding_ICalc" binding="i0:BasicHttpBinding_ICalc">
  <soap:address location="http://localhost:8080/Calc" />
  </wsdl:port>
  </wsdl:service>
  </wsdl:definitions>

The WSDL is flat !!!!

One last note

The XML nampsaces on the service contract and the service implementation must match. The problem is that the service implementation support only one XML namespaces so overloading (see last post) and flat WSDL are not possible together.

Manu

WCF services and Xml namespaces or How to implement overloading

 

It is trivial that a service can implement many different contracts at the same time and exposing an endpoint per contract. Simple and easy.

 

   [ServiceContract]

    public interface IAdd

    {

        [OperationContract]

        int add(int a, int b) ;

    }

 

    [ServiceContract]   

    public interface ISub

    {

        [OperationContract]

        int sub(int a, int b);

    }

 

 

    class Calc : IAdd, ISub

    {

        ...

    }

 

<services>

  <service name="WCF_XmlNamespace.Calc">

    <endpoint address="Add"

  binding="basicHttpBinding"

  contract="WCF_XmlNamespace.IAdd"/>

    <endpoint address="Sub"

  binding="basicHttpBinding"

  contract="WCF_XmlNamespace.ISub"/>

  </service>

</services>

The problem starts when we need the same function name in both contracts (i.e. Add)

What we actually need is overloading but as we know overloading is not supported for service contracts.

This might happen when we have a service for several customers and each customer wants the same method to have a different signature and to do something different.

We do not want to build the service per customer so we start with using C# namespaces.

 

namespace Special

{

    [ServiceContract]   

    public interface IAdd

    {

        [OperationContract]

        int Add(int a, int b, int c);

    }

}

 

 

namespace WCF_XmlNamespace

{

    [ServiceContract]

    public interface IAdd

    {

        [OperationContract]

        int Add(int a, int b) ;

    }

 

 

    class Calc : IAdd, Special.IAdd

    {

 

        #region IAdd Members

 

        public int Add(int a, int b)

        {

            return (a + b);

        }

 

        #endregion

 

        #region Special.IAdd Members

 

        int Special.IAdd.Add(int a, int b, int c)

        {

            return (a + b + c);

        }

 

        #endregion

    }

}

   

   <services>

      <service name="WCF_XmlNamespace.Calc">

        <endpoint address="Add"

                  binding="basicHttpBinding"

                  contract="WCF_XmlNamespace.IAdd"/>

        <endpoint address="SpecialAdd"

                  binding="basicHttpBinding"

                  contract="Special.IAdd"/>

      </service>

    </services>

This compiles of course but when we run it we get the following exception:

"The Service contains multiple ServiceEndpoints with different ContractDescriptions which each have Name='IAdd' and Namespace='http://tempuri.org/'.  Either provide ContractDescriptions with unique Name and Namespaces, or ensure the ServiceEndpoints have the same ContractDescription instance."

 

In simple words C# namespaces solved the naming problem as far as compilation was concerned but WCF does not care about C# namespaces.  A WCF service will accept a soap message with the action "Add" .It does not have any way of distinguishing between the two implementations. Remember that overloading i.e. taking the signature into account is not supported.

To solve the naming problem for the service we must introduce XML namespaces for the contracts.

 

namespace Special

{

    [ServiceContract(Namespace="http://special.com")]

    public interface IAdd

    {

        [OperationContract]

        int Add(int a, int b, int c);

    }

}

 

 

namespace WCF_XmlNamespace

{

    [ServiceContract(Namespace="http://normal.com")]

    public interface IAdd

    {

        [OperationContract]

        int Add(int a, int b) ;

    }

 

 

    class Calc : IAdd, Special.IAdd

    {

 

        #region IAdd Members

 

        public int Add(int a, int b)

        {

            return (a + b);

        }

 

        #endregion

 

        #region Special.IAdd Members

 

        int Special.IAdd.Add(int a, int b, int c)

        {

            return (a + b + c);

        }

 

        #endregion

    }

Now it works.

The conclusions is that XML namespaces enables us to solve naming problems in the services XML world exactly like C# namespaces do in the C# programming world.

 

A final word. If we want no trace of the http://tempuri XML namespace in the WSDL or we want to create a flat WSDL like with old ASMX web services we need the service implementation to agree about the XML namespace with the service contract. We do that with a service behavior.

 

    [ServiceBehavior(Namespace = "http://normal.com")]

    class Calc : IAdd, Special.IAdd

    {

The problem is that the service can have only one XML namespace and if we have two contracts with each having its own XML namespace we have a problem…

Practical Application Security

Application Security is a problematic subject.

It is a non functional requirement so it cannot be presented to a customer and it is expensive. The management feels that money is being spent without tangible results and the developers feel that security is a pain so they will do anything to avoid it.

When being asked "what is application security?" so many different answers are given …

So how can application security be implemented? In this article I will show how the broad concept of application security can be translated into simple tangible tasks.

Application security requires design. If it is being considered at the early stages of the product life cycle it can be implemented without outstanding costs. If only realistic threats will be mitigated it the security spending can be reasonable.

Still the question "what is application security?" remains. The question "what exactly should be implemented?" remains open.

To help the practical implementation application security was divided into 10 major chapters.

Input validation

Most attacks we know today and many future attacks begin with malicious input.

In this category we will find all the injection attacks, buffer overflow attacks, some DOS attacks and many more.

Simple input validation would prevent the attack. Simple measures can prevent huge threats.

There are two types of validation white box and black box. White box means that there is a known pattern to the input. Anything outside of the pattern is considered malicious. This is a very effective method of validation as the pattern can be easily checked. Black box is less effective but more frequent. Here there is no pattern. All there is, is a known list of attacks. If the input looks like a known attack it is rejected everything else is allowed. It is obvious why this method is less effective. It is impossible to filter tomorrow's attacks and even known attacks are very difficult to identify.

When possible: Data should be designed to have a pattern as validation is much stronger.

In client server applications validation can be done on the server and on the client.

Client side validation should never be considered as a security measure. Its only purpose is to help the user. An attacker can easily bypass client side validation.

Security validation must be done on the server and as early as possible.

There are many security tools like dynamic analyzers that actually check for non validated data flows in the system.

The rule is simple: when ever data is received from an untrusted source (i.e. user) it should be validated.

Authentication

Authentication means identification of entities.

Entities can be users but also devices and applications. There are different technologies of authentication for different types of entities.

Usually users have only username and passwords which are the weakest type of credentials. In a domain environment users are authenticated against an Active Directory. Outside the domain an identity management database should be established. Sometimes users have stronger credentials like a smartcard or biometrics. Governments often promise to distribute strong ID to their citizens but until that promise if fulfilled username and passwords will be used for the masses.

Application and devices uses X509 certificates created by a proper Certificate Authority. An enterprise can create its own CA and issue certificates to its servers and applications and devices. Certificates depend on the trust in the CA. the idea is simple: I trust the CA. You give me a token produced by the CA that says that you are who you are. Because I trust the CA I assume that your identity is real. Certificates also include a public key that can help transfer keys or validate a digital signature.

An application can use a third party to authenticate on its behalf. The application must of course trust the authentication provider. These authentication providers can authenticate users for many applications. The user will get a single sign on experience and the application will be released from the burden of managing identities.

Authorization

Authorization is the process of setting and enforcing the entity permissions.

There are many authorization technologies.

Operating systems create a token for the user after passing authentication. This token includes a list of SIDs (Security Identifier) for the identities and the groups the user belongs to. Every resource managed by the operating system has an Access Control List (figure1)
clip_image002

Figure – 1 Access Control List

When a user tries to access such resource its SIDs are compared against the Access control list to determine the access policy.

On a client server scenario applications depends on a token created by the application itself or a third party authenticator. This token includes the list of roles (groups) the entity belongs to. The application will use this data declaratively or imperatively to determine the access policy.

Another interesting authorization technology is claim based authorization. Here the token includes a list of claims which are actual information about the entity identity and resources it is allowed to consume. To access a resource an entity has to present a list of claims.

The token can include a long list of claims so the application can receive interesting information about the user from the token.

Configuration Management

The configuration holds sensitive information about the application. Connection strings that include credentials to the database are just an example.
Application use configuration files to store business policy (rule based systems), providers types, services address and configuration, throttling info and more.

Altering the configuration can change the behavior of the application or break it. Stealing configuration can create a serious security breach. The fact that the configuration files is put on the production servers does not mean it is secure. Administrators can be manipulated and other infrastructure security problems can open access to these sensitive files.

Configuration must be treated as highly sensitive information and thus it should be encrypted and the access to it must be logged.

Sensitive information:

What is sensitive information? To answer that question the application and the business must be examined. The usual developer does not have the right perspective about the business so he cannot answer the question alone. On the other hand the business people does not have the right perspective about the technical aspects of the application so they too cannot answer the question by themselves. Only deep consolidation between the two can create a list of sensitive information. Now a sensitive information policy can be enforced with the knowledge that nothing was left out.

Cryptography

One of the methods to protect data is cryptography. Today the cryptography research is well advanced and computers power still follow the moor low. This means that we have strong algorithms but the hackers have great tools and computing power.

Choosing the wrong algorithm can have disastrous results. To create new algorithms that cannot be broken by modern tools requires good mathematical knowledge and cryptography expertise which are not usually available to the average developer.

Sensitive information must be encrypted using well known and tested algorithms which are approved by distinguished institutions like the NSA.

The strength of cryptographic algorithms is a dynamic matter. What was impossible in terms of computing power few years ago is available at every house. The application should be able to upgrade the cryptography algorithm when necessary.

When speaking about encryption the first thing to think about is key management.

Data is encrypted with symmetric algorithms. Asymmetric algorithms are used for key exchange and digital signature but not for large data encryption. The one key that is used for encryption must be well protected. Protection using encryption does not solve the problem as you still remain with key to protect. Key protection must be done using well known key management infrastructures like DPAPI or TPM.

When speaking about integrity (approval that data source is the one expected and the data was not changed on the way) Digital signature is the technology to use. Digital signature is based on the fact that the public key of the source is used to check the signature at the destination. The destination must be sure that the public key it uses belongs to the source. One of the technologies to assure that is X.509 certificates. The certificate produced by a trusted certificate authority includes the public key. The trust in the CA supplies the assurance of the keys identity.

Parameter manipulations

Distributed applications send parameters between modules. If the parameters are changed by a man in the middle the application can hacked. There is a great example that demonstrates how a Ferrari can be bought on a price of one dollar. The trick was that the application uses the price written in the web form to actually create the debit. A hacker used an http proxy and changed this http web form field to the value of one dollar and mission was accomplished.

Sometimes web sites uses an index to present data. Some data is sensitive. The index is put as a URL parameter. Changing that parameter might reveal sensitive data.

Web forms are great example how parameters can be changed in the URL, cookies etc and surprising effects occur.

Sensitive parameters must be protected. One way of doing so is using digital signatures. Proper design would prevent sensitive actions do be executed as a result of the reception of unprotected parameters.

Exception management.

Some technologies use exceptions as the root for error handling. Exceptions are great for developers and administrators because they hold lots of information about the application and the problem that caused the exception. This advantage for the developer might be a huge problem for the user. A user does not understand the information included in the exception. It is totally irrelevant for him. The hacker on the other hand will find this information extremely practical to the design the next attack. If exceptions are exposed to the user they are available to the hacker. Building an effective attack requires a lot of internal information about the application. Exceptions are a great source for this info.

The hacker would make the application fail and throw exceptions from which he will learn about the application internals. The hacker can learn the schema of the database, different modules names, important file names etc. All these will help him to design the next attack.

Exceptions should be sanitized. The user should get a general error message with no internal technical information about application. The exception itself should be logged so administrators can read the log and understand what went wrong and maybe fix the problem.

Logging and auditing

When the application is being attacked measures have to be taken. The attack should be stopped, damage should be fixed and maybe the attacker can be caught.

The application and its administrators must understand that they are under attack.

To do that the application must distinguish between normality and abnormality.

The normal activities of the application should be logged and their normal pattern should be understood. When the events logged looks out of the pattern maybe we are in a situation of an attack. For example in a normal scenario we know that in average 5 users per minute register to the app. If the logging shows registration of 1000 users per minute it should look suspicious.

Maybe we are under a Denial Of Service attack.

To handle attack access to situations sensitive information must be logged and the logs must be protected. For example every access to sensitive database tables should be logged. It makes sense that hackers will try to access these resources. If the access is logged it can help to find the hacker and the security breach he used.

This is why hackers will try to attack the logs themselves and try to destroy them.

Summary

Application security is more than authentication and SSL there are a lot of issues to be taken into consideration.

When designing an application use this list of topics to create a security plan and make sure all of the above are properly handled in your application.

Choose the proper technology for each of the above issues.

Make this list available and understood by developers and testers to make sure it will implemented and tested consistently throughout the application.

When security which is an abstract term becomes a list of tangible tasks it becomes clear and practical.