Archive for June, 2008

Let me see that certificate a little more closely. Part 1 – Validating the Server’s Certificate

June 11th, 2008 by Brian Lewis

If you are developing a client to a server service that communicates over SSL such as a Web Service then it is your job to ensure your server is the "real deal" and not some rouge server or man-in-the-middle. How do you do that? Validate the server's certificate. Make sure the certificate is for the domain you are accessing, make sure the certificate chain is valid, and make sure the certificate is signed by a trusted certificate authority (CA). Sound like a pain? Well it isn't. You get a lot for a little with the right API calls.

WinHttpReceiveResponse in C++ will return FALSE if the certificate has one of the following errors:

WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED

Certification
revocation checking has been enabled, but the revocation check failed to verify
whether a certificate has been revoked. The server used to check for revocation
might be unreachable.

WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT

SSL certificate is invalid.

WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED

SSL certificate was revoked.

WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA

The function is unfamiliar with the Certificate Authority that generated the server's certificate.

WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID

SSL certificate common name (host name field) is incorrect, for example, if you entered www.microsoft.com and the common name on the certificate says www.msn.com.

WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID

SSL certificate date that was received from the server is bad. The certificate is expired.

WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR

The application experienced an internal error loading the SSL libraries.

However, WinHttpReceiveResponse does not return these errors directly as a call to GetLastError() will only return ERROR_WINHTTP_SECURE_FAILURE if there is a problem with the server's certificate. You must use the CallBack WINHTTP_STATUS_CALLBACK to access the specific errors listed above.


public WINHTTP_STATUS_CALLBACK myOwnAsyncCallback( __in HINTERNET hInternet,
__in DWORD_PTR dwContext,
__in DWORD dwInternetStatus,
__in LPVOID lpvStatusInformation,
__in DWORD dwStatusInformationLength)
{
if (dwInternetStatus == WINHTTP_CALLBACK_STATUS_SECURE_FAILURE)
// We have a certificate issue but which one? Take action before each break. This function must be thread safe and reentrant.
switch(*(DWORD*)lpvStatusInformation)
{
case WINHTTP_CALLBACK_STATUS_FLAG_CERT_REV_FAILED:
break;
case WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CERT:
break;
case WINHTTP_CALLBACK_STATUS_FLAG_CERT_REVOKED:
break;
case WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA:
break;
case WINHTTP_CALLBACK_STATUS_FLAG_CERT_CN_INVALID:
break;
case WINHTTP_CALLBACK_STATUS_FLAG_CERT_DATE_INVALID:
break;
case WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR:
break;
}
}
HINTERNET hSession = WinHttpOpen(L"A WinHTTP Example Program/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
WINHTTP_STATUS_CALLBACK isCallback = WinHttpSetStatusCallback( hSession, WINHTTP_STATUS_CALLBACK)myOwnAsyncCallback,WINHTTP_CALLBACK_FLAG_SECURE_FAILURE,
NULL);
//The rest of your code including call WinHttpReceiveResponse

For more information see
http://msdn.microsoft.com/en-us/library/cc185684(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa383917(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa384266(VS.85).aspx
http://msdn.microsoft.com/en-us/library/aa384115(VS.85).aspx

useUnsafeHeaderParsing = what?

June 5th, 2008 by Chris Weber

As software security people we usually like input restrictions to be tight. With .Net's HttpWebRequestElement.UseUnsafeHeaderParsing Property you can loosen up the way HTTP requests get parsed.

Setting this property ignores validation errors that occur during HTTP parsing. The documentation from MSDN makes it pretty clear. When this property is set to 'true' then many HTTP RFC violations will be relaxed and ignored.

When this property is set to false, the following validations are performed during HTTP parsing:

* In end-of-line code, use CRLF; using CR or LF alone is not allowed.
* Headers names should not have spaces in them.
* If multiple status lines exist, all additional status lines are treated as malformed header name/value pairs.
* The status line must have a status description, in addition to a status code.
* Header names cannot have non-ASCII chars in them. This validation is performed whether this property is set to true or false.

When a protocol violation occurs, a WebException exception is thrown with the status set to ServerProtocolViolation. If the UseUnsafeHeaderParsing property is set to true, validation errors are ignored.

Setting this property to true has security implications, so it should only be done if backward compatibility with a server is required.

Let's keep an eye out for this option when it's set either programmatically or through web.config.


<configuration>
<system.net>
<settings>
<httpWebRequest useUnsafeHeaderParsing=”true” />
</settings>
</system.net>
</configuration>

Powershell Grep

June 3rd, 2008 by John Hernandez

So, I spent a good couple of hours today trying to find a easy solution to the lack of Grep on windows. I've tried using findstr but the output gave me a headache trying to parse it. So I decidied to use powershell, what a great tool by MS, once you get past the learning curve obviously.

Here is my code for grep the way i like it. I just created a PS1 file and added it to my “bin” dir… which is just a directory mapped to my path variable for command line programs. Anyways this looks through code files only based on the $filetypes… handy.. really it is…

$searchstr = $args[0]
$searchdir = $args[1]

$filetypes = “*.cpp”, “*.hpp”, “*.c”, “*.h”, “*.cxx”, “*.hxx”, “*.cs”, “*.aspx”,”*.asmx”, “*.html”, “*.js”, “*.vbs”, “*.vb”, “*.xml”, “*.txt”

if($searchdir -eq “” )
{
$searchdir = “.\”
}

get-childitem $searchdir -include $filetypes -recurse | select-string -pattern $searchstr | Format-Table -property FileName, LineNumber, Line -Autosize