Intrusion Prevention

Build Security Into Your Web Services with WSE 2.0 and ISA Server 2004

Dino Esposito

This article discusses:

  • Authentication techniques for .NET Web services
  • Security and policy in WSE 2.0
  • The use of firewalls in protecting Web services
  • ISA Server 2004 and WSDL
This article uses the following technologies:
WSE 2.0, Web services, XML, C#, Security

Contents

Desperately Seeking Standards
The Moral of the Story
Putting WSE 2.0 into Perspective
Authenticating Users
Integrity and Confidentiality
Policy and Assertions
ISA Server 2004 At a Glance
Web Service-Specific Firewalls
Call to Action

There are aspects of software design and development many of us would like to overlook because they're just not fun. The work we do in security, performance tuning, and optimization may not be glamorous, but it is essential. And while security has always been important, it is especially critical to today's Web applications because of the great financial risk that is posed by insecure code.

Software security is a team effort. An application cannot be secure if the network on which it runs is insecure. Likewise, proper administration is ineffective if the code is wide open to malicious attack. While proper administrative policy may be at the foundation of security, even the most restrictive policy won't be able to keep inherently insecure code safe.

To achieve security for any piece of software exposed over the Web, you must enforce network and application security. The primary network threats to guard against include denial of service (DoS), spoofing, and eavesdropping. A more complete list of threats and a description of various threat models can be found at https://msdn.microsoft.com/security. Such attacks can result in the theft of passwords and other critical data, as well as request floods. They also provide attackers with an understanding of your network topology. Examples of threats aimed at the application include the notorious SQL injection and cross-site scripting (XSS) attacks.

In this article, I'll focus on some of the issues surrounding .NET Web services security. I'll review authorization, authentication, confidentiality, encryption, integrity, and policy, and spend a good deal of my time talking about what you can do in and around your code to fend off attacks. In addition to the hacker-resistant programming techniques I will discuss, I'll will explain the benefits of using a SOAP-aware firewall to stop potentially injurious calls from reaching your Web services. One of these smart Web service-specific firewalls is available with Internet Security and Acceleration (ISA) Server 2004. I'll take a look at it later on and explain the ad-vantages that XML intrusion prevention can bring to your system.

Desperately Seeking Standards

Security for Web services comes at three levels. First, you must ensure that the message has not been tampered with. Second, you must verify that the user sending the message provides valid credentials and is authorized to have the message processed. Third, you need to check that any assertions made for processing the message are fulfilled (including assertions defined using regular expressions on the content of the message). The implementation of these features is left to the developer, but the industry is coalescing around standards (and related developer's toolkits) that should be taken into careful account.

Imagine you need to build a .NET Web service that implements authentication and ensures that only authorized users can invoke methods. The interaction between a client and a .NET Web service consists of sending a packet (typically an HTTP request) to a public URL (typically an ASMX resource). Any request that hits IIS is first processed by the Web server. If the request is considered valid, control of the request passes to the ASP.NET application. If the ASP.NET application is configured for Windows® authentication, the security token generated by IIS is set as the identity of the authenticated user. Next, ASP.NET looks at whether that user is authorized to access the requested ASMX resource.

You don't need to be a security guru to see that such a built-in security mechanism available in the Microsoft® .NET Framework for Web services is somehow limiting in the real world. To allow or deny specific users access to the Web service, either you use the ASP.NET configuration system, providing a list of users and rules that are authorized to access the specified resource (such as that done in the Web.config snippet shown in Figure 1), or you set access control lists (ACLs) on the .asmx file itself. In the end, ASP.NET Windows authentication is mostly appropriate for intranet applications that authenticate users in the current domain. Windows authentication is simply too unwieldy for Internet applications where you may have to manage thousands or even millions of users. What can you do at this point?

Figure 1 Allow and Deny Specific User Access

<configuration> <system.web> <authentication mode="Windows" /> </system.web> <location path="myservice.asmx"> <system.web> <authorization> <allow users="Administrator"/> <allow users="DOMAIN\Davolio"/> <deny roles="BUILTIN\Power Users"/> </authorization> </system.web> </location> </configuration>

To authenticate a user who is attempting to execute a WebMethod, credentials must be passed along with the request. The format you use for the credentials is custom and service specific. In general, valid credentials are any sequence of values that the Web service can validate and successfully transform into a user identity. At a minimum, valid credentials include a user ID and a password. Some real-world services like Amazon.com also employ user tokens, such as alphanumeric strings unequivocally linked to an identity record in a number of ways.

How can you pass these user tokens to the service? You could, for example, wrap the user token in a custom SOAP header or have it passed as an extra argument to each and every method that requires authorized users. It would then perhaps be wise to use an HTTP module to filter incoming requests for authenticity before the request is served and the method is executed. This allows you to factor the authentication out of the individual service methods.

A SOAP message can optionally contain user-defined headers that solely serve to transmit metadata that is not strictly related to the semantics of a Web service call. This data can include security credentials. A Web service that intends to implement a custom authentication layer based on SOAP headers must do a couple of things. First, it must indicate that the SOAP header is expected to contain the authentication credentials. Second, it must process the credentials and authorize or deny the request.

In the .NET Framework, a custom SOAP header is a class that inherits from SoapHeader, like the simple one shown here:

public class CredentialsHeader : SoapHeader { public string UserName; public string Password; }

This class is bound to the Web service through the SoapHeader attribute, as shown in Figure 2. The Web service, in turn, defines a property to import the values carried by the header. In light of the custom header, the SOAP envelope for each secured method looks slightly different (see Figure 3).

Figure 3 The Soap Envelope

<soap:Envelope ...> <soap:Header> <CredentialsHeader xmlns="..."> <UserName>string</UserName> <Password>string</Password> </CredentialsHeader> </soap:Header> <soap:Body> <GetCustomersOrders xmlns="..."> <custID>string</custID> <year>int</year> </GetCustomersOrders> </soap:Body> </soap:Envelope>

Figure 2 Binding the SoapHeader Class

public class CredentialsHeader : SoapHeader { public string UserName; public string Password; } public class MyService : WebService { // Custom authentication header public CredentialsHeader UserToken; [WebMethod] [SoapHeader("UserToken", Required=true)] public DataSet GetCustomersOrders(string custID, int year) { // Forward a message to the logic // Collect data and return } ••• }

The values in the SOAP header are used to populate the corresponding Web service property (the UserToken property of Figure 2). On the client side, the proxy C# or Visual Basic® .NET file generated for the Web service contains another [SoapHeader] attribute for each secured method. The attribute guarantees that any SOAP packet issued for that method will contain the extra header.

Unfortunately, this approach will result in passwords sent to the server as clear text. One thing you can do to work around this problem is hash the password before sending it to the server. The server can then compare the hashed password to a similarly hashed string stored in a server database. In this scenario, the code to hash the password must be placed within the client application making the call. In addition, the hash algorithms used to hash the password on the client and on the server (for storing in the database) must match. Note, however, that sending hashed passwords doesn't protect you against replay and dictionary attacks. In the end, use of a username token is not a great idea unless the underlying transport is inherently secure, such as secure sockets layer (SSL), or unless you encrypt the username token, for example. I'll return to this point later in this article when discussing the .NET security framework for Web services—Web Services Enhancements (WSE) 2.0 (now at Service Pack 1).

Let's consider where the authentication takes place. Certainly it doesn't happen in the WebMethod since it would be improperly factored. If all WebMethods are secured, which is definitely a good practice, at the very least you can use a SOAP extension or an HTTP module to keep authentication code out of the WebMethod. Note that in an HTTP module you can intercept any events that characterize the lifecycle of an HTTP request. In a SOAP extension, you can inspect and modify parts of the SOAP message before and after its serialization and deserialization on the client and server.

Authorization doesn't require much more work once the user's been authenticated, though one more step is needed. You need to parse the SOAP source, retrieve the name of the invoked method, and check if the user is in the list of those who can execute the requested method. Typically, the method/user information is found in a separate data store, such as a SQL database.

SOAP headers are central to the implementation of an authentication and authorization layer for Web services. As the SOAP specification dictates, SOAP messages can include any number of custom headers for carrying any sort of custom information.

The Moral of the Story

Web services are growing quickly, and more and more super-smart people are taking up the challenge. As a result, good ideas are emerging at an amazing pace, but without much control over their implementations. For example, suppose two very smart people have the same raw idea. It's likely that the two ideas differ on some details and require some adjustments to really express the same concept. These adjustments define common rules and naming conventions so that the same concept is expressed using the same words. This is, of course, the purpose of having standards.

Let's say you want to use SOAP headers that contain scrambled passwords. How do you name the additional SOAP headers? How do you hash or encrypt the password? How do you validate parameters before execution? How do you define assertions? The list could go on and on.

Figure 4 Web Service Security Standards

Figure 4** Web Service Security Standards **

Web services standards (especially standards that relate to security) have been evolving so rapidly in the past couple of years that software toolkits have had a hard time keeping up with them. Today, the situation is more stable, and a bunch of WS-* specifications explain how Web services security should be implemented in a loosely coupled and platform-independent manner. WS-* specifications include directives about establishing secured communications, defining policies for services interaction, and defining rules of trust between domains of services. Figure 4 shows the stack of emerging security standards and Figure 5 provides a brief description of the main specifications.

Figure 5 Main Web Security Specifications

Specification Description
WS-Security Describes enhancements to SOAP messaging to provide protection through message integrity, confidentiality, and authentication. WS-Security also provides a mechanism for associating security tokens with messages and describes how to encode binary security tokens (X.509 certificates and Kerberos tickets) as well as how to include encrypted keys.
WS-Policy Provides a model and corresponding syntax to describe and communicate the policies of a Web service. It doesn't define any policy assertions itself; it simply defines the framework for packaging and processing assertions in a standard way.
WS-PolicyAssertions Specifies a set of common message policy assertions that can be specified within a policy. For example, it contains an assertion that validates user-defined expressions in a generalized way.
WS-PolicyAttachment Specifies mechanisms for associating policy expressions with WSDL type definitions and UDDI entities.
WS-SecurityPolicy Extends the WS-Security specification and indicates the policy assertions from the WS-Policy specification that apply to security.
WS-Trust Built on WS-Security, it defines how to request and issue security tokens and manage trust relationships.
WS-SecureConversation Built on WS-Security and WS-Trust, it defines how to provide secure communication. It also defines mechanisms for establishing and sharing security contexts.
WS-Federation Defines the mechanisms used to enable identity, authentication, and authorization federation across different trust realms.
WS-Addressing Defines elements to render in a transport-neutral format (information typically provided by transport protocols and messaging systems). The specification formalizes the receiver of a message (Web service endpoint) and message information headers.
WS-ReliableMessaging Describes a protocol that allows messages to be delivered reliably between distributed applications in the presence of software component or network failures.

A roadmap to Web services security can be found at Security in a Web Services World: A Proposed Architecture and Roadmap. It presents a broad set of specifications that cover security technologies including authentication, authorization, privacy, trust, integrity, confidentiality, and secure communications channels across a wide range of application and business topologies.

Standards are very important, and as a result, libraries have been developed that incorporate them. Most of the WS-Security and related specifications, such as WS-Policy, are now integrated in Web Services Enhancements 2.0.

Actually, there are far more standards out than are integrated into WSE. All of the WS-Transaction and related standards are not there, for example. As mentioned, the primary standards implemented by WSE are WS-Security and WS-Policy, the first of which is probably the most mature of all the WS-* specifications.

Putting WSE 2.0 into Perspective

WSE 2.0 helps Web service developers implement security best practices using accepted standards. Note, though, that the WSE property dialogs and wizards don't replace a good understanding of Web service security topics, nor are they supposed to.

WSE 2.0 enables developers and administrators to apply security policies for .NET Web services more easily. WSE 2.0 allows you to create signed and encrypted channels for Web services communication using Kerberos tickets, X.509 certificates, user credentials, and other custom binary or XML-based security tokens. In addition, WSE 2.0 supports policies and assertions to validate Web services calls and provides the ability to secure long-running communication via secure conversations. You can download WSE 2.0 from Web Services Enhancements. Aaron Skonnard provides a programmer's perspective of WSE 2.0 in the August 2004 installment of The XML Files column.

Let's see how WS-* specifications standardize and simplify the application of some common security measures such as authentication, authorization, encryption, and validation assertions. I'll use WSE 2.0 to explain these concepts.

Authenticating Users

WS-Security provides a general-purpose mechanism for associating security tokens with Web service method requests. Security tokens can be username and password pairings, X.509 certificates, or Kerberos tickets. WS-Security standardizes the header for credentials using <wsse:Security>. Here's an example:

<wsse:Security soap:mustUnderstand="1"> <wsse:UserNameToken xmlns:wsu="..."> <wsse:UserName>user</wsse:UserName> <wsse:Password type="wsse:PasswordDigest">R4eU...</wsse:Password> </wsse:UserNameToken> </wsse:Security>

This fragment is an excerpt from a SOAP message that contains username/password credentials. The UserNameToken node maps to a WSE 2.0 class (with the same name) that stores the credentials in two properties: Username and Password. A management class is then expected to process this token. The class is named UsernameTokenManager in WSE 2.0.

Interestingly enough, the UsernameTokenManager class is not abstract (nor is it sealed). Its default implementation authenticates the security token in the received message against a Windows account or an Active Directory® user. If it succeeds, a Windows principal is assigned to the Principal property of the UsernameToken. In most cases, though, you don't want Windows authentication because it requires that a user have an account on the server. This is acceptable for a small set of users (mostly intranets), but not for the thousands of users of an e-commerce Internet application. To implement a custom-authentication algorithm, you derive a class from UsernameTokenManager and override the AuthenticateToken method. For example, if you want to compare the incoming credentials with those stored in a SQL database, you can do so with a derived class as follows:

public class SqlUsernameTokenManager : UsernameTokenManager { protected override string AuthenticateToken(UsernameToken t) { // Find a match in the SQL database // Return the stored password for the specified user } }

Note that AuthenticateToken must return a string intended to be the password read from the data store. The password you return from the method will be compared to the password supplied with the SOAP message, and the authentication succeeds if the two match. If the user can't be authenticated, an exception is thrown.

In most production systems the AuthenticateToken method typically consults an external users database where the "password" is often in actuality a derivative of the real password, such as a hash of it. Most secure applications, in fact, store passwords in the database using a one-way hashing algorithm. This means that it is theoretically impossible to revert the hashed string back to the clear password for comparison. As a result, for authentication to work, the client must be able to send an equally hashed version of the password so that the comparison can occur on hashed strings. As mentioned, though, this is still subject to dictionary attacks. The advantage is that you can check the password's validity without manipulating the actual password for the user.

WSE 2.0 allows you to choose from three options when it comes to sending the password, as shown in Figure 6. The sidebar "Building Password-Secure Authentication Models" summarizes the feasible approaches you can take to build password-secure authentication models for WSE-enabled Web services.

Figure 6 Sending a Password in WSE 2.0

Value Description
SendHashed An SHA-1 hash of the password is sent in the SOAP message.
SendNone No password is sent in the SOAP message. The option makes sense if a digital signature is attached to the message. The signature must be built from a valid security token (such as credentials, Kerberos tickets, or certificates). The solution makes sense in distributed applications where a single sign-on architecture exists.
SendPlainText The password is sent in clear text. When using this option, a secure transport channel such as SSL should always be used. However, for a stricter security implementation, SSL should be used with SendHashed too.

The custom security token class must be registered with the Web service application. You can accomplish this in either of two ways. You can manually edit the Web.config file, which is the new section added by WSE 2.0, or you can resort to the WSE 2.0 tabbed dialog. You open the Security tab and add a new security token manager type. A lot of practical information on WSE 2.0 programming can be found in the following article: Securing .NET Web Services with the WS-Security Protocol. If you're particularly interested in WS-Security, be sure to take a look.Building Password-Secure Authentication Mode

If you choose Windows authentication with WSE 2.0, you can only send the password as clear text. In this case, WSE 2.0 gets the authentication token through a call to the LogonUser Win32® API function, which requires the password as plain clear text. It goes without saying that you should be sending unencrypted passwords only over a secure channel (SSL or TLS) or within a SOAP packet that has been previously encrypted using some of the other WSE 2.0 facilities.

If you go for custom user authentication and implement a custom user token class, you can take advantage of the other two options provided for sending passwords: sending a password hashed or sending no password whatsoever. If you choose the former option, WSE 2.0 transmits a hash of your password calculated using the SHA-1 algorithm. On the server, WSE 2.0 retrieves the stored password for the user, applies the same SHA-1 algorithm and compares the result against the transmitted hash. That's why the AuthenticateToken overridable method on the UsernameTokenManager class requires you to return the stored password instead of a simpler Boolean value.

This is a hazard from a general security standpoint. If the server is ever hacked, the attacker can just sit and see clear passwords pass by. This approach can produce severe damage in the case of a compromised server and lays the server open to replay attacks. A replay attack is when someone sees a valid token pass and just inserts the same token in another message.

A way to alleviate such risks consists of using (and storing) pre-hashed versions of the password created using an algorithm such as SHA-1 on which both the sender and the receiver agree. Basically, you transmit the hashed password (either further hashed or clear), rather than the original, and make AuthenticateToken return the hashed password stored in the database. Of course, the hash algorithm must be the same. This trick alone doesn't make the Web service call inherently more secure. Once the system is hacked, it doesn't make any difference if the attacker replays the call using the original or the hashed password. However, at least the hacker doesn't know the original password and can't cause more severe damage to the system.

If custom user authentication is your choice, then an even more secure approach involves adding a signature to the SOAP message along with the user token. If you choose to indicate a digital signature, you can avoid sending the password altogether. The signature built on the client from user name and password (the user token) represents your proof of possession. By doing so, you instruct Web Services Enhancements 2.0 to retrieve the password from the attached signature and compare it to the password that is returned by AuthenticateToken.

The WSE 2.0 user security token object features a property named Principal. The property gets and sets the IPrincipal object for the security token. The principal is set in the AuthenticateToken method immediately after retrieving the password for the specified user. In this case, the principal is a WindowsPrincipal object. Its IsInRole method will look up the user in the list of Windows accounts. If you're using a custom user name token class, you must add some code to your override of AuthenticateToken to generate a new GenericPrincipal object with its own list of roles:

// First, retrieve roles for the authenticated user this.Principal = new GenericPrincipal(token.Username, roles);

In the WebMethod code, you ensure that the user is a member of the roles authorized to call:

if (token == null || !token.Principal.IsInRole("PowerUsers")) throw new UnauthorizedAccessException();

The preceding code ensures that a UsernameToken was used to sign the SOAP message and that the user is, in fact, a member of the PowerUsers role.

Integrity and Confidentiality

Just adding credentials to a SOAP message doesn't make it inherently more secure. At a minimum, you need to add some encryption to ensure that the contents of the SOAP message are not intelligible as they travel over the network. SOAP messages, in fact, are by default plain text and thus can be read by any recipient. An encrypted SOAP message is cryptographically encoded, so that only the owner of the proper decryption key can read the contents of the message.

You might be asking why you should care about SOAP encryption when you can simply use network-level secure protocols, such as SSL and Transport Layer Security (TLS). SSL is easy to set up and works well; however, it has been designed mainly for Web sites and is not always optimal for Web services.

The first aspect to consider is that Web services are often implemented over HTTP, but that is neither necessary nor is it the only option. Microsoft Message Queuing (MSMQ) and SMTP, for example, are valid transport layers as well. WS-Security decouples Web services from HTTP security. Second, SSL encrypts the entire SOAP message and was not designed to protect only selected portions of messages.

This might not seem like a significant issue but consider what happens when a message is routed through multiple locations. Should you permit sensitive data to be visible to everybody who has something to process in the message? It's a good rule to make critical data available to the fewest number of people, so an all-or-nothing encryption scheme may pose a severe security issue. Another point to consider might be performance. Data confidentiality doesn't come for free and encrypting and decrypting the whole message is, computationally speaking, more costly than protecting only portions of it. WS-Security provides you with a flexibility that you just can't obtain out of SSL or similar protocols.

WSE 2.0 supports both asymmetric and symmetric encryption. Asymmetric encryption allows the client of a Web service to encrypt the message using the public key of an X.509 certificate. Subsequently, only the owner of the private key can decrypt the message. The WSE 2.0 Settings Tool contains a certificate wizard to let you secure request and response of a service application.

Symmetric encryption requires that a Web service and client already share a secret key. The sender encrypts SOAP messages using the shared key after which the recipient decrypts the SOAP messages using that same secret key.

The information collected through the WSE 2.0 Settings Tool wizard is recorded in a policy configuration file that contains assertions about the required integrity and/or confidentiality of the message. When you don't specify the portions of the SOAP message to encrypt, WSE 2.0 encrypts the entire contents of the <Body> element, but all of the SOAP headers are left as clear text. As for digital signing, by default WSE 2.0 signs the body, timestamp, and all addressing headers, such as To, ReplyTo, and RelatesTo. You can change these default settings programmatically or by editing the assertions in the policy file. If you want to edit the policy file, locate the <wssp:MessageParts> node below <wssp:Integrity> (for digital signing), or <wssp:Confidentiality> (for encryption).

Policy and Assertions

In summary, the security of Web services has three main facets: encryption/signing, authentication/authorization, and assertions. The first relates to the secure sending of the bytes over the network. While encryption guarantees that the message is not viewed, you also need to ensure that nothing got modified along the way. Digital signatures are one way of providing such integrity as well as providing the identity of the sender. The second aspect relates to the binding between the sender and the requested function. Authentication checks the credentials of the sender (whom he or she claims to be) while authorization verifies whether the sender has rights to perform the operation. The third level of security gets closer to the usage and logic of the Web service and, among other things, is aimed at ensuring that methods are invoked according to accepted predicates. Web services policies are extremely important to this level of security.

WS-Policy provides a flexible grammar for expressing the capabilities and requirements of WebMethods. A policy is a collection of one or more policy assertions. Some assertions specify requirements related to the wire (such as the authentication scheme or transport protocol) while others specify requirements critical to the service usage (such as the privacy policy). WS-Policy provides a unified grammar to allow assertions to be defined consistently.

The WS-PolicyAssertions standard provides an initial set of assertions to address some common needs of Web services. Built-in assertions include the required character set, language, and specification version. A fourth type of assertion is MessagePredicate.

MessagePredicate lets you assert arbitrary expressions to implement predicates and preconditions to which each message must conform. For example, these assertions can implement business rules. You can express assertions in either of two languages: XPath or SOAP message parts. You can find more information and an example in the March 2004 installment of The XML Files column.

The three aspects of Web services security I've examined form a defense perimeter only within the Web service application, which is where most of today's attacks occur. Nowadays, a traditional firewall is not necessarily an effective barrier because attacks tend to look like legitimate traffic to firewalls, which often only inspect the outermost envelope such as the headers of communication packets. To be effective, firewalls must start looking into the actual payload to figure out the intent of a request.

ISA Server 2004 belongs to this new breed of firewalls and has the ability to do deep content inspection and analysis for many popular Internet protocols.

ISA Server 2004 At a Glance

ISA Server 2004 is the next version of the Internet firewall, offering improved network security and performance. Designed from the ground up to provide efficient application-layer filtering, ISA Server 2004 is a rule-based firewall and a powerful HTTP proxy and caching server. Of the several enhancements that the newest version of ISA brings to the table, the one that is most relevant here is the extensible application-layer filtering. In Figure 7, you can see the overall architecture of ISA Server where the custom application filter components stand out.

The important thing going on here is that unlike some other firewall software, ISA Server 2004 looks into the actual content of an HTTP request in addition to inspecting the IP and TCP headers. In this way, ISA is capable of blocking any non-HTTP traffic, any contents brought by packets that look suspicious, and anything else that violates rules and policies that are set administratively. A fine-grained set of security policies give administrators the means to configure the level of security as they want.

Application filters play a key role in the architecture shown in Figure 7. They act like protocol handlers by filtering both outgoing (access) and incoming (published) traffic. ISA Server comes with built-in filters for most common protocols including HTTP, SMTP, and RPC.

Figure 7 ISA Server 2004 Architecture

Figure 7** ISA Server 2004 Architecture **

The HTTP filter provides for comprehensive syntax analysis, and the SMTP filter analyzes commands and filters messages for potentially injurious data. Other monitored protocols are DNS and POP3. As I mentioned earlier in this article, this portion of the architecture is extensible and based on a plug-in model. In other words, third-party vendors can extend ISA with ad hoc filters performing particular tasks. Yigal Edery discussed the application filter extensibility mechanism of ISA Server in the March 2004 issue of MSDN®Magazine (see Developing an Application Filter for Microsoft Internet Security and Acceleration Server 2004).

Several companies offer application filters for ISA Server that enhance security and interoperability for different protocols and types of traffic (a list is available at Partner Application Filters). I'd like to focus on one of these products in particular—Forum XWall for ISA Server—because of its unique Web service-specific features to protect against intrusions.

Web Service-Specific Firewalls

Forum XWall (an ISA Server 2004 plug-in) works as a kind of smart firewall that implements certain security features specifically targeted at Web services. Usually calls to Web services pass through ports that firewalls leave open, like port 80 and 443. This allows SOAP and XML messages to flow undetected into the company's internal network. While ISA Server introduces rich content filtering at the HTTP level, Forum XWall complements ISA Server by ensuring the integrity of Web services traffic as it flows through the organization. Basically, XWall is a sentinel against XML intrusions. In Figure 8 you see XWall installed within ISA Server 2004 and configured to monitor the request/response traffic for a few Web Services Description Language (WSDL) hosted on the server.

Figure 8 XWall Installed in ISA Server 2004

All of the policies in the figure are created by navigating the Publish Web Service or Publish Secure Service menu items in the task list. This is similar to the Publish Web Server and Publish Secure Server tasks that exist in the traditional firewall policies. Each Web services firewall policy is created as a result of a WSDL file being consumed from the local file system or from a Uniform Resource Identifier (URI) or Universal Description, Discovery, and Integration (UDDI) directory.

XWall detects and controls XML and SOAP traffic based on predefined criteria. In doing so, it can check the conformance of the call to the WSDL of the service and prevent parameters tampering, buffer overflows, replay attacks, command injection, and more. XWall can decide whether or not individual XML/SOAP messages, users, and URLs may gain access (such as read, write, execute privileges) to Web services behind the wall.

Figure 9 IDP Rule

Figure 9** IDP Rule **

It also enforces data integrity by checking raw XML against approved schemas, user-defined data validation rules, and a set of Intrusion Detection and Prevention (IDP) rules such as giving packets a maximum length and a maximum number of nested tags. Figure 9 shows an IDP rule where the maximum document size attribute is used to limit the SOAP/XML payload size that flows through the firewall.

In some cases, you can also use XWall to virtualize the WSDL based on ACLs so that any call that the authenticated user attempts to direct at a certain WebMethod is blocked at the gate if the user is not authorized. In other words, XWall can take the WSDL of the Web service and map portions of it to individual users, such as those using Active Directory.

Figure 10 Controlling Access to Web Service Methods

Figure 10** Controlling Access to Web Service Methods **

Access to Web service methods can be controlled either by mapping each method to a group of users for authorization or just by turning off access to every method. In Figure 10, the Add method can only be invoked by users who are members of the group EU-Partners. The Divide method doesn't require any authorization and thus anyone can invoke it. Finally, access to Multiply and Subtract are simply turned off so no one can access these operations.

Call to Action

As an increasingly essential piece of the enterprise architecture, Web services shouldn't simply be considered a sort of Web site accessed by software rather than humans. To deliver appropriate security to a Web service-based environment, you need to remember that Web services are first and foremost "services" and not necessarily tied to HTTP. Hence, secure transportation layers like SSL are certainly an option, but not the only one, and not necessarily the best one.

Securing the physical packet is, however, the first out of three protection levels. The second level is authentication and authorization where you ensure who's making the call and why they are making the call. Finally, the third level consists of verifying that conditions necessary for the call to take place exist.

To secure the packet, authenticate the caller, and validate the call, you can employ a variety of techniques. WS-* specifications for security have been defined and implemented to standardize these techniques across platforms. Adhering to standards and employing related toolkits like WSE 2.0 means developing on best practices, using common solutions, and in the long run, possibly integrating your services with smarter software and hardware system tools and products like firewalls and network filters.

The focus on security for Web applications must be on the application layer and the quality of checks must be raised to touch the actual content being sent and not just the outer envelope. For Web services, this means looking into the actual contents of the XML/SOAP payload itself.

You can build an effective perimeter outside the realm of the service using a smart firewall like Forum XWall or similar products. The advantage you can get is double: on one end, you have the certainty that badly formed calls are stopped at the gate and never reach the service. On the other end, you can keep your service more lean and mean by limiting code-level security checks to a minimum. For all its advantages, code-level security does unfortunately come at the cost of performance.

Dino Esposito is a Wintellect instructor and consultant based in Italy. Author of Programming ASP.NET and the new book Introducing ASP.NET 2.0 (both from Microsoft Press), he spends most of his time teaching classes on ASP.NET and ADO.NET and speaking at conferences. Get in touch with Dino at cutting@microsoft.com.