Friday, July 1, 2011

Account Lockout Fail

A while back I was hunting for vulnerabilities in a web app's Forgot Password feature. On the first page you had to enter your username and email address. The second page asked a personal security question. That is quite weak. I recommend asking for at least 3 pieces of data on the first step. Asking for only two inputs, especially when they are username and email address, is not very secure. Username and email address are often related. If you know one, you might be able to guess the other. For example, the email address for user "jthomas" could be "jthomas@yahoo.com". I also recommend asking two personal security questions on the second page, not just one.

Anyway, one of the things I like to check is whether or not the account is locked after a certain number of failed attempts to answer the security question(s). This is an important defense against attackers who are trying to break in via the Forgot Password functionality. Sure enough, the message "account has been locked" appeared after I purposefully entered 3 wrong answers.

I was just about to make a note about this commendable practice, but something caught my eye. The input field was still there on the page. That's not something you normally see. Usually the application takes it away after a lockout occurs. So being a curious fellow, I proceeded to enter the correct answer to the question. Lo and behold the application sent me to the next page where I was allowed to reset the password on the account. Now that's an account lockout fail! I'm not sure why or how the developers created a lockout message without actually coding the lockout. Just another example of how difficult app security can be.

Thursday, April 21, 2011

Blackhole Exploit Kit

Something I found surprising at first when learning about real-world SQL injection attacks on web applications is that hackers will strive to insert data into the database, not necessarily try to extract data from it. Why would they do this? They want to inject JavaScript code. Basically, the goal is to leverage SQL injection to create a stored XSS attack on application users. It really shows you how supremely dangerous stored XSS vulnerabilities are, huh?

If successful, the malicious JavaScript code will execute in users' browsers. This is bad. Think of it as executable code, chosen by an attacker, running on a victim's computer. One example of the nastiness that can result is the Blackhole Exploit Kit. This malware originated in Russia and is openly for sale. Blackhole is designed to compromise victim computers by exploiting known vulnerabilities in certain software products like Adobe Reader or Java. Symantec researchers have provided a nice writeup of how Blackhole works. Typically, the badness begins with an iframe (created by JavaScript of course) that points to a Blackhole server.

A U.S. Postal Service website was recently found to have been compromised with Blackhole. There is some question how it happened. Regardless, the thing to keep in mind is that a web application that allows for SQL injection might very well lead to stored XSS attacks.

Sunday, March 6, 2011

Educational Videos about Web Application Security

A terrific and free resource for introducing developers to web application security concepts is a video tutorial series from OWASP. Jerry Hoff is the leader on this tutorial project. The first two episodes are complete - AppSec Basics and Injection Attacks. The videos are very well done, with nice graphics, sound, and animation.

Saturday, September 11, 2010

Latest Forgot Password Best Practices Doc

A new version of my white paper entitled "Best Practices for a Secure Forgot Password Feature" is available. You can download the white paper here. No significant changes were made in terms of content, but it does have fewer pages and a more pleasing look now. The link I had given out previously is no longer valid.

The white paper was used as the basis for the OWASP Forgot Password Cheat Sheet.

Wednesday, September 8, 2010

Password Complexity Rules

A Consumer Reports blogger has been taking Facebook to task for allowing certain dictionary words to be used as passwords (he found 20 of them). I can't confirm that Facebook actually forbids the use of dictionary words like the blogger claims. The signup page did not reject the word "animal" when I tried it, and their password strength FAQ does not state that dictionary words are banned.

The flak got me to thinking about password complexity rules in general. It needs to be evaluated when assessing the security posture of a web application. I see huge variety in the password rules that are being used. That's not the problem. It makes sense that highly sensitive applications, such as financial or governmental, should enforce stricter requirements. The problem I see is that the password rules simply aren't strong enough, ever. Identifying this weakness calls for a manual test or a code review. It is not something a web app scanner like WebInspect or AppScan would flag. Maybe that's part of the problem.

Below are the password rules I normally recommend for Internet-facing web applications.
  • Minimum password length of 7
  • Allow passwords to be 50 characters or more in length
  • Require at least one uppercase letter
  • Require at least one lowercase letter
  • Require at least one number
  • Allow special characters
  • Do not allow any part of username to appear in the password
  • Do not allow the user's first or last name to appear in the password
  • Do not allow any form of the word “password”
  • Do not allow the same character three or more times in succession
Notice there is nothing about banning dictionary words (other than a number being required). Applications can mitigate that particular risk by using an account lockout mechanism to prevent automated password guessing. Also, it probably goes without saying, but passwords should be case sensitive.

Please let me know if you have any other suggestions on this subject!

Friday, May 28, 2010

Bug Editing Cookies in Web Developer Extension

Just a quick note I've been meaning to post about a small bug in Chris Pederick's Firefox Web Developer extension. It is a fantastic extension and I use it all the time, especially for working with cookies. Kudos to Mr. Pederick!

Unfortunately, what I noticed is that if you have "accept third-party cookies" unchecked in Firefox's privacy options, you can't edit cookies or add cookies. In fact it ends up deleting the cookies that you try to edit. D'oh!

This bug bit me a few times when I was trying to demonstrate session hijacking while teaching an application security class. This bug is a known issue and I'm hoping Chris can find a way to make it work in the next version. In the meantime, I will keep using the extension and trying to remember to enable third-party cookies whenever I teach the class.

Monday, May 17, 2010

A Case for HttpOnly

Last month the Apache Infrastructure Team fell victim to a common web application attack. Rather than keep the information secret, they were kind enough to explain how the attack occurred. The initial attack leveraged cross-site scripting to steal users' session IDs. This is something that could have been prevented if the web app's session cookie had been marked with the HttpOnly attribute. When a web app sets a cookie, the presence of HttpOnly instructs browsers to disallow client-side script from accessing the cookie.

You will sometimes hear or read that HttpOnly helps prevent XSS attacks. That is not quite true. It helps prevent session hijacking. Specifically, it helps guard against one attack vector, namely where session cookies are stolen via XSS. HttpOnly can be used for any sensitive cookie that you don't want falling into the hands of fraudsters. (I should use "fraudster" more often - it is a fun word)

There is one caveat to using HttpOnly. It might break your application if it was written in such a way that the functionality depends on JavaScript having access to the cookie. That is fairly uncommon however.

Wednesday, May 12, 2010

Dynamically-Generated PDFs

Many web applications will generate PDF files for users so they can view nicely-formatted statements, reports, etc. These dynamically-generated PDFs are typically accessed by users in two different ways.

1) The application creates an actual PDF file on the server and redirects the user's browser to the file (via 302 response code).

2) The application streams the bytes for the PDF directly to the user's browser as part of the HTTP response.

This second method is much more secure. The reason is that a PDF file sitting on a server can probably be accessed by anyone. The only information needed is the directory and the file name. That said, I have seen the first method implemented securely, but two important mitigating factors were employed. First, the application used randomized file names. A globally-unique identifier (GUID) is great for this. Second, the files were deleted within about 10 seconds of them being created. These two factors, when combined, made it almost impossible to gain access to another user's PDF file.

Testing for this vulnerability is simple. If you run across an application that allows you to download a dynamic PDF, make note of the URL when viewing the PDF. Is it a direct link to the PDF file? If so, copy the link, open a different browser (not another window of the same browser), and paste the URL. Is the PDF loaded? If so, then you have a problem, especially if the file name is guessable or follows a pattern. You might also check to see if the PDF is deleted from the server after a time.

This topic applies to other static files that your application might generate dynamically too, such as Excel files. PDFs just seem to be the most common.