Catching Exceptions with Elmah within WCF

We all use the excellent ELMAH to deal with unhandled exceptions in an ASP.NET 3.5 web or MVC application. This works extremely well for all of the site, now what about WCF how can we get Elmah to work for us?

You can use the HttpHandler, and Decorate your Service(s) with an Error Handling attribute.

The ServiceErrorBehaviourAttribute:

using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

/// <summary>
/// So we can decorate Services with the [ServiceErrorBehaviour(typeof(HttpErrorHandler))]
/// ...and errors reported to ELMAH
/// </summary>
public class ServiceErrorBehaviourAttribute : Attribute, IServiceBehavior
{
    readonly Type _errorHandlerType;

    public ServiceErrorBehaviourAttribute(Type errorHandlerType)
    {
        this._errorHandlerType = errorHandlerType;
    }

    public void Validate(ServiceDescription description, ServiceHostBase serviceHostBase)
    {
    }

    public void AddBindingParameters(ServiceDescription description, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection parameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
    {
        var errorHandler = (IErrorHandler)Activator.CreateInstance(_errorHandlerType);
        foreach (var channelDispatcher in serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>())
        {
            channelDispatcher.ErrorHandlers.Add(errorHandler);
        }
    }
}



Now the HttpErrorHandler:

using Elmah;
using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;

/// <summary>
/// Your handler to actually tell ELMAH about the problem.
/// </summary>
public class HttpErrorHandler : IErrorHandler
{
    public bool HandleError(Exception error)
    {
        return false;
    }

    public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
    {
        if (error == null) return;

        ErrorLog.GetDefault(null).Log(new Error(error));
    }
}

Now it is just a simple case of adding an attribute to the WCF Service:

[ServiceErrorBehaviour(typeof(HttpErrorHandler))]
public class Game : IGame
{



Here is a small sample application showing it in action

WcfService1.zip (8.26 kb)

Removing and Cleaning search content to prevent DoS attacks

There are many ways to search a system, what we have to be careful of is making sure that the search does not cause a DoS (Denial of Service) attack.

So following on from my article Denial Of Service (DoS) attacks via SQL Wildcards should be prevented here is a method to remove and clean up the search to prevent such an attack.

using System;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections.Specialized;

public class Search
{
private readonly Regex RegexStripHtml = new Regex("<[^>]*>", RegexOptions.Compiled);

private StringCollection StopWords
{
    get
    {
        var stopWords = new StringCollection();
        // Add your stopword here, or get them from a data source
        return stopWords;
    }
}

public string CleanContent(string content, bool removeHtml)
{
    if (removeHtml)
    {
        content = StripHtml(content);
    }

    content =
        content.Replace("\\", string.Empty).Replace("|", string.Empty).Replace("(", string.Empty).Replace(
            ")", string.Empty).Replace("[", string.Empty).Replace("]", string.Empty).Replace("*", string.Empty).
            Replace("?", string.Empty).Replace("}", string.Empty).Replace("{", string.Empty).Replace(
                "^", string.Empty).Replace("+", string.Empty).Replace("%", string.Empty).Replace("_", string.Empty);

    var words = content.Split(new[] { ' ', '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries);
    var sb = new StringBuilder();
    foreach (var word in
        words.Select(t => t.ToLowerInvariant().Trim()).Where(word => word.Length > 1 && !StopWords.Contains(word)))
    {
        sb.AppendFormat("{0} ", word);
    }

    return sb.ToString().Trim();
}

private string StripHtml(string html)
{
    return StringIsNullOrWhitespace(html) ? string.Empty : RegexStripHtml.Replace(html, string.Empty).Trim();
}

private bool StringIsNullOrWhitespace(string value)
{
    return ((value == null) || (value.Trim().Length == 0));
}

Some of this code was cribbed from the BlogEngine

Here are some Unit Tests to test the CleanCode method, yes Unit Tests, this is the perfect method to perform and under how the methodworks.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using Capita.Dolphin.Web.Helpers;

/// <summary>
/// Summary description for HelperSearchTests
/// </summary>
[TestClass]
public class HelperSearchTests
{
    [TestMethod]
    public void CleanContentValidCharacters()
    {
        // Assign
        var search = new Search();
        const string expected = "hello moon";
            
        // Act
        var actual = search.CleanContent("Hello moon", false);

        // Assert
        Assert.AreEqual(expected, actual);
    }

    [TestMethod]
    public void CleanContentInValidCharacters()
    {
        // Assign
        var search = new Search();
        const string expected = "hello moon";

        // Act
        var actual = search.CleanContent("Hello moo%*([|+^}{)n", false);

        // Assert
        Assert.AreEqual(expected, actual);
    }

    [TestMethod]
    public void CleanContentRemoveHTMLCharacters()
    {
        // Assign
        var search = new Search();
        const string expected = "hello moon";

        // Act
        var actual = search.CleanContent("<p>Hello moon</p>", true);

        // Assert
        Assert.AreEqual(expected, actual);
    }

    [TestMethod]
    public void CleanContentRemoveExtraWildCardsCharacters()
    {
        // Assign
        var search = new Search();
        const string expected = "hello moon";

        // Act
        var actual = search.CleanContent("[][^]_%Hello moon</p>", true);

        // Assert
        Assert.AreEqual(expected, actual);
    }
}

MVC way to check the File Extension

Following on from my article about checking for the file signature to ensure that the file is who it says it is

I decide to take it further and produce a Data Validation attribute, I found that the Microsoft.Web.Mvc.dll library already has one ,but it only checks for the file names, which is generally okay.

So I thought I'd enhance the Microsoft FileExtension attribute, but it was sealed......!  Grrrrrrrr  But Microsoft now have most of its code as open source, yaaaaa  :-)

So I downloaded the source and created my own variation of the FileExtensionsAttribute

First we need to generate DataTypeAttribute, and IClientValidatable to inherit.

IClientValidatable

using System.Collections.Generic;
using System.Web.Mvc;

public interface IClientValidatable
{
    IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context);
}

ModelClientValidationRule

using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;

[TypeForwardedFrom("System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
public class ModelClientValidationRule
{
    private readonly Dictionary<string, object> _validationParameters = new Dictionary<string, object>();
    private string _validationType;

    public string ErrorMessage { get; set; }

    public IDictionary<string, object> ValidationParameters
    {
        get { return _validationParameters; }
    }

    public string ValidationType
    {
        get { return _validationType jQuery15201478678032162548_1380881227039 String.Empty; }
        set { _validationType = value; }
    }
}

Now the actual code for FileExtensionsAttribute

FileExtensionsAttribute

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DataValidation.Properties;

/// <summary>
/// The file extensions, default is png,jpg,jpeg,gif.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class FileExtensionsAttribute : DataTypeAttribute, IClientValidatable
{
    private string _extensions;
    private string _extensionsSignatures;

    public FileExtensionsAttribute()
        : base("upload")
    {
        ErrorMessage = DataValidationResource.FileExtensionsAttribute_Invalid;
    }

    /// <summary>
    /// The file extensions, default is png,jpg,jpeg,gif.
    /// </summary>
    /// <value>
    /// The extensions.
    /// </value>
    public string Extensions
    {
        get { return String.IsNullOrWhiteSpace(_extensions) ? "png,jpg,jpeg,gif" : _extensions; }
        set { _extensions = value; }
    }

    /// <summary>
    /// The extensions signatures, this is the fileclass signature within the actual file.
    /// </summary>
    /// <value>
    /// The extensions signatures.
    /// </value>
    public string ExtensionsSignatures
    {
        get { return String.IsNullOrWhiteSpace(_extensionsSignatures) ? "" : _extensionsSignatures; }
        set { _extensionsSignatures = value; }
    }

    private string ExtensionsFormatted
    {
        get { return ExtensionsParsed.Aggregate((left, right) => left + ", " + right); }
    }

    [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "These strings are normalized to lowercase because they are presented to the user in lowercase format")]
    private string ExtensionsNormalized
    {
        get { return Extensions.Replace(" ", String.Empty).Replace(".", String.Empty).ToLowerInvariant(); }
    }

    [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "These strings are normalized to lowercase because they are presented to the user in lowercase format")]
    private string ExtensionsSignaturesNormalized
    {
        get { return ExtensionsSignatures.Replace(" ", String.Empty).Replace(".", String.Empty).ToLowerInvariant(); }
    }

    private IEnumerable<string> ExtensionsParsed
    {
        get { return ExtensionsNormalized.Split(',').Select(e => "." + e); }
    }

    private IEnumerable<string> ExtensionsSignaturesParsed
    {
        get { return ExtensionsSignaturesNormalized.Split(','); }
    }

    public override string FormatErrorMessage(string name)
    {
        return String.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, ExtensionsFormatted);
    }

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
    {
        var rule = new ModelClientValidationRule
        {
            ValidationType = "extension",
            ErrorMessage = FormatErrorMessage(metadata.GetDisplayName())
        };
        rule.ValidationParameters["extension"] = ExtensionsNormalized;
        yield return rule;
    }

    public override bool IsValid(object value)
    {
        if (value == null)
        {
            return true;
        }

        var valueAsFileBase = value as HttpPostedFileBase;
        if (valueAsFileBase != null)
        {
            return ValidateExtension(valueAsFileBase.FileName) && ValidateFileContent(valueAsFileBase);
        }

        var valueAsString = value as string;
        return valueAsString != null && ValidateExtension(valueAsString);
    }

    [SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", Justification = "These strings are normalized to lowercase because they are presented to the user in lowercase format")]
    private bool ValidateExtension(string fileName)
    {
        try
        {
            return ExtensionsParsed.Contains(Path.GetExtension(fileName).ToLowerInvariant());
        }
        catch (ArgumentException)
        {
            return false;
        }
    }

    private bool ValidateFileContent(HttpPostedFileBase file)
    {
        var validExtensions = GetValidExtenstions();
            
        var br = new BinaryReader(file.InputStream);
        string fileclass;
        byte buffer;

        try
        {
            buffer = br.ReadByte();
            fileclass = buffer.ToString();
            buffer = br.ReadByte();
            fileclass += buffer.ToString();
        }
        catch
        {
            return false;
        }

        return string.IsNullOrWhiteSpace(ExtensionsSignatures)
            ? ExtensionsParsed.Where(validExtensions.ContainsKey).Any(extension => validExtensions[extension].ToString() == fileclass) 
            : ExtensionsSignaturesParsed.Any(extensionsSignatures => extensionsSignatures == fileclass);
    }

    private Dictionary<string, int> GetValidExtenstions()
    {
        var validExtenstions = new Dictionary<string, int>
                                    {
                                        {".gif", 7173},
                                        {".jpg", 255216},
                                        {".png", 13780},
                                        {".bmp", 6677},
                                        {".txt", 239187},
                                        {".aspx", 239187},
                                        {".asp", 239187},
                                        {".sql", 239187},
                                        {".xls", 208207},
                                        {".doc", 208207},
                                        {".docx", 208207},
                                        {".dot", 208207},
                                        {".dotx", 208207},
                                        {".ppt", 208207},
                                        {".xml", 6063},
                                        {".html", 6033},
                                        {".js", 4742},
                                        {".xlsx", 8075},
                                        {".zip", 8075},
                                        {".ptx", 8075},
                                        {".mmap", 8075},
                                        {".rar", 8297},
                                        {".accdb", 01},
                                        {".mdb", 01},
                                        {".exe", 7790},
                                        {".dll", 7790},
                                        {".bat", 64101},
                                        {".tiff", 7373},
                                        {".tif", 7373}
                                    };
        return validExtenstions;
    }
}

You'll notice the ValidateFileContent method which is the additional feature I've added to check for the file signature.

That's it job done

A sample project can be found here

FileUploader.zip (9.24 mb)

File Upload does not check content

Is it possible to upload files of any type to the server through web application’s functionality?

Only file extension restrictions were could be enforced and the server may not perform any content checking (apart from possible anti-virus checks).

At the very least, a rudimentary check of the file content/headers must be made to ensure that the file extension does relate to the file content and that both are acceptable for uploading into the system.

Ideally the file content must be checked to ensure no malicious scripts or macros in word documents are present.

Recommendation:

All uploaded files should be thoroughly scanned and validated before being made available to other users.

If in doubt, the file should be discarded. Ideally, only files of certain types should be allowed and checking for file types should be done by the server for their content and file extensions, Content-Encoding or Content-Type headers should not be relied upon.

I've produced a simple application that checks for file signature when upload that can be used

http://bryanavery.co.uk/post/2013/06/25/Determine-which-file-type-has-been-uploaded.aspx

Anothe rsource of reference can he found here:

http://stackoverflow.com/questions/58510/using-net-how-can-you-find-the-mime-type-of-a-file-based-on-the-file-signature

SSL Vulnerable to BEAST attack

A vulnerability exists in SSL 3.0 and TLS 1.0 that could allow information disclosure if an attacker intercepts encrypted traffic served from an affected system. The weakness is down to insufficiently randomised data being used for the Initialisation Vectors (IV) within the CBC-mode encryption algorithms. The exploit can be performed through multiple injection points, both native to the browser’s functionality.

This issue is reduced in risk by the fact that the attacker is required to have a Man-in-the-Middle position for this exploit whereby traffic interception can be performed, and with this position obtained it is generally easier to attack the victim through other methods (SSL-stripping, mixed-scripting [requesting HTTP resources from an HTTPS connection], etc…) which do not require complex cryptanalysis such as BEAST to execute.

TestSSLServer.exe (43.00 kb)

http://www.bolet.org/TestSSLServer/

 

Supported versions:
 SSLv2 SSLv3 TLSv1.0
Deflate compression: no
Supported cipher suites (ORDER IS NOT SIGNIFICANT):
  SSLv2
     RC4_128_WITH_MD5
     DES_192_EDE3_CBC_WITH_MD5
  SSLv3
     RSA_WITH_RC4_128_MD5
     RSA_WITH_RC4_128_SHA
     RSA_WITH_3DES_EDE_CBC_SHA
  TLSv1.0
     RSA_WITH_RC4_128_MD5
     RSA_WITH_RC4_128_SHA
     RSA_WITH_3DES_EDE_CBC_SHA
     RSA_WITH_AES_128_CBC_SHA
     RSA_WITH_AES_256_CBC_SHA
     TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
     TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
----------------------
Server certificate(s):
  0edc8b5e2d1e4c803319c3e4e80dd9945d953db2: CN=application.local.someone.zone
----------------------
Minimal encryption strength:     strong encryption (96-bit or more)
Achievable encryption strength:  strong encryption (96-bit or more)
BEAST status: vulnerable
CRIME status: protected

Recommendation:

Client-side:

Various browsers are introducing or have introduced mitigations for the issue which make exploitation less likely. There are also steps which can be taken on the server side to make exploitation impossible.

Server-side:

Enabling and prioritising TLS 1.1/1.2 would be advised where possible although removing support for TLS1.0 is impractical at this time.

In the short-term due to the lack of wide-scale support by browsers and servers alike, prioritising the use of a stream cipher (such as RC4-SHA) instead of a CBC-mode cipher is recommended in order to maintain compatibility with browsers (see note).

Migration away from TLS 1.0 and below to TLS 1.1/1.2 should considered as a medium-term option for secure applications.

SSL Best Practice Guide:

https://www.ssllabs.com/projects/best-practices/index.html

BEAST attack

On September 23, 2011 researchers Thai Duong and Juliano Rizzo demonstrated a "proof of concept" called BEAST ("Browser Exploit Against SSL/TLS") using a Java applet to violate same origin policy constraints, for a long-known Cipher block chaining (CBC) vulnerability in TLS 1.0.[44][45] Practical exploits had not been previously demonstrated for this vulnerability, which was originally discovered by Phillip Rogaway[46] in 2002. The vulnerability of the attack had been fixed with TLS 1.1 in 2006, but TLS 1.1 had not seen wide adoption prior to this attack demonstration.

Mozilla updated the development versions of their NSS libraries to mitigate BEAST-like attacks. NSS is used by Mozilla Firefox and Google Chrome to implement SSL. Some web servers that have a broken implementation of the SSL specification may stop working as a result.

Microsoft released Security Bulletin MS12-006 on January 10, 2012, which fixed the BEAST vulnerability by changing the way that the Windows Secure Channel (SChannel) component transmits encrypted network packets.

Users of Windows 7 and Windows Server 2008 R2 can enable use of TLS 1.1 and 1.2, but this work-around will fail if it is not supported by the other end of the connection and will result in a fall-back to TLS 1.0.

Verbose Error Messages

The software generates an error message that includes sensitive information about its environment, users, or associated data. 

Extended Description

The sensitive information may be valuable information on its own (such as a password), or it may be useful for launching other, more deadly attacks. If an attack fails, an attacker may use error information provided by the server to launch another more focused attack. For example, an attempt to exploit a path traversal weakness might yield the full pathname of the installed application. In turn, this could be used to select the proper number of ".." sequences to navigate to the targeted file. An attack using SQL injection might not initially succeed, but an error message could reveal the malformed query, which would expose query logic and possibly even passwords or other sensitive information used within the query.

Recommendation

Suppress these error messages by ensuring that a customised error handler is called in the event of an error. This can produce a generic message which does not hint at the underlying cause of the exception.

References

OWASP – Error Handling
http://www.owasp.org/index.php/Improper_Error_Handling

How to: Display Safe Error Messages

When your application displays error messages, it should not give away information that a malicious user might find helpful in attacking your system. For example, if your application unsuccessfully tries to log in to a database, it should not display an error message that includes the user name it is using.

There are a number of ways to control error messages, including the following:

Configure the application not to show verbose error messages to remote users. (Remote users are those who request pages while not working on the Web server computer.) You can optionally redirect errors to an application page.

Include error handling whenever practical and construct your own error messages. In your error handler, you can test to see whether the user is local and react accordingly.

Create a global error handler at the page or application level that catches all unhandled exceptions and routes them to a generic error page. That way, even if you did not anticipate a problem, at least users will not see an exception page.

To configure the application to turn off errors for remote users

In the Web.config file for your application, make the following changes to the customErrors element:

  • Set the mode attribute to RemoteOnly (case-sensitive). This configures the application to show detailed errors only to local users (that is, to you, the developer).
  • Optionally include a defaultRedirect attribute that points to an application error page.
  • Optionally include <error> elements that redirect specific errors to specific pages. For example, you can redirect standard 404 errors (page not found) to your own application page.

The following code example shows a typical customErrors block in the Web.config file.

<customErrors mode="RemoteOnly" defaultRedirect="AppErrors.aspx">
   <error statusCode="404" redirect="NoSuchPage.aspx"/>
   <error statusCode="403" redirect="NoAccessAllowed.aspx"/>
</customErrors>

Environment issue - Untrusted Certificate

Certificate is singed by an unrecognised certificate authority.  If a browser receives a self-signed certificate, it pops up a warning, and the burden falls to the user to confirm the identity.  Pushing this decision to the user is ultimately what opens up the possibility of a man-in-the-middle (MITM) attack.  The security issue is not with self-signed certificates, but with the way users interact with them in the browser.

Recommendation:


Purchase or generate a proper certificate for this service.

Check out, for Mand in the middle

http://www.schneier.com/blog/archives/2010/04/man-in-the-midd_2.html

You can purchase SSL certificates from Symantec

https://www.symantec.com/en/uk/verisign/ssl-certificates/secure-site

Denial Of Service (DoS) attacks via SQL Wildcards should be prevented

SQL Wildcard attacks force the underlying database to carry out CPU-intensive queries by using several wildcards. This vulnerability generally exists in search functionalities of web applications. Successful exploitation of this attack will cause Denial of Service (DoS).

Depending on the connection pooling settings of the application and the time taken for attack query to execute, an attacker might be able to consume all connections in the connection pool, which will cause database queries to fail for legitimate users.

By default in ASP.NET, the maximum allowed connections in the pool is 100 and timeout is 30 seconds. Thus if an attacker can run 100 multiple queries with 30+ seconds execution time within 30 seconds no one else would be able to use the database related parts of the application.

Recommendation

If the application does not require this sort of advanced search, all wildcards should be escaped or filtered.

References:

OWASP Testing for SQL Wildcard Attacks

https://www.owasp.org/index.php/Testing_for_SQL_Wildcard_Attacks_(OWASP-DS-001)

DoS Attacks using SQL Wildcards

http://www.zdnet.com/blog/security/dos-attacks-using-sql-wildcards-revealed/1134

Brief Summary

SQL Wildcard Attacks are about forcing the underlying database to carry out CPU-intensive queries by using several wildcards. This vulnerability generally exists in search functionalities of web applications. Successful exploitation of this attack will cause Denial of Service.

Description of the Issue

SQL Wildcard attacks might affect all database back-ends but mainly affect SQL Server because the MS SQL Server LIKE operator supports extra wildcards such as "[]","[^]","_" and "%".

In a typical web application, if you were to enter "foo" into the search box, the resulting SQL query might be:

SELECT * FROM Article WHERE Content LIKE '%foo%'

In a decent database with 1-100000 records the query above will take less than a second. The following query, in the very same database, will take about 6 seconds with only 2600 records.

SELECT TOP 10 * FROM Article WHERE Content LIKE '%_[^!_%/%a?F%_D)_(F%)_%([)({}%){()}£$&N%_)$*£()$*R"_)][%](%[x])%a][$*"£$-9]_%'

So, if the tester wanted to tie up the CPU for 6 seconds they would enter the following to the search box:

_[^!_%/%a?F%_D)_(F%)_%([)({}%){()}£$&N%_)$*£()$*R"_)][%](%[x])%a][$*"£$-9]_

Black Box testing and example

Testing for SQL Wildcard Attacks:

Craft a query which will not return a result and includes several wildcards. You can use one of the example inputs below.

Send this data through the search feature of the application. If the application takes more time generating the result set than a usual search would take, it is vulnerable.

Example Attack Inputs to send

    '%_[^!_%/%a?F%_D)_(F%)_%([)({}%){()}£$&N%_)$*£()$*R"_)][%](%[x])%a][$*"£$-9]_%'
    '%64_[^!_%65/%aa?F%64_D)_(F%64)_%36([)({}%33){()}£$&N%55_)$*£()$*R"_)][%55](%66[x])%ba][$*"£$-9]_%54' bypasses modsecurity
    _[r/a)_ _(r/b)_ _(r-d)_
    %n[^n]y[^j]l[^k]d[^l]h[^z]t[^k]b[^q]t[^q][^n]!%
    %_[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[! -z]@$!_%

...

Result Expected

If the application is vulnerable, the response time should be longer than usual.

SQL Wildcard attacks force the underlying database to carry out CPU-intensive queries by using several wildcards. This vulnerability generally exists in search functionalities of web applications. Successful exploitation of this attack will cause Denial of Service.

Here, it was possible to search by keying in a value for the forename/firstname field as M__E (i.e. M underscore underscore E) and the search returned results treating the two underscores as wildcards for any two characters.

This may still exist on the current code base so it's a case of going through the forms and ensuring that it doesn't occur / fix it if the vulnerability exists.

DoS Attacks Using SQL Wiltcards.pdf (567.23 kb)

Check the solution I have produced to prevent this Removing and Cleaning search content to prevent DoS attacks

HTTP Header Disclosure

Vulnerability overview/description

Due to unsanitized user input it is possible to inject arbitrary HTTP header values in certain HTTP responses of the Satellite Server. This can be exploited, for example, to perform session fixation and malicious redirection attacks via the Set-Cookie and the Refresh headers. Moreover, the Satellite Server caches these HTTP responses with the injected HTTP header resulting in all further requests to the same resource being served with the poisoned HTTP response, while these objects remain in cache.

Information Disclosure

Information disclosure enables an attacker to gain valuable information about a system. Therefore, always consider what information you are revealing and whether it can be used by a malicious user. The following lists possible information disclosure attacks and provides mitigations for each. 

Message Security and HTTP

If you are using message-level security over an HTTP transport layer, be aware that message-level security does not protect HTTP headers. The only way to protect HTTP headers is to use HTTPS transport instead of HTTP. HTTPS transport causes the entire message, including the HTTP headers, to be encrypted using the Secure Sockets Layer (SSL) protocol.

http://msdn.microsoft.com/en-us/library/aa738441.aspx 

Environment change

The web application returned information about itself in the HTTP header that could aid an attacker.  Default web server installations often include the vendor and version details of the web application, and possibly further information about scripting services also installed

User Enumeration - Login failure messages shouldn't give out any information that results in vulnerabilities.

Is it possible to enumerate user account details within the Web application via the logon page?

Where an application requires account details to retrieve other information, it may be possible to enumerate the details based on the error message returned by the application.

In this case it was also possible to determine the state of the user account

Recommendation:

Messages which allow an attacker to enumerate account details should be removed. A generic error message which does not disclose information about account information should be used.

References:

OWASP Testing for user enumeration

https://www.owasp.org/index.php/Testing_for_user_enumeration_(OWASP-AT-002)

Enumeration

  • Enumeration is the first attack on target network, enumeration is the process to gather the information about a target machine by actively connecting to it.
  • Enumeration means to identify the user account, system account and admin account. Enumerating windows active directory to find out these stuffs.
  • Discovering NetBIOS name enumeration with NBTscan.
  • Establishing null sessions and connections. Null sessions tools like Dumpsec, Winfo and Sid2User or more, may used to perform this attack.

The login failure messages can give away too much information and it would be possible to enumerate user details via the log-on page. It reports on whether an account exists/not and if an account is locked out or not etc.

There should ideally be just one generic message that's of no use to a potential hacker.

- See more at: http://www.ehacking.net/2011/04/scanning-and-enumeration-second-step-of.html#sthash.B3KW4Kcs.dpuf

Other Considerations

You'll need to log somewhere in your application the actual reasons why the user could not login, this could be that the account is locked, suspened, deleted etc. 

By logging this information a system adminstrator or the like can see why a user could not get access to the application through the login page.

About the author

You have probably figured out by now that my name is Bryan Avery (if not, please refer to your browser's address field).  Technology is more than a career to me - it is both a hobby and a passion.  I'm an ASP.NET/C# Developer at heart...

Month List