Archive for the ‘Security Testing’ Category

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

IE Shortcuts for debugging 3rd party applications..

May 2nd, 2008 by admin

This is mostly a reminder for myself. But here are some useful shortcuts/tips for working in IE.

CTRL-I : brings up the favorites menu, this is useful on those pop-ups that dont have upper menus to enable right clicking for viewing source…

Bookmarklet for enabling right click: javascript:void(document.oncontextmenu=null)

Bookmarklelt for enabling the Firebug Lite console: http://remysharp.com/2007/03/13/firebug-in-ie-for-any-web-site/

Also another useful setting is setting in ie options that new windows open in tabs verse a pop up. This helps by
allowing you to quickly/easily access bookmarklets/plug-ins like ie dev bar.

How safe is the safecrt handling of formatting strings?

April 25th, 2008 by Jordan Tigani

One rule of thumb in c/c++ is that you should never let the user be in control of a formatting string. This has been recognized as a security bug for years, and one that has been mostly cleaned up since it is so easy to identify and fix. With visual studio 2005, Microsoft released a safer version of the crt — functions that end with _s to tell you that they are security enhanced. So let's say you are being a good security citizen by using the safe-crt …. can a format string vulnerability (where the user controls the format string) still be exploited?

The MSDN docs don't really have the answer. A cursory reading of the “security enhancements in the CRT” page as well as others may lead you to believe that format string vulnerabilities are a thing of the past. One example shows a call to 'sprintf_s(buf,_countof(buf), “%s”,NULL)' and remarks that this results in a runtime error. Looks like they do some kind runtime-validation. However, unless they added magic pixie dust to their compiler that sends cosmic rays from outer space to fix up malicious format strings at runtime, it isn't really possible to have strongly-typed printf-style format strings in C.

So let's investigate how far the parameter validation will get you. Here is a little sample program I wrote to send nasty format strings to sprintf_s:


#include
#define OUT_SIZE 0x1000
int main(int argc, char** argv) {
char * out = new char[OUT_SIZE];
sprintf_s(out, OUT_SIZE, OUT_SIZE, argv[1]);
printf("%s\n", out);
return 0;
}

So let's try this with a couple of format strings:

Input: "%s"
Output: Error: ("Buffer too small", 0)

So far so good… but buffer too small?
What about just dumping stack variables?

Input: "%p %p %p %p %p %p"
Output: 00344FD0 00344FD0 0012FFB8 004019D3 00000002 00343728

Interesting… so looks like this type checking is not so robust after all. We've just dumped the stack.
Let's see if we can crash the program. Looks like there is a 0000002 on the stack… that probably won't appreciate being dereferenced.

Input: "%p %p %p %p %s"


Ok so we can crash the program. Can we do anything more interesting?
Let's say there was some interesting data somewhere in the program. To simulate this, I'll put my bank account number on the stack with the following line of code at the beginning of “main” “volatile char * bankAccount = “Account#123-456-7890″;” (the volatile helps convince the compiler not to throw it away since I don't use it).

Now when I call the function with the right input, I can dump my bank account number:

Input: test.exe "%p %s"
Output: 00344FD0 Account#123-456-7890 00344FD0

Ok but nobody really cares about Denial-of-service and Information-disclosure. Those are sooooo pri-3. Can we use take over the machine? As everyone knows, the hacker's favorite format string character is '%n'. '%n' writes the number of bytes written so far to the param from the stack. Let's try a '%n':

Input: test.exe "%p %n"
Output: Error: (state != ST_INVALID)

Blast! Foiled! It turns out Microsoft decided that %n was too much power, and that we mere mortals couldn't handle it. Good for them. There is an override, but it turns out to not be available using the Safe CRT. The moral of the story? The safe crt is a wonderful and powerful tool to help prevent buffer overruns. But there is no excuse for letting a user control a format string.

Handling Unicode when marshalling from .Net to a platform invoke

April 22nd, 2008 by Chris Weber

By default, the .Net runtime will marshall a string (and files in a value type) as a LPStr to a platform invoke (p/invoke) function. By default the .Net framework and runtime handles strings as UTF-16. That's two bytes representing a single Unicode 'code point', and more familiar, a single character. An LPStr on the other hand, is an ANSI character, so in order to convert, the runtime will perform a best-fit conversion to the classic windows-1252 code page. This conversion is well-documented here:

http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WindowsBestFit/bestfit1252.txt

This might not be so surprising to people in tune with Unicode, but it's can lead to huge security problems when security filters are at risk. For example, if you're performing HTML filtering or file canonicalization, you need to perform so after the conversion to LPStr.

This default marshalling behavior is documented at: http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.marshalasattribute(VS.71).aspx

To properly and more safely deal with this, you can use the MarshallAsAttribute class to specify a LPWStr type instead of a LPStr. For example:

[MarshalAs(UnmanagedType.LPWStr)]

Because LPWStr is a pointer to a null-terminated array of Unicode characters, this ensures the Unicode code points are preserved across the marshalling.

Open redirects – what’s the problem?

March 2nd, 2008 by Chris Weber

Been getting this question a bit lately. First off, what's an open redirect? It's a function in your application which sends the user to some other location. The redirect could be a response from the server, such as an HTTP 301 or 302 response code, or a META redirect. The redirect can be delivered in several forms, the important part is that when an attacker can control the redirect location, they can exploit it for nefarious purposes – usually this means spam or phishing attacks.

For example, your application takes a request from the user, maybe it's a GET request for a certain page. Included in the request is a value indicating the location where the user should be redirected once they've finished on the page. So, the user requests a page like:

http://somesite.tld/page.aspx?name=value&returnUrl=http://somesite.tld/referringpage.aspx

As you can see, the returnUrl takes a value of the redirect location. Then your code acts on it somewhere by redirecting the user with something like:

Response.Redirect(returnUrl);

Spammers and phishers love this, it gives them good camouflage. For example:

http://somesite.tld/page.aspx?name=value&returnUrl=http://evil.tld/installMalware.bad

Now imagine the spammer has crafted up a nice email that looks like it originates from somesite.tld, includes all the logos, fonts, etc. They coerce the victim into clicking this link by saying something like “your account needs immediate attention” or “you've won 500 points”. User clicks the link, gets redirected to evil.tld, and may not realize that the domain has switched before they say Yes to install the thing that the spammer wants them to download.

Tricky, right. In fact this is a favorite of spam, malware, and phish, next to the old XSS bug.

What's the solution
Well, simply, don't redirect openly, rather, implement a SafeRedirect() function that looks something like:


public static SafeRedirect(string url) {
// check that protocol is either http:// https:// ftp:// or other specific protos you want to allow
// check that domain is in fact yourdomain.tld
// If these checks pass, then you can go ahead
Response.Redirect(returnUrl);
// If the checks fail, you can try to clean up the URL, but probably best to just fail and redirect to a safe landing page
}

That's about all there is too it.

Using ASP.Net session handling with secure sites (set the secure flag)

February 4th, 2008 by Samuel Bucholtz

One of the common problems we see with many web applications is reliance on ASP.Net sessionID without understanding the security ramifications. ASP.Net provides web developers with a powerful means of tracking user state and identity with very little coding. Rather than creating your own custom authentication cookie, handling the trickiness of forms auth or mapping your cookie to a Windows identity, password policy implementation, not to mention creating server objects to store the state for a given user, ASP.net does it all for you.

ASP.Net offers two methods of tracking session state- URL or cookie. URL based methods are used in cases where it is expected that some users will have disabled cookies and still need a server-side session to track state. This has become less common as more and more of the web relies on cookies. In addition the URLs look ugly and are considered unacceptableby many usability gurus.

The second method is a cookie sent as a header to the server. This cookie is sent over HTTP or HTTPS and is used by ASP.net to link an incoming request to the server-side state. So you are running your site on SSL, where is the problem? By default, the SessionID is just a cookie the browser sends it when making any response to the domain. If you go to https://yourapp/application, you will be sent a cookie over SSL that I cannot see. If I e-mail you a link to click for http://yourapp/application, I will see the cookie sent over HTTP as long as your server responds on port 80.

What you want to do is set the 'secure' flag on the cookie. You have many options for doing this: adsutil set w3svc/1/AspKeepSessionIDSecure 1 will tell ASP.net to mark the session cookie as Secure. When a cookie is marked as secure it will not be sent by the web browser unless the connection to the server is over https. You must be aware that the user will now have no session state if they browse to the site using http your application will need to redirect http requests to https in order to access the session state.

Is the ASP.Net session ID the only cookie I can protect in this way? No. You can use a web.config configuration to customize the security of all your cookies (http://msdn2.microsoft.com/en-us/library/ms228262.aspx). You will also be able to set cookies to be HttpOnly which adds its own element of security and is supported by newer browsers.

Finally, you can set both the secure flag and the HttpOnly flag for any other cookies you set programmatically through ASP.Net with http://msdn2.microsoft.com/en-us/library/ms228262.aspx.

A few other things to remember-

ASP.Net sessions expire after 20 minutes UNLESS a new request is seen. Otherwise they can remain until the server is recycled.

SessionIDs can be reused. When stored as a cookie the sessionID will go to any machine hosting the same parent domain. They will NOT have the server-side state though unless some clustering or back-end logic handles sharing state across servers. If you want to ensure that reuse does not happen, rather than using Session.Abandon you must overwrite the ASP.Net session cookie with an empty cookie value. To properly end a session or force a user to start a new one use Session.Abandon.

For more information checkout – http://msdn2.microsoft.com/en-us/library/ms972969.aspx

Whatever happened to?

January 16th, 2008 by Samuel Bucholtz

One of the most useful sites on the Internet was the Ports Database at http://www.portsdb.org

Unfortunately it went missing over a year ago and has not returned. The best alternative I have found is using the IANA list at http://www.iana.org/assignments/port-numbers and doing a manual search. Not ideal, but it works. Maybe we will put a little database up on this site in the future.

New risks for old credentials

January 16th, 2008 by Samuel Bucholtz

I was playing around with my Tivo this weekend and realized that many of the new features being offered on Tivo are handy but leave valuable information stored on your Tivo.

How so?

Well, Tivo now offers Amazon Unbox downloads, Yahoo Weather/Traffic, etc. All of these services require you to store your credentials on the device or on Tivo's website. Imagine what might happen if an attacker can break into the device and gather such information. With an Amazon account an attacker has access to any stored credit cards for purchases on the site. Even if an attacker cannot hack into your private network and break into the Tivo, what happens when the Tivo is put into the trash at the end of its life?