Chapter 12 – Building Secure Web Services

 

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

patterns & practices Developer Center

Improving Web Application Security: Threats and Countermeasures

J.D. Meier, Alex Mackman, Michael Dunner, Srinath Vasireddy, Ray Escamilla and Anandha Murukan
Microsoft Corporation

Published: June 2003

Last Revised: January 2006

Applies to:

  • Web Services (.NET Framework version 1.1)

See the "patterns & practices Security Guidance for Applications Index" for links to additional security resources.

See the Landing Page for the starting point and a complete overview of Improving Web Application Security: Threats and Countermeasures.

Summary: This chapter discusses practices and techniques to help you design and build secure Web services. It provides an overview of the main Web service threats together with appropriate countermeasures. Web Services Security (WS-Security) is the emerging security standard designed to address these threats. The chapter discusses how you can use Web Services Enhancements 2.0 for Microsoft .NET (WSE) with .NET Framework 1.1 to implement countermeasures based on WS-Security.

Note   Although WSE 2.0 SP3 is supported on .NET Framework 2.0, it is recommended that you use WSE 3.0 instead. For more information see "Web Services Enhancements (WSE)."

Important   WSE 2.0 is not wire-level compatible with WSE 3.0.

Contents

In This Chapter
Overview
How to Use This Chapter
Threats and Countermeasures
Design Considerations
Input Validation
Authentication
Authorization
Sensitive Data
Parameter Manipulation
Exception Management
Auditing and Logging
Proxy Considerations
Code Access Security Considerations
Deployment Considerations
Summary
Additional Resources

In This Chapter

  • Web service threats and countermeasures
  • Strategies for Web service input validation
  • Confidentiality and integrity for Web service messages
  • Web Services Enhancements 2.0 for Microsoft .NET (WSE) with .NET Framework 1.1

Overview

Web services are used by an increasing number of companies as they expose products and services to customers and business partners through the Internet and corporate extranets. The security requirements for these service providers are of paramount importance. In some cases, primarily intranet or extranet scenarios where you have a degree of control over both endpoints, the platform-based security services provided by the operating system and Internet Information Services (IIS) can be used to provide point-to-point security solutions. However, the message based architecture of Web services and the heterogeneous environments that span trust boundaries in which they are increasingly being used pose new challenges. These scenarios require security to be addressed at the message level to support cross-platform interoperability and routing through multiple intermediary nodes.

Web Services Security (WS-Security) is the emerging security standard designed to address these issues. Microsoft has released Web Services Enhancements (WSE) 2.0 for Microsoft .NET 1.1 and WSE 3.0 for .NET 2.0, which supports WS-Security and a related family of emerging standards. WSE allows you to implement message level security solutions including authentication, encryption and digital signatures.

Note   The specifications and standard supported by WSE are evolving and therefore the current WSE does not guarantee it will be compatible with future versions of the product. At the time of this writing, interoperability testing is under way with non-Microsoft toolkits provided by vendors including IBM and VeriSign.

How to Use This Chapter

This chapter discusses various practices and techniques to design and build secure Web services.

To get the most from this chapter:

  • Read Chapter 19, "Securing Your ASP.NET Application and Web Services." It is geared toward an administrator so that an administrator can configure an ASP.NET Web Application or Web service, bringing a semi-secure application to a secure state.
  • Read Chapter 17, "Securing Your Application Server." Read Chapter 17 to familiarize yourself with remote application server considerations.
  • Use the "Checklist: Securing Web Services" in the "Checklists" section of this guide. The checklist is a summary of the security measures required to build and configure secure Web services.
  • Use this chapter to understand message level threats and how to counter those threats.
  • Use the application categories as a means to tackle common problems. The sections give you relevant information using these categories.

Threats and Countermeasures

To build secure Web services, know the associated threats. The top threats directed at Web services are:

  • Unauthorized access
  • Parameter manipulation
  • Network eavesdropping
  • Disclosure of configuration data
  • Message replay

Figure 12.1 shows the top threats and attacks directed at Web services.

Ff648643.f12thcm01(en-us,PandP.10).gif

Figure 12.1

Main Web services threats

Unauthorized Access

Web services that provide sensitive or restricted information should authenticate and authorize their callers. Weak authentication and authorization can be exploited to gain unauthorized access to sensitive information and operations.

Vulnerabilities

Vulnerabilities that can lead to unauthorized access through a Web service include:

  • No authentication used
  • Passwords passed in plaintext in SOAP headers
  • Basic authentication used over an unencrypted communication channel

Countermeasures

You can use the following countermeasures to prevent unauthorized access:

  • Use password digests in SOAP headers for authentication.
  • Use Kerberos tickets in SOAP headers for authentication.
  • Use X.509 certificates in SOAP headers for authentication.
  • Use Windows authentication.
  • Use role-based authorization to restrict access to Web services. This can be done by using URL authorization to control access to the Web service file (.asmx) or at the Web method level by using principal-permission demands.

Parameter Manipulation

Parameter manipulation refers to the unauthorized modification of data sent between the Web service consumer and the Web service. For example, an attacker can intercept a Web service message, perhaps as it passes through an intermediate node en route to its destination; and can then modify it before sending it on to its intended endpoint.

Vulnerabilities

Vulnerabilities that can make parameter manipulation possible include:

  • Messages that are not digitally signed to provide tamperproofing
  • Messages that are not encrypted to provide privacy and tamperproofing

Countermeasures

You can use the following countermeasures to prevent parameter manipulation:

  • Digitally sign the message. The digital signature is used at the recipient end to verify that the message has not been tampered with while it was in transit.
  • Encrypt the message payload to provide privacy.

Network Eavesdropping

With network eavesdropping, an attacker is able to view Web service messages as they flow across the network. For example, an attacker can use network monitoring software to retrieve sensitive data contained in a SOAP message. This might include sensitive application level data or credential information.

Vulnerabilities

Vulnerabilities that can enable successful network eavesdropping include:

  • Credentials passed in plaintext in SOAP headers
  • No message level encryption used
  • No transport level encryption used

Countermeasures

You can use the following countermeasures to protect sensitive SOAP messages as they flow across the network:

  • Use transport level encryption such as SSL or IPSec. This is applicable only if you control both endpoints.
  • Encrypt the message payload to provide privacy. This approach works in scenarios where your message travels through intermediary nodes route to the final destination.

Disclosure of Configuration Data

There are two main ways in which a Web service can disclose configuration data. First, the Web service may support the dynamic generation of Web Service Description Language (WSDL) or it may provide WSDL information in downloadable files that are available on the Web server. This may not be desirable depending on your scenario.

Note   WSDL describes the characteristics of a Web service, for example, its method signatures and supported protocols.

Second, with inadequate exception handling the Web service may disclose sensitive internal implementation details useful to an attacker.

Vulnerabilities

Vulnerabilities that can lead to the disclosure of configuration data include:

  • Unrestricted WSDL files available for download from the Web server
  • A restricted Web service supports the dynamic generation of WSDL and allows unauthorized consumers to obtain Web service characteristics
  • Weak exception handling

Countermeasures

You can use the following countermeasures to prevent the unwanted disclosure of configuration data:

  • Authorize access to WSDL files using NTFS permissions.
  • Remove WSDL files from Web server.
  • Disable the documentation protocols to prevent the dynamic generation of WSDL.
  • Capture exceptions and throw a SoapException or SoapHeaderException — that returns only minimal and harmless information — back to the client.

Message Replay

Web service messages can potentially travel through multiple intermediate servers. With a message replay attack, an attacker captures and copies a message and replays it to the Web service impersonating the client. The message may or may not be modified.

Vulnerabilities

Vulnerabilities that can enable message replay include:

  • Messages are not encrypted
  • Messages are not digitally signed to prevent tampering
  • Duplicate messages are not detected because no unique message ID is used

Attacks

The most common types of message replay attacks include:

  • Basic replay attack. The attacker captures and copies a message, and then replays the same message and impersonates the client. This replay attack does not require the malicious user to know the contents of the message.
  • Man in the middle attack. The attacker captures the message and then changes some of its contents, for example, a shipping address, and then replays it to the Web service.

Countermeasures

You can use the following countermeasures to address the threat of message replay:

  • Use an encrypted communication channel, for example, SSL.

  • Encrypt the message payload to provide message. Although this does not prevent basic replay attacks, it does prevent man in the middle attacks where the message contents are modified before being replayed.

  • Use a unique message ID or nonce with each request to detect duplicates, and digitally sign the message to provide tamperproofing.

    Note   A nonce is a cryptographically unique value used for the request.

    When the server responds to the client it sends a unique ID and signs the message, including the ID. When the client makes another request, the client includes the ID with the message. The server ensures that the ID sent to the client in the previous message is included in the new request from the client. If it is different, the server rejects the request and assumes it is subject to a replay attack.

    The attacker cannot spoof the message ID, because the message is signed. Note that this only protects the server from client-initiated replay attacks using the message request, and offers the client no protection against replayed responses.

Design Considerations

Before you start to develop Web services, there are a number of issues to consider at design time. The key security considerations are:

  • Authentication requirements
  • Privacy and integrity requirements
  • Resource access identities
  • Code access security

Authentication Requirements

If your Web service provides sensitive or restrictive information, it needs to authenticate callers to support authorization. In Windows environments, you can use Windows authentication. However, where you are not in control of both endpoints, WSE provides authentication solutions that conform to the emerging WS-Security standard. WSE provides a standard framework for using SOAP headers to pass authentication details in the form of user names and passwords, Kerberos tickets, X.509 certificates, or custom tokens. For more information, see the "Authentication" section later in this chapter.

Privacy and Integrity Requirements

If you pass sensitive application data in Web service requests or response messages, consider how you can ensure that they remain private and unaltered while in transit. WSE provides integrity checking through digital signatures, and it also supports XML encryption to encrypt sensitive elements of the entire message payload. The advantage of this approach is that it is based on the emerging WS-Security standard and that it provides a solution for messages that pass through multiple intermediate nodes.

The alternative is to use transport level encryption through SSL or IPSec channels. These solutions are only appropriate where you are in control of both endpoints.

Resource Access Identities

By default, ASP.NET Web services do not impersonate, and the least privileged ASPNET process account is used for local and remote resource access. You can use this ASP.NET process account to access remote network resources such as SQL Servers that require Windows authentication, by creating a mirrored local account on the database server.

Note   On Windows Server 2003, the Network Service account is used by default to run Web services.

For more information about using the ASP.NET process account for remote database access, see the "Data Access" section in Chapter 19, "Securing Your ASP.NET Application and Web Services."

If you use impersonation, the issues and considerations that apply to Web applications also apply to Web services. For more information, see the "Impersonation" sections in Chapter 10, "Building Secure ASP.NET Web Pages and Controls" and Chapter 19, "Securing Your ASP.NET Application and Web Services."

Code Access Security

Consider the trust level defined by security policy in your target deployment environment. Your Web service's trust level, defined by its <trust> element configuration, affects the types of resources that it can access and the other privileged operations it can perform.

Also, if you call a Web service from an ASP.NET Web application, the Web application's trust level determines the range of Web services it can call. For example, a Web application configured for Medium trust, by default, can only call Web services on the local computer.

For more information about calling Web services from Medium and other partial trust Web applications, see Chapter 9, "Using Code Access Security with ASP.NET."

Input Validation

Like any application that accepts input data, Web services must validate the data that is passed to them to enforce business rules and to prevent potential security issues. Web methods marked with the WebMethod attribute are the Web service entry points. Web methods can accept strongly typed input parameters or loosely typed parameters that are often passed as string data. This is usually determined by the range and type of consumers for which the Web service is designed.

Strongly Typed Parameters

If you use strongly typed parameters that are described by the .NET Framework type system, for example integers, doubles, dates, or other custom object types such as Address or Employee, the auto-generated XML Schema Definition (XSD) schema contains a typed description of the data. Consumers can use this typed description to construct appropriately formatted XML within the SOAP requests that are sent to Web methods. ASP.NET then uses the System.Xml.Serialization.XmlSerializer class to deserialize the incoming SOAP message into common language runtime (CLR) objects. The following example shows a Web method that accepts strongly typed input consisting of built-in data types.

[WebMethod]
public void CreateEmployee(string name, int age, decimal salary) {...}

In the preceding example, the .NET Framework type system performs type checks automatically. To validate the range of characters that are supplied through the name field, you can use a regular expression. For example, the following code shows how to use the System.Text.RegularExpressions.Regex class to constrain the possible range of input characters and also to validate the parameter length.

if (!Regex.IsMatch(name, @"[a-zA-Z'.'-'\s]{1,40}"))
{
  // Invalid name
}

For more information about regular expressions, see the "Input Validation" section in Chapter 10, "Building Secure ASP.NET Pages and Controls." The following example shows a Web method that accepts a custom Employee data type.

using Employees;  // Custom namespace
[WebMethod]

public void CreateEmployee(Employee emp) { ... }

The consumer needs to know the XSD schema to be able to call your Web service. If the consumer is a .NET Framework client application, the consumer can simply pass an Employee object as follows:

using Employees;
Employee emp = new Employee();
// Populate Employee fields
// Send Employee to the Web service
wsProxy.CreateEmployee(emp);

Consumer applications that are not based on the .NET Framework must construct the XML input manually, based on the schema definition provided by the organization responsible for the Web service.

The benefit of this strong typing approach is that the .NET Framework parses the input data for you and validates it based on the type definition. However, inside the Web method you might still need to constrain the input data. For example, while the type system confirms a valid Employee object, you might still need to perform further validation on the Employee fields. You might need to validate that an employee's date of birth is greater than 18 years ago. You might need to use regular expressions to constrain the range of characters that can be used in name fields, and so on.

For more information about constraining input, see the "Input Validation" section in Chapter 10, "Building Secure ASP.NET Pages and Controls."

Loosely Typed Parameters

If you use string parameters or byte arrays to pass arbitrary data, you lose many of the benefits of the .NET Framework type system. You must parse the input data manually to validate it because the auto-generated WSDL simply describes the parameters as string input of type xsd:string. You need to programmatically check for type, length, format, and range as shown in the following example.

[WebMethod]
public void SomeEmployeeFunction(string dateofBirth, string SSN)
{
    . . .
  // EXAMPLE 1: Type check the date
  try
  {
    DateTime dt = DateTime.Parse(dateofBirth).Date;
  }
  // If the type conversion fails, a FormatException is thrown
  catch( FormatException ex )
  {
    // Invalid date
  }

  // EXAMPLE 2: Check social security number for length, format, and range
  if( !Regex.IsMatch(empSSN,@"\d{3}-\d{2}-\d{4}",RegexOptions.None))
  {
      // Invalid social security number
  }
}

XML Data

In a classic business-to-business scenario, it is common for consumers to pass XML data that represents business documents such as purchase orders or sales invoices. The validity of the input data must be programmatically validated by the Web method before it is processed or passed to downstream components.

The client and the server have to establish and agree on a schema that describes the XML. The following code fragment, which is applicable to .NET Framework 1.1, shows how a Web method can use the System.Xml.XmlValidatingReader class to validate the input data, which, in this example, describes a simple book order. Notice that the XML data is passed through a simple string parameter.

Note   The XmlValidatingReader class is obsolete in Microsoft .NET Framework version 2.0. You can create a validating XmlReader instance by using the XmlReaderSettings class and the Create method. For more information, see "Validating XML Data with XmlReader."

using System.Xml;
using System.Xml.Schema;

[WebMethod]
public void OrderBooks(string xmlBookData)
{
  try
  {
    // Create and load a validating reader
    XmlValidatingReader reader = new XmlValidatingReader(xmlBookData,
                                                         XmlNodeType.Element,
                                                         null);
    // Attach the XSD schema to the reader
    reader.Schemas.Add("urn:bookstore-schema",
                       @"https://localhost/WSBooks/bookschema.xsd");
    // Set the validation type for XSD schema.
    // XDR schemas and DTDs are also supported
    reader.ValidationType = ValidationType.Schema;
    // Create and register an event handler to handle validation errors
    reader.ValidationEventHandler += new ValidationEventHandler(
                                                   ValidationErrors );
    // Process the input data
    while (reader.Read())
    {
      . . .
    }
    // Validation completed successfully
  }
  catch
  {
   . . .
  }
}

// Validation error event handler
private static void ValidationErrors(object sender, ValidationEventArgs args)
{
  // Error details available from args.Message
  . . .
}

The following fragment shows how the consumer calls the preceding Web method:

string xmlBookData = "<book  xmlns='urn:bookstore-schema'
                         xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>" +
                     "<title>Building Secure ASP.NET Applications</title>" +
                     "<isbn>0735618909</isbn>" +
                     "<orderQuantity>1</orderQuantity>" +
                     "</book>";
BookStore.BookService bookService = new BookStore.BookService();
bookService.OrderBooks(xmlBookData));

The preceding example uses the following simple XSD schema to validate the input data.

<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns="urn:bookstore-schema"
            elementFormDefault="qualified"
            targetNamespace="urn:bookstore-schema">
  <xsd:element name="book" type="bookData"/>
  <xsd:complexType name="bookData">
    <xsd:sequence>
      <xsd:element name="title" type="xsd:string" />
      <xsd:element name="isbn" type="xsd:integer" />
      <xsd:element name="orderQuantity" type="xsd:integer"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

The following table shows additional complex element definitions that can be used in an XSD schema to further constrain individual XML elements.

Table 12.1   XSD Schema Element Examples

Description Example
Using regular expressions to constrain XML elements
<xsd:element name="zip">
  <xsd:simpleType>
    <xsd:restriction base="xsd:string">
     <xsd:pattern value="\d{5}(-\d{4})?" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:element>
Constraining a decimal value to two digits after the decimal point
<xsd:element name="Salary">
  <xsd:simpleType>
    <xsd:restriction base="xsd:decimal">
      <xsd:fractionDigits value="2" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:element>
Constraining the length of an input string
<xsd:element name="FirstName">
  <xsd:simpleType>
    <xsd:restriction base="xsd:string">
      <xsd:maxLength value="50" />
      <xsd:minLength value="2" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:element>
Constraining input to values defined by an enumerated type
<xsd:element name="Gender">
  <xsd:simpleType>
    <xsd:restriction base="xsd:string">
      <xsd:enumeration value="Male" />
      <xsd:enumeration value="Female" />
    </xsd:restriction>
  </xsd:simpleType>
</xsd:element>

For more information, see Microsoft Knowledge Base articles:

  • 307379, "How To: Validate an XML Document by Using DTD, XDR, or XSD in Visual C# .NET."
  • 318504, "How To: Validate XML Fragments Against an XML Schema in Visual C#.NET."

SQL Injection

SQL injection allows an attacker to execute arbitrary commands in the database using the Web service's database login. SQL injection is a potential issue for Web services if the services use input data to construct SQL queries. If your Web methods access the database, they should do so using SQL parameters and ideally, parameterized stored procedures. SQL parameters validate the input for type and length, and they ensure that the input is treated as literal text and not executable code. For more information about this and other SQL injection countermeasures, see the "Input Validation" section in Chapter 14, "Building Secure Data Access."

Cross-Site Scripting

With cross-site scripting (XSS), an attacker exploits your application to execute malicious script at the client. If you call a Web service from a Web application and send the output from the Web service back to the client in an HTML data stream, XSS is a potential issue. In this scenario, you should encode the output received from the Web service in the Web application before returning it to the client. This is particularly important if you do not own the Web service and it falls outside the Web application's trust boundary. For more information about XSS countermeasures, see the "Input Validation" section in Chapter 10, "Building Secure ASP.NET Pages and Controls."

Authentication

If your Web service outputs sensitive, restricted data or if it provides restricted services, it needs to authenticate callers. A number of authentication schemes are available and these can be broadly divided into three categories:

  • Platform level authentication
  • Message level authentication
  • Application level authentication

Platform Level Authentication

If you are in control of both endpoints and both endpoints are in the same or trusting domains, you can use Windows authentication to authenticate callers.

Basic Authentication

You can use IIS to configure your Web service's virtual directory for Basic authentication. With this approach, the consumer must configure the proxy and provide credentials in the form of a user name and password. The proxy then transmits them with each Web service request through that proxy. The credentials are transmitted in plaintext and therefore you should only use Basic authentication with SSL.

The following code fragment shows how a Web application can extract Basic authentication credentials supplied by an end user and then use those to invoke a downstream Web service configured for Basic authentication in IIS.

// Retrieve client's credentials (available with Basic authentication)
string pwd = Request.ServerVariables["AUTH_PASSWORD"];
string uid = Request.ServerVariables["AUTH_USER"];
// Set the credentials
CredentialCache cache = new CredentialCache();
cache.Add( new Uri(proxy.Url), // Web service URL
          "Basic",
           new NetworkCredential(uid, pwd, domain) );
proxy.Credentials = cache;

Integrated Windows Authentication

You can use IIS to configure your Web service's virtual directory for Integrated Windows authentication, which results either in Kerberos or NTLM authentication depending on the client and server environment. The advantage of this approach in comparison to Basic authentication is that credentials are not sent over the network, which eliminates the network eavesdropping threat.

To call a Web service configured for Integrated Windows authentication, the consumer must explicitly configure the Credentials property on the proxy.

To flow the security context of the client's Windows security context (either from an impersonating thread token or process token) to a Web service you can set the Credentials property of the Web service proxy to CredentialCache.DefaultCredentials as follows.

proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

You can also use an explicit set of credentials as follows:

CredentialCache cache = new CredentialCache();
cache.Add( new Uri(proxy.Url), // Web service URL
          "Negotiate",         // Kerberos or NTLM
           new NetworkCredential(userName, password, domain));
proxy.Credentials = cache;

If you need to specify explicit credentials, do not hard code them or store them in plaintext. Encrypt account credentials by using DPAPI and store the encrypted data either in an <appSettings> element in Web.config or beneath a restricted registry key.

For more information about platform level authentication, see the "Web Services Security" section in "Microsoft patterns & practices Volume I, Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication" at https://msdn.microsoft.com/library/en-us/dnnetsec/html/secnetlpMSDN.asp?frame=true.

Message Level Authentication

You can use WSE to implement a message level authentication solution that conforms to the emerging WS-Security standard. This approach allows you to pass authentication tokens in a standard way by using SOAP headers.

Note   When two parties agree to use WS-Security, the precise format of the authentication token must also be agreed upon.

The following types of authentication token can be used and are supported by WSE:

  • User name and password
  • Kerberos ticket
  • X.509 certificate
  • Custom token

User Name and Password

You can send user names and password credentials in the SOAP header. However, because these are sent in plaintext, this approach should only be used in conjunction with SSL due to the network eavesdropping threat. The credentials are sent as part of the <Security> element, in the SOAP header as follows.

<wsse:Security
         xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext">
  <wsse:UsernameToken>
    <wsse:Username>Bob</wsse:Username>
    <wsse:Password>YourStr0ngPassWord</wsse:Password>
   </wsse:UsernameToken>
</wsse:Security>

User Name and Password Digest

Instead of sending a plaintext password, you can send a password digest. The digest is a Base64-encoded SHA1 hash value of the UTF8-encoded password. However, unless this approach is used over a secure channel, the data can still be intercepted by attackers armed with network monitoring software and reused to gain authenticated access to your Web service. To help address this replay attack threat, a nonce and a creation timestamp can be combined with the digest.

User Name and Password Digest with Nonce and Timestamp

With this approach the digest is a SHA1 hash of a nonce value, a creation timestamp, and the password as follows.

digest = SHA1(nonce + creation timestamp + password)

With this approach, the Web service must maintain a table of nonce values and reject any message that contains a duplicate nonce value. While the approach helps protect the password and offers a basis for preventing replay attacks, it suffers from clock synchronization issues between the consumer and provider when calculating an expiration time, and it does not prevent an attacker capturing a message, modifying the nonce value, and then replaying the message to the Web service. To address this threat, the message must be digitally signed. With the WSE, you can sign a message using a custom token or an X.509 certificate. This provides tamperproofing and authentication, based on a public, private key pair.

Kerberos Tickets

You can send a security token that contains a Kerberos ticket as follows.

<wsse:Security
         xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext">
  <wsse:BinarySecurityToken
           ValueType="wsse:Kerberosv5ST"
           EncodingType="wsse:Base64Binary">
    U87GGH91TT ...
  </wsse:BinarySecurityToken>
</wsse:Security>

X.509 Certificates

You can also provide authentication by sending an X.509 certificate as an authentication token.

<wsse:Security
         xmlns:wsse="https://schemas.xmlsoap.org/ws/2002/12/secext">
  <wsse:BinarySecurityToken
          ValueType="wsse:X509v3"
          EncodingType="wsse:Base64Binary">
     Hg6GHjis1 ...  
  </wsse:BinarySecurityToken>
</wsse:Security>

For more information about the above approaches, see the samples that ship with WSE.

Application Level Authentication

You can design and build your own custom authentication by using custom SOAP headers for your application. Before doing so, review the features provided by the platform and WSE to see if any of these features can be used. If you must use a custom authentication mechanism, and you need to use cryptography, then use standard encryption algorithms exposed by the System.Security.Cryptography namespace.

Authorization

After authentication, you can restrict callers to a subset of the functionality exposed by your Web service, based on the caller's identity or role membership. You can restrict access to service endpoints (at the .asmx file level), individual Web methods, or specific functionality inside Web methods.

Web Service Endpoint Authorization

If your Web service is configured for Integrated Windows authentication you can configure NTFS permissions on your Web service (.asmx) files to control access, based on the security context of the original caller. This authorization is performed by the ASP.NET FileAuthorizationModule and impersonation is not required.

Regardless of the authentication type, you can use the ASP.NET UrlAuthorizationModule to control access to Web service (.asmx) files. You configure this by adding <allow> and <deny> elements to the <authorization> element in Machine.config or Web.config.

For more information about both forms of authorization, see the "Authorization" section in Chapter 19, "Securing Your ASP.NET Application and Web Services."

Web Method Authorization

You can use declarative principal permission demands to control access to individual Web methods based on the identity or role membership of the caller. The caller's identity and role membership is maintained by the principal object associated with the current Web request (accessed through HttpContext.User.)

[PrincipalPermission(SecurityAction.Demand, Role=@"Manager")]
[WebMethod]
public string QueryEmployeeDetails(string empID)
{
}

For more information about principal permission demands, see the "Authorization" section in Chapter 10, "Building Secure ASP.NET Pages and Controls."

Programmatic Authorization

You can use imperative permission checks or explicit role checks by calling IPrincipal.IsInRole inside your Web methods for fine-grained authorization logic as follows.

// This assumes non-Windows authentication. With Windows authentication
// cast the User object to a WindowsPrincipal and use Windows groups as
// role names
GenericPrincipal user = User as GenericPrincipal;
if (null != user)
{
  if ( user.IsInRole(@"Manager") )
  {
    // User is authorized to perform manager functionality
  }

Note   Additionally, if you are running ASP.NET 2.0 and you have enabled the Role Manager feature, you can use the Roles API for role checks. For more detailed information on using the Role Manager feature in ASP.NET 2.0, see "How To: Use Role Manager in ASP.NET 2.0. ".

Sensitive Data

The threats of network eavesdropping or information disclosure at intermediate application nodes must be addressed if your Web service request or response messages convey sensitive application data, for example, credit card numbers, employee details, and so on.

In a closed environment where you are in control of both endpoints, you can use SSL or IPSec to provide transport layer encryption. In other environments and where messages are routed through intermediate application modes, a message level solution is required. The WS-Security standard defines a confidentiality service based on the World Wide Web Consortium (W3C) XML Encryption standard that allows you to encrypt some or all of a SOAP message before it is transmitted.

XML Encryption

You can encrypt all or part of a SOAP message in three different ways:

  • Asymmetric encryption using X.509 certificates
  • Symmetric encryption using shared keys
  • Symmetric encryption using custom binary tokens

Asymmetric Encryption Using X.509 Certificates

With this approach, the consumer uses the public key portion of an X.509 certificate to encrypt the SOAP message. This can only be decrypted by the service that owns the corresponding private key.

The Web service must be able to access the associated private key. By default, WSE searches for X.509 certificates in the local machine store. You can use the <x509> configuration element in Web.config to set the store location to the current user store as follows.

<configuration>
  <microsoft.web.services>
    <security>
      <x509 storeLocation="CurrentUser" />
   </security>
  </microsoft.web.services>
</configuration>

If you use the user store, the user profile of the Web service's process account must be loaded. If you run your Web service using the default ASPNET least privileged local account, the .NET Framework loads the user profile for the ASPNET account on Windows 2000. On Windows Server 2003, the profile for this account is only loaded if the ASP.NET process model is used. In this scenario, the user key store is accessible.

Note   The user profile for the ASP.NET process identity is not loaded explicitly by IIS 6.0 if the IIS 6.0 process model is used on Windows Server 2003.

For Web services built using version 1.0 of the .NET Framework, the ASPNET user profile is not loaded. In this scenario, you have two options.

  • Run your Web service using a custom least privileged account with which you have previously interactively logged on to the Web server to create a user profile.

  • Store the key in the local machine store and grant access to your Web service process account. On Windows 2000, this is the ASPNET account by default. On Windows Server 2003, it is the Network Service account by default.

    To grant access, use Windows Explorer to configure an ACL on the following folder that grants full control to the Web service process account.

    \Documents and Settings\All Users\Application Data\
                                                  Microsoft\Crypto\RSA\MachineKeys
    

For more information, see the "Managing X.509 Certificates," "Encrypting a SOAP Message Using an X.509 Certificate," and "Decrypting a SOAP Message Using an X.509 Certificate" sections in the WSE documentation.

Symmetric Encryption Using Shared Keys

With symmetric encryption, the Web service and its consumer share a secret key to encrypt and decrypt the SOAP message. This encryption is faster than asymmetric encryption although the consumer and the service provider must use some out-of-band mechanism to share the key.

For more information, see the "Encrypting a SOAP Message Using a Shared Key" and "Decrypting a SOAP Message Using a Shared Key" sections in the WSE documentation.

Symmetric Encryption Using Custom Binary Tokens

You can also use WSE to define a custom binary token to encapsulate the custom security credentials used to encrypt and decrypt messages. Your code needs two classes. The sender class must be derived from the BinarySecurityToken class to encapsulate the custom security credentials and encrypt the message. The recipient class must be derived from DecryptionkeyProvider class to retrieve the key and decrypt the message.

For more information, see the "Encrypting a SOAP Message Using a Custom Binary Security Token" and "Decrypting a SOAP Message Using a Custom Binary Security Token" sections in the WSE documentation.

Encrypting Parts of a Message

By default, WSE encrypts the entire SOAP body and none of the SOAP header information. However, you can also use WSE to programmatically encrypt and decrypt portions of a message.

For more information, see the "Specifying the Parts of a SOAP Message that are Signed or Encrypted" section in the WSE documentation.

Parameter Manipulation

Parameter manipulation in relation to Web services refers to the threat of an attacker altering the message payload in some way while the message request or response is in transit between the consumer and service.

To address this threat, you can digitally sign a SOAP message to allow the message recipient to cryptographically verify that the message has not been altered since it was signed. For more information, see the "Digitally Signing a SOAP Message" section in the WSE documentation.

Exception Management

Exception details returned to the consumer should only contain minimal levels of information and not expose any internal implementation details. For example, consider the following system exception that has been allowed to propagate to the consumer.

System.Exception: User not in managers role
   at EmployeeService.employee.GiveBonus(Int32 empID, Int32 percentage) in c:\inetpub\wwwroot\employeesystem\employee.asmx.cs:line 207

The exception details shown above reveal directory structure and other details to the service consumer. This information can be used by a malicious user to footprint the virtual directory path and can assist with further attacks.

Web Services can throw three types of exceptions:

  • SoapException objects.

    These can be generated by the CLR or by your Web method implementation code.

  • SoapHeaderException objects

    These are generated automatically when the consumer sends a SOAP request that the service fails to process correctly.

  • Exception objects

    A Web service can throw a custom exception type that derives from System.Exception. The precise exception type is specific to the error condition. For example, it might be one of the standard .NET Framework exception types such as DivideByZeroException, or ArgumentOutOfRangeException and so on.

Regardless of the exception type, the exception details are propagated to the client using the standard SOAP <Fault> element. Clients and Web services built with ASP.NET do not parse the <Fault> element directly but instead deal consistently with SoapException objects. This allows the client to set up try blocks that catch SoapException objects.

Note   If you throw a SoapException from a custom HTTP module, it is not automatically serialized as a SOAP <Fault>. In this case, you have to create the SOAP <Fault> manually.

Using SoapExceptions

The following code shows a simple WebMethod, where the validation of application logic fails and, as a result, an exception is generated. The error information sent to the client is minimal. In this sample, the client is provided with a help desk reference that can be used to call support. At the Web server, a detailed error description for the help desk reference is logged to aid problem diagnosis.

using System.Xml;
using System.Security.Principal;

[WebMethod]
public void GiveBonus(int empID, int percentage)
{
  // Only managers can give bonuses
  // This example uses Windows authentication
  WindowsPrincipal wp = (HttpContext.Current.User as WindowsPrincipal);
  if( wp.IsInRole(@"Domain\Managers"))
  {
     // User is authorized to give bonus
     . . .
  }
  else
  {
    // Log error details on the server. For example:
    //    "DOMAIN\Bob tried to give bonus to Employee Id 345667;
    //     Access denied because DOMAIN\Bob is not a manager."
    // Note: User name is available from wp.Identity.Name

    // Return minimal error information to client using a SoapException
    XmlDocument doc = new XmlDocument();
    XmlNode detail = doc.CreateNode(XmlNodeType.Element,
                                    SoapException.DetailElementName.Name,
                                    SoapException.DetailElementName.Namespace);
    // This is the detail part of the exception
    detail.InnerText = "User not authorized to perform requested operation";
    throw new SoapException("Message string from your Web service",
                            SoapException.ServerFaultCode,
                            Context.Request.Url.AbsoluteUri, detail, null );
  }
}

The consumer code that handles potential SoapExceptions follows:

try
{
  EmployeeService service = new EmployeeService();
  Service.GiveBonus(empID,percentage);
}
catch (System.Web.Services.Protocols.SoapException se)
{
   // Extract custom message from se.Detail.InnerText
   Console.WriteLine("Server threw a soap exception" + se.Detail.InnerText );
}

Application Level Error Handling in Global.asax

ASP.NET Web applications commonly handle application level exceptions that are allowed to propagate beyond a method boundary in the Application_Error event handler in Global.asax. This feature is not available to Web services, because the Web service's HttpHandler captures the exception before it reaches other handlers.

If you need application level exception handling, create a custom SOAP extension to handle it. For more information, see MSDN article, "Altering the SOAP Message using SOAP Extensions" in the "Building Applications" section of the .NET Framework SDK at https://www.microsoft.com/downloads/details.aspx?FamilyID=9b3a2ca6-3647-4070-9f41-a333c6b9181d&DisplayLang=en.

Auditing and Logging

With a Web service, you can audit and log activity details and transactions either by using platform-level features or by using custom code in your Web method implementations.

You can develop code that uses the System.Diagnostics.EventLog class to log actions to the Windows event log. The permission requirements and techniques for using this class from a Web service are the same as for a Web application. For more information, see the "Auditing and Logging" section in Chapter 10, "Building Secure ASP.NET Pages and Controls."

Proxy Considerations

If you use WSDL to automatically generate a proxy class to communicate with a Web service, you should verify the generated code and service endpoints to ensure that you communicate with the desired Web service and not a spoofed service. If the WSDL files on a remote server are inadequately secured, it is possible for a malicious user to tamper with the files and change endpoint addresses, which can impact the proxy code that you generate.

Specifically, examine the <soap:address> element in the .wsdl file and verify that it points to the expected location. If you use Visual Studio .NET to add a Web reference by using the Add Web Reference dialog box, scroll down and check the service endpoints.

Finally, whether you use Visual Studio.NET to add a Web reference or manually generate the proxy code using Wsdl.exe, closely inspect the proxy code and look for any suspicious code.

Note   You can set the URL Behavior property of the Web service proxy to Dynamic, which allows you to specify endpoint addresses in Web.config.

Code Access Security Considerations

Code access security can limit the resources that can be accessed and the operations that can be performed by your Web service code. An ASP.NET Web service is subject to ASP.NET code access security policy, configured by the Web service's <trust> element.

.NET Framework consumer code that calls a Web service must be granted the WebPermission by code access security policy. The precise state of the WebPermission determines the range of Web services that can be called. For example, it can constrain your code so that it can only call local Web services or services on a specified server.

If the consumer code has full trust, it is granted the unrestricted WebPermission which allows it to call any Web service. Partial trust consumer code is subject to the following limitations:

  • If you call a Web service from a Medium trust Web application, by default you can only access local Web services.
  • Consumer code that uses the WSE classes must be granted full trust. For example, if your Web service proxy classes derive from Microsoft.Web.Services.WebServicesClientProtocol, which is provided by the WSE, full trust is required. To use WSE from a partial trust Web application, you must sandbox calls to the Web service.

For more information about calling Web services from partial trust Web applications, see Chapter 9, "Using Code Access Security with ASP.NET." For more information about WebPermission, see the "Web Services" section in Chapter 8, "Code Access Security in Practice."

Deployment Considerations

The range of security options available to you depends greatly on the specific deployment scenarios your Web services attempt to cover. If you build applications that consume Web services in an intranet, then you have the widest range of security options and techniques at your disposal. If, however, your Web service is publicly accessible over the Internet, your options are far more limited. This section describes the implications of different deployment scenarios on the applicability of the approaches to securing Web services discussed previously in this chapter.

Intranet Deployment

Because you control the consumer application, the service, and the platform, intranets usually provide the widest range of available options for securing Web services.

With an intranet scenario, you can usually choose from the full range of authentication and secure communication options. For example, you might decide to use Windows authentication if the consumer and service are in the same or trusting domains. You can specify that client application developers set the credentials property on the client proxy to flow the user's Windows credentials to the Web service.

Intranet communication is often over a private network, with some degree of security. If this is insufficient, you might decide to encrypt traffic by using SSL. You can also use message level security and install WSE on both the client and server to handle security at both ends transparently to the application. WSE supports authentication, digital signatures, and encryption.

Extranet Deployment

In an extranet scenario, you may need to expose your Web service over the Internet to a limited number of partners. The user community is still known, predictable, and possibly uses managed client applications, although they come from separate, independent environments. In this situation, you need an authentication mechanism that is suitable for both parties and does not rely on trusted domains.

You can use Basic authentication if you make account information available to both parties. If you use Basic authentication, make sure that you secure the credentials by using SSL.

Note   SSL only protects credentials over the network. It does not protect them in situations where a malicious user successfully installs a proxy tool (such as sslproxy) local to the client machine to intercept the call before forwarding it to the Web service over SSL.

As an alternate option for use with an extranet, you can use IIS client certificate authentication instead of passing explicit credentials. In this case, the calling application must present a valid certificate with the call. The Web service uses the certificate to authenticate the caller and authorize the operation. For more information, see the "Extranet Security" section in MSDN article, "Building Secure ASP.NET Applications" at https://msdn.microsoft.com/en-us/library/aa302386.aspx.

Internet Deployment

If you expose your Web service to a large number of Internet consumers and require authentication, the options available to you are substantially constrained. Any form of platform level authentication is unlikely to be suitable, since the consumers will not have proper domain accounts to which they can map their credentials. The use of IIS client certificate authentication and the transport (SSL) level is also problematic when a large number of client certificates must be made known to the target IIS Web server (or the ISA Server in front of it). This leaves message and application-level authentication and authorization the most likely choice. Credentials passed by the consumer of the service in the form of user name, password, certificate, Kerberos ticket, or custom token) can be validated transparently by the Web services infrastructure (WSE) or programmatically inside the target service. client certificates are difficult to manage scale. Key management (issuing and revoking) becomes an issue. Also, certificate-based authentication is resource intensive and therefore is subject to scalability issues with large number of clients.

SSL usually provides encryption of the network traffic (server-side certificate only), but can also be supplemented by message-level encryption.

Using client certificates, while advantageous from a security point of view, often becomes problematic for large numbers of users. You must carefully manage the certificates and consider how they should be delivered to clients, renewed, revoked, and so on. Another potential issue in Internet situations is the overall scalability of the solution due to processing overhead or the encryption/decryption and certificate validation for a large-scale Web service with significant workload.

Summary

WS-Security is the emerging standard for Web services security. The specification defines options for authentication by passing security tokens in a standard way using SOAP headers. Tokens can include user name and password credentials, Kerberos tickets, X.509 certificates, or custom tokens. WS-Security also addresses message privacy and integrity issues. You can encrypt whole or partial messages to provide privacy, and digitally sign them to provide integrity.

In intranet scenarios, where you are in control of both endpoints, platform level security options such as Windows authentication, can be used. For more complex scenarios where you do not control both endpoints and where messages are routed through intermediate application nodes, message level solutions are required. The following section, "Additional References," lists the Web sites you can use to track the emerging WS-Security standard and the associated WSE tool kit that allows you to build solutions that conform to this and other emerging Web service standards.

Additional Resources

For more information, see the following resources:

patterns & practices Developer Center

Retired Content

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

© Microsoft Corporation. All rights reserved.