Securing Your WSDL

Posted on Feb 25, 2014 in General  | No comments

This is a short follow-up to my previous post on Securing Web Services with Sitecore Authentication Providers in 5 easy steps.

ASP.Net helpfully generates documentation pages for your web services automatically.  This is the HTML that is served when you browse to an asmx file.  It gives you a list of all the methods connected to the web service.  Clicking into any one of these methods provides information on the parameters and return values, as well as the request methods that are allowed, generally SOAP and HTTP POST, but sometimes also HTTP GET.  It also provides a link to the auto-generated WSDL file with a complete list of types, properties and method signatures provided by your web service.

That’s great if you’re creating a web service designed to be consumed by the public, but a bit too much information to publish on your corporate internet site.  At least that’s what I think.  It’s more than enough information for a potential attacker to craft a well though out attack on your site and blind-side you.  Frankly it’s the equivalent of hiding the key under the front door mat and leaving a note with directions to the key posted on the door.

The Broadsword Way

Using the web.config file it’s possible to disable all documentation functions for all web services simultaneously. Noice.

<configuration>
  <system.web>
    <webServices>
      <protocols>
        <remove name=”Documentation” />
      </protocols>
      <wsdlHelpGenerator href="DefaultSdlHelpGenerator.aspx"/>
    </webServices>
  </system.web>
</configuration>

This way you just get a “Request format is unrecognised” error.

The Scalpel Way

It’s possible you don’t want to nuke everything.  That’s OK.

You can replace the standard auto-generated help pages without affecting the WSDL file by leaving the Documentation protocol alone and specifying a custom help page like so:

<configuration>
  <system.web>
    <webServices>
      <wsdlHelpGenerator href="WSHelpPage.aspx"/>
    </webServices>
  </system.web>
</configuration>

Note that the href is a file path and not a URL.  Also you can use absolute or relative paths, but if you specify a relative path then it should be relative to the web.config file.

You can also replace the WSDL file but that’s a bit harder.

In your asmx class file, add one or more WebServiceBindingAttribute decorations to the class.  This allows you to arbitrarily define multiple sets of metadata for use with your web service.  So, for example, you could have a different WSDL file for each of several namespaces, or you could split the methods in the class across several namespaces.

You can set the Name arbitrarily as it’s just an internal reference.  Set the Location property to the URL of your WSDL file.  This can be relative or absolute and if relative is in relation to the asmx file.

On each method you can then specify a SoapDocumentationMethodAttribute passing in the name of a binding you set earlier. This tells the system which method should be emitted (and documented) against which binding.  Noice.

So by way of example straight from MSDN:

using System.Web.Services;
using System.Web.Services.Protocols;
// Binding is defined in this XML Web service and uses the default namespace.
[WebServiceBinding(Name="LocalBinding")]
// Binding is defined in this XML Web service, but it is not a part of the default namespace.
[WebServiceBinding(Name="RemoteBinding", Namespace="http://foo.com/MyBinding", Location="MyWSDL.aspx")]
public class MyWebServices()
{
    [WebMethod]
    [SoapDocumentationMethod(Binding="LocalBinding")]
    public string HelloWorldInternal() { return "Hello world, internally!"; }

    [WebMethod]
    [SoapDocumentationMethod(Binding="RemoteBinding")]
    public string HelloWorldExternal() { return "Hello world, externally!"; }
}

Incidentally you can also use the SoapDocumentationMethodAttribute to specify element names in the request/response too. Noice.