Security Frame: Exception Management | Mitigations
Product/Service | Article |
---|---|
WCF | |
Web API | |
Web Application |
WCF- Do not include serviceDebug node in configuration file
Title | Details |
---|---|
Component | WCF |
SDL Phase | Build |
Applicable Technologies | Generic, NET Framework 3 |
Attributes | N/A |
References | MSDN, Fortify Kingdom |
Steps | Windows Communication Framework (WCF) services can be configured to expose debugging information. Debug information should not be used in production environments. The <serviceDebug> tag defines whether the debug information feature is enabled for a WCF service. If the attribute includeExceptionDetailInFaults is set to true, exception information from the application will be returned to clients. Attackers can leverage the additional information they gain from debugging output to mount attacks targeted on the framework, database, or other resources used by the application. |
Example
The following configuration file includes the <serviceDebug>
tag:
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name=""MyServiceBehavior"">
<serviceDebug includeExceptionDetailInFaults=""True"" httpHelpPageEnabled=""True""/>
...
Disable debugging information in the service. This can be accomplished by removing the <serviceDebug>
tag from your application's configuration file.
WCF- Do not include serviceMetadata node in configuration file
Title | Details |
---|---|
Component | WCF |
SDL Phase | Build |
Applicable Technologies | Generic |
Attributes | Generic, NET Framework 3 |
References | MSDN, Fortify Kingdom |
Steps | Publicly exposing information about a service can provide attackers with valuable insight into how they might exploit the service. The <serviceMetadata> tag enables the metadata publishing feature. Service metadata could contain sensitive information that should not be publicly accessible. At a minimum, only allow trusted users to access the metadata and ensure that unnecessary information is not exposed. Better yet, entirely disable the ability to publish metadata. A safe WCF configuration will not contain the <serviceMetadata> tag. |
Ensure that proper exception handling is done in ASP.NET Web API
Title | Details |
---|---|
Component | Web API |
SDL Phase | Build |
Applicable Technologies | MVC 5, MVC 6 |
Attributes | N/A |
References | Exception Handling in ASP.NET Web API, Model Validation in ASP.NET Web API |
Steps | By default, most uncaught exceptions in ASP.NET Web API are translated into an HTTP response with status code 500, Internal Server Error |
Example
To control the status code returned by the API, HttpResponseException
can be used as shown below:
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}
Example
For further control on the exception response, the HttpResponseMessage
class can be used as shown below:
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
{
Content = new StringContent(string.Format("No product with ID = {0}", id)),
ReasonPhrase = "Product ID Not Found"
}
throw new HttpResponseException(resp);
}
return item;
}
To catch unhandled exceptions that are not of the type HttpResponseException
, Exception Filters can be used. Exception filters implement the System.Web.Http.Filters.IExceptionFilter
interface. The simplest way to write an exception filter is to derive from the System.Web.Http.Filters.ExceptionFilterAttribute
class and override the OnException method.
Example
Here is a filter that converts NotImplementedException
exceptions into HTTP status code 501, Not Implemented
:
namespace ProductStore.Filters
{
using System;
using System.Net;
using System.Net.Http;
using System.Web.Http.Filters;
public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is NotImplementedException)
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
}
}
}
}
There are several ways to register a Web API exception filter:
- By action
- By controller
- Globally
Example
To apply the filter to a specific action, add the filter as an attribute to the action:
public class ProductsController : ApiController
{
[NotImplExceptionFilter]
public Contact GetContact(int id)
{
throw new NotImplementedException("This method is not implemented");
}
}
Example
To apply the filter to all of the actions on a controller
, add the filter as an attribute to the controller
class:
[NotImplExceptionFilter]
public class ProductsController : ApiController
{
// ...
}
Example
To apply the filter globally to all Web API controllers, add an instance of the filter to the GlobalConfiguration.Configuration.Filters
collection. Exception filters in this collection apply to any Web API controller action.
GlobalConfiguration.Configuration.Filters.Add(
new ProductStore.NotImplExceptionFilterAttribute());
Example
For model validation, the model state can be passed to CreateErrorResponse method as shown below:
public HttpResponseMessage PostProduct(Product item)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
// Implementation not shown...
}
Check the links in the references section for additional details about exceptional handling and model validation in ASP.NET Web API
Do not expose security details in error messages
Title | Details |
---|---|
Component | Web Application |
SDL Phase | Build |
Applicable Technologies | Generic |
Attributes | N/A |
References | N/A |
Steps | Generic error messages are provided directly to the user without including sensitive application data. Examples of sensitive data include:
Trapping all errors within an application and providing generic error messages, as well as enabling custom errors within IIS will help prevent information disclosure. SQL Server database and .NET Exception handling, among other error handling architectures, are especially verbose and extremely useful to a malicious user profiling your application. Do not directly display the contents of a class derived from the .NET Exception class, and ensure that you have proper exception handling so that an unexpected exception isn't inadvertently raised directly to the user.
|
Implement Default error handling page
Title | Details |
---|---|
Component | Web Application |
SDL Phase | Build |
Applicable Technologies | Generic |
Attributes | N/A |
References | Edit ASP.NET Error Pages Settings Dialog Box |
Steps | When an ASP.NET application fails and causes an HTTP/1.x 500 Internal Server Error, or a feature configuration (such as Request Filtering) prevents a page from being displayed, an error message will be generated. Administrators can choose whether or not the application should display a friendly message to the client, detailed error message to the client, or detailed error message to localhost only. The
Open the |
Set Deployment Method to Retail in IIS
Title | Details |
---|---|
Component | Web Application |
SDL Phase | Deployment |
Applicable Technologies | Generic |
Attributes | N/A |
References | deployment Element (ASP.NET Settings Schema) |
Steps | The Often times, switches and options that are developer-focused, such as failed request tracing and debugging, are enabled during active development. It is recommended that the deployment method on any production server be set to retail. open the machine.config file and ensure that |
Exceptions should fail safely
Title | Details |
---|---|
Component | Web Application |
SDL Phase | Build |
Applicable Technologies | Generic |
Attributes | N/A |
References | Fail securely |
Steps | Application should fail safely. Any method that returns a Boolean value, based on which certain decision is made, should have exception block carefully created. There are lot of logical errors due to which security issues creep in, when the exception block is written carelessly. |
Example
public static bool ValidateDomain(string pathToValidate, Uri currentUrl)
{
try
{
if (!string.IsNullOrWhiteSpace(pathToValidate))
{
var domain = RetrieveDomain(currentUrl);
var replyPath = new Uri(pathToValidate);
var replyDomain = RetrieveDomain(replyPath);
if (string.Compare(domain, replyDomain, StringComparison.OrdinalIgnoreCase) != 0)
{
//// Adding additional check to enable CMS urls if they are not hosted on same domain.
if (!string.IsNullOrWhiteSpace(Utilities.CmsBase))
{
var cmsDomain = RetrieveDomain(new Uri(Utilities.Base.Trim()));
if (string.Compare(cmDomain, replyDomain, StringComparison.OrdinalIgnoreCase) != 0)
{
return false;
}
else
{
return true;
}
}
return false;
}
}
return true;
}
catch (UriFormatException ex)
{
LogHelper.LogException("Utilities:ValidateDomain", ex);
return true;
}
}
The above method will always return True, if some exception happens. If the end user provides a malformed URL, that the browser respects, but the Uri()
constructor doesn't, this will throw an exception, and the victim will be taken to the valid but malformed URL.