Archive for Security

Security Trends

Dec 29

I have been around computers for most of my life and for the past ten years I have been involved in corporate IT on both the network side and the programming side. I was reflecting on some of the changes and trends over the past decade and thought I would share them.

  1. We have realized that network security is important. Every organization I visit seems to have a firewall, antivirus, and windows updates turned on. Ten years ago it was every computer was connected straight to the internet with an exposed c$ share it seems like. Finally most corporate (and many home users) seem to have taken some basic security measures.
  2. Users still click on anything that pops up on the screen until they get the application/website to work. I have tried to educate people on this but it has become apparent to many of us in the industry that users just want things to work and it only when they go wrong that they care. For instance, my parents install every plugin they are prompted to as they feel that if it was bad their antivirus would catch it. I don’t fault them for it, it is just human nature. We expect the locks on our house to keep people out when it is simple to smash a window (or cut a hole in the wall). We are coming around the corner on this one and seeing that we can’t educate everyone and things need to just be more secure by default and leak less information.
  3. People care a lot more about their privacy now. People also don’t realize that most places gathering information don’t care about you as a person, they care about you as a demographic. Granted it is not a happy thought to know how much info about you is floating around but if it personalizes my searches and shows me advertisements for things I am interested in so what? It is only an issue (to me) if that information is used for nefarious purposes.
  4. Many more technologies are shipping with a more “secure by default” mentality. The *nix/bsd attitude has been like this since I can remember and Microsoft has really turned a corner and secured their products. I remember when a new client would tell us they were running an IIS server and we would just laugh, wipe the box, and install FreeBSD/Apache for them. Nowdays I only laugh when people have an Adobe product installed (we all do… so ha ha). Adobe has realized that this is starting to hurt them and are making a big security push like MS did years ago.
  5. Schools have not taught about security and they still don’t. I see a bit of growth in this area but I feel this is incredibly lacking. Every time I give a presentation and ask how many people don’t know about SQL injection someone still raises their hands. It is not acceptable to have developers that don’t even know about the most basic/common security holes and how to prevent them. It is like hiring an electrician that does not know how to use a circuit breaker: they might get by for years without an incident but it is bound to happen eventually.
  6. Phishing/scams/chain letters has risen and fallen a lot. I find most people I talk to realize that people are trying to scam them (or will ask others to see if it is a scam) and that they know if they don’t forward this message to ten other people a kitten will die (except for my sister). 
  7. Piracy became common place. Back in the day it was technically difficult to find the software/music/movies and then crack it if necessary. Now my grandma can run a P2P client (or the vast array of other tools) to get her favorite songs. It is common place and it is sad. Not because I love big rich Hollywood types that complain about the money being stolen from them as they drive through Starbucks in a gold plated Bently. It is the fact that for such a huge market that they continually fail to make it simple to get the content we want quickly, conveniently, and be able to use it how we see fit. If I ran an ice cream store and everyone wanted paint flavored ice cream served off a piece of copper pipe you would see me at the hardware store every day. I think they are starting to get it and I hope to see some progress there so that everyone is happy (except me…. until I get a gold plated Starbucks).
  8. The goal of software development was and still is for the most part to deliver working software. Security takes a huge back seat and is almost never a first class citizen. I don’t see this trend changing much. The nice thing is that many languages are shipping in a more secure configuration which helps developers not leave as many gaping holes but I still feel that education is very important for developers.
Filed Under: General, Security

WCF Security – Part 1: Message & Transport Security

Dec 16

WCF has a huge security component to it (as rightly it should). The technology is massively configurable to support almost any security scenario one can dream up. Unfortunately this also makes it massively hard to learn and implement successfully and many developers tend to work around the security rather than learn how to implement it correctly. With a bit of knowledge WCF security is not nearly as intimidating as one may think.

There are several security concerns to deal with in any communication technology. The top two most common concerns  are: making sure that no one can read, modify, or replay a sensitive message and ensuring that a caller is authenticated  to use the system and authorized to access the resources they are allowed to access (and denied access to the ones they are not allowed to access of course). The other concerns are usually around Availability (i.e. making sure the service is resistant to Denial Of Service attacks) and Auditing (being able to log and monitor security events).

Message Protection

Protection of the traffic in transit is easy to use and is typically turned on by default (basicHTTPBinding has no security by default). There are two choices to make with securing traffic: Transport or Message security. Transport security relies on security builtin to the protocol you are using (e.g. HTTPS for HTTPBindings and TLS for TCP bindings). Message security lets WCF sign and encrypt messages and then sends it across the transport.

Transport Security:
+Interoperability: Neither party in a communication need to support WS-Security specifications
+Potentially better performance
-Security is point to point. If a message is routed through an intermediary it will not be guaranteed to be secure (i.e. many load balancers accept SSL traffic, decrypt it, and send it unencrypted to a node in its array)
-Supports a smaller set of credentials and claims used for authentication
-All or nothing: A message is either encrypted or it is not

Message Security:

+End to end security: message security survives being routed through intermediaries
+Allows partial message signing/encryption so that only messages that need protection can be protected
+Transport independent: Message security can be used with any transport protocol
+supports a large set of credentials and claims
-May reduce performance as each message is secured and can not take advantage of hardware acceleration
-Not as interoperable as both sides must implement the WS-Security specification

 

Binding

Transport mode support

Message mode support

basicHTTPBinding

HTTPS

HTTP basic authentication
WS-Security

wsHTTPBinding

HTTPS

WS-Security
SOAP message with credentials sent over HTTPS transport security

wsDualHTTPBinding

None

WS-Security

netTCPBinding

TLS over TCP

WS-Security

netNamedPipeBinding

Negotiated (best compatible support is used)

None

netMSMQBinding

RC4 or AES (default is RC4). Messages signed with receiving queues public certificate.

WS-Security

wsFederationHttpBinding

HTTPS

WS-Security

 

There are also a few other approaches as well. There is the hybrid TransportWithMessageCredential which the client credentials are provided at the message level and the remainder (the message itself and service authentication) is secured by the transport. The other type is TransportCredentialOnly which is ONLY for basicHTTPBinding that does mutual authentication at the transport level.    

Binding

Transport mode support

Message mode support

TransportWithMessageCredential support

BasicHttpBinding

Yes

Yes

Yes

WSHttpBinding

Yes

Yes

Yes

WSDualHttpBinding

No

Yes

No

NetTcpBinding

Yes

Yes

Yes

NetNamedPipeBinding

Yes

No

No

NetMsmqBinding

Yes

Yes

No

MsmqIntegrationBinding

Yes

No

No

wsFederationHttpBinding

No

Yes

Yes

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

Up Next: Authentication


Filed Under: Security, WCF

ASP.NET “POET” Vulnerability

Sep 20

There has been lots of good posts so far about the ASP.NET vulnerability that was unveiled late Friday. In summary the attack exposes cryptographic keys used in ASP.net which can lead to all sorts of nastiness.

I recommend you read and apply the advice from Scott Guthrie and then come back and read more.

Microsoft is releasing very little information on this issue until they have a fix ready. As such, some of the information here is based on my best guess of how it is actually working. Although these are assumptions the advice on how to avoid these attacks are not.

Components
What I have inferred from the given workaround is that there are two components to this vulnerability. The first is an information disclosure vulnerability that certain responses to requests give different error codes. The second is a side channel attack that occurs that reveals how long it took to yield a certain error code.

Information Disclosure Vulnerabilities
An information disclosure vulnerability is just what the name implies. Information is being disclosed that gives an attacker information. The classic example of this is with a login system that states “Invalid Username” when you use a username that does not exist and “Invalid Password” when you use a username that DOES exist but the wrong password. The system should just give you a generic error message and not reveal the reason for the login failure.

Side Channel Attacks
The attack is an example of a side channel attack. A side channel attack is when an attacker uses clues from a system to determine information instead of brute forcing the attack. The most common form of this is a timing attack in which an attacker looks at how long something takes to determine what is happening. Some other side channels that have been used have been looking at power consumption of systems, the sound the systems make, and the electromagnetic radiation given off by systems. Granted, timing attacks are the simplest to execute remotely (but network speed variability can introduce inaccurate timings.)

A real world example of a timing attack would be my magic toaster. It has different settings for toast, bagels, waffles, and black pucks I can also tweak the darkness of the item with a dial. If I knew what time something was put into the toaster and what time it popped up I could probably determine the setting that was used on the toaster. With more refinement of my attack I could probably tell what the darkness toasting dial was set to as well. This attack is not precise though. Toast on 10 and Bagel on 1 might take the same amount of time (or close to it). Plus there may be differences in the materials inserted that affect timing (i.e. thin break or thick break).

As you can see, side channel attacks do not (usually) net you what you are looking for with ease 100% of the time. The real thing they do is narrow down the possibilities of what could be happening. If I said guess a number between 1 and 1,000,000,000 it would take a while to get it. If I said guess a number between 1, and 1,000,000,000 but the number is 7, 34, or 2million…. well that makes it a lot easier.

The Workaround
As descibed in Scott’s post the workaround is two address these two issues. By having custom errors on (which you should have anyways) for all error codes to redirect to a page should address the information disclosure vulnerability. The page that Scott shows also puts in a random delay of the response to mitigate the timing side channel component.

The Consequences
As this attack is used to determine encryption keys then I would state that encrypted data is at risk to being decryted. This would be things like viewstate, cookies, forms tickets, membership data, and more. As this attack is out there and should be fairly easy to automate I would consider my keys as most likely compromised. It appears the attack can run fairly quickly too (the example I saw got the key in 5 minutes).

To this end it may be a good time to update keys (after you have applied the workaround) used in your systems.

Mitigating Information Disclosure In Your Code
Combating information disclosure of exceptions is fairly simple. In a client server environment I take any error the server throws and I log it (with as much information) and then return a generic error. In this case it may be that a 404 (page not found) error is returned in one case and 500 (internal server error) in another. Normally this is pretty standard behavior but it really does not help the user. In the end they wanted something and it did not happen so a generic error is sufficient. This can be achieved with the setting of a standard error page that hides the HTTP error code from the user.

Mitigating Timing Side Channel Attacks In Your Code
The timing side channel attack is tricky to spot as it is not a typical attack vector but it is fairly easy to fix. If you have code that can reveal information based on the time taken it may be practically to add a random wait time to responses. Going back to the login scenario it may take 2-5ms to determine if the user is in the database and then an additional 2-3ms to hash the password and compare it if the user exists. By seeing the process takes 2-5 ms before getting a login failure we see that the user probably did not exist. If it takes 7-10ms the user probably exists but the password was wrong. By adding a Thread.Sleep(cryptographically_random*) if the user is not found we can simulate the amount of time taken to hash and compare the password.

But Wait! There’s a catch. If we wait longer than the time it would take to hash the password we have just created the same problem. I.e. if we sleep for 0-20ms then an attacker may know that if it takes between 7-10ms that we have the right user and if it takes between 5-20ms is that the user was not found (but a sleep was added to lengthen the process). So adding wait time created the same issue we were trying to prevent! The most encompassing solution would be to wait on success or failure in this case. So no matter what the time it takes to execute something is variable. This may negatively affect performance though as you have threads sleeping all over.

RANDOM IDEA AS I WRITE THIS POST: As every computer is different stating that success is a-b milliseconds and failure is x-y milliseconds as hardcoded fact in code does not work as the software may be installed in many different places (or upgraded to faster systems in the future). It may be an idea to build in a profiler around a sensitive method call that monitors the time it takes and then assures that subsequent calls fall within that range.

*It is important not to just use Random as the sequence of Random can be preditced. Using a crypto level random number generator generates a more random random :)

Mitigating Timing Side Channel Attacks On Your Network Layer
The other component to this is that it takes multiple requests to the server to test different bits of data. The demo I saw did close to 40,000 requests. This may be able to be stopped or slowed down by rate limiting requests to a server to a reasonable/human level. It also leaves a pretty big log footprint on your servers.

Filed Under: Security

Staying Secure

Mar 25

I have started to realize that there are a few things I do that most average users do not to stay secure.

  1. I use a password manager (Roboform) that integrates with my browser. This tool makes me remember one master password and then allows me to fill in login forms on websites with only needing to know one master password. This has let me use unique passwords on all the sites I login to. I see looking through my list of sites that I have 45 accounts on various sites and there is no way that I could remember 45 unique passwords.
  2. I use encrypted pop/smtp/imap so as not to divulge my password. Most of the world still seems to use unauthenticated POP3 for some reason
  3. I use the NoScript add on for Firefox that allows me to control if scripts run on a page or not
  4. I use the ForceTLS add on for Firefox so that if I visit a http site that it will redirect me to an https site (unfortunately you have to setup this list on your own)
  5. I never upgrade an OS. I always reinstall. Call me paranoid but it is hard for anything bad to survive a wipe and reinstall
  6. I run the Secunia Personal Software Inspector that checks for security issues in third party apps and allows me to easily download updates
  7.  I run Microsoft Security Essentials. A free, lightweight, and (from what I have read) accurate virus scanner. It reminds me of how all antivirus software starts out so lets hope MS does not bloat it up.
Filed Under: Security

Trust. It is a Two Way Street

Jan 20

One of the most common flaws I am seeing in applications is the lack of mutual authentication. Most systems authenticate that the user connecting to their system is a valid user. What is lacking is that the client verifies that it is connecting to who it thinks it is connecting to.

One of the big examples of this is WiFi. If I have a wireless router named “myrouter” and set my laptop to use that router things work great. If I go down the street and someone else has a router named “myrouter”, my laptop automatically tries to connect to it. This is because the WiFi implementation does not verify that I am connecting to who I think I am connecting to.

This happens a lot on the service level of applications. The client app resolves a DNS name like www.myservice.com to it’s IP address and then sends over some form of authentication. Now what happens if I somehow manage to change the DNS record for www.myservice.com to point to my IP address which contains a service with the same name and same methods exposed to it? The client will connect and divulge its authentication data to this fake service. I can now use the authentication data that you gave me authenticate against the real system and do whatever nefarious things I desire.

The solution for this is for clients to verify that the service it is talking to is actually the service you want to be talking to. This is best accomplished by using some form of shared secret. This takes on many forms but a few methods:

  1. Ask the server to answer a shifting question. i.e. ask the server to hash a certain string. If the hash the server returns matches what you expect then the server might be the one you want (or an attacker managed to replicate the algorithm)
  2. Use windows authentication. For WCF the mutual authentication is implied in this case.
  3. Use certificate authentication. This is the best way to do this task but can be a pain to implement.
Filed Under: Security

Brute Force Attack Countermeasuers

Jul 28

One common attack to get into a website is to brute force the username / password. This is effective mainly due to the lack of brute force countermeasures that people build into their websites login mechanism. There are a few common countermeasures out there currently.

Account Lockout

An account lockout is when a set number of failed attempts are reached that no more attempts are allowed. Usually this involves flagging the user account in your database as locked out. While this stops a brute force attack in its tracks, it does have some consequences. The most obvious is that there will need to be a mechanism to unlock the account which is usually an administrator or else a set period of time has elapsed. The not so obvious consequence is that an attacker may lock out legitimate accounts on purpose which would deny legitimate users access until the lock is released!

Tarpitting

Tarpitting is the process of slowing an attack down. Typically an attacker tries to login thousands of times per minute in a brute force attack. By putting a delay on how long it takes to get the results back you can drop the number of attacks per minute drastically. This prevents the intententional lockout attack mentioned for the account lockout countermeasure.

The most common mistake I see when implementi ng tarpitting is when it is implemented as Thread.Sleep(failedLoginAttempts * 1000). The main issue here is that the delay time keeps growing, If I wanted to prevent a legitimate user from logging in all I have to do is fail your login a few thousand times and it would then take thousands of seconds to log back in. Instead use a hard coded delay (even something like one or two seconds drops the number of attempts an attacker can perform).

The other item to worry about when implementing tarpitting is resource exhaustion. By keeping a thread sleeping you are using resources to maintain and monitor that thread. If an attacker were to be able to do enough attempts they may be able to exhaust your servers resources which could deny service to legitmiate users.

Fake That The Login Worked

This is something I theorized that may get around the negatives of account lockouts and tarpitting. What if you build a login screen that once so many failed logins were reached that it would redirect the attacker to an empty page so that the tool they are using to brute force stops as it thinks it got a hit? I have not tested this theory out but there is a bit more information here: http://www.haveyougotwoods.com/archive/0001/01/01/annoying-brute-forcers.aspx

CAPTCHA

This one is quite annoying but placing a CAPTCHA (one of those computer generated images that you have to type in the word) on the login would drastically reduce the effectiveness of an automated attack. Now the attacker has to guess the username, password, and either guess or break the CAPTCHA image which makes the attack harder. This comes at the cost of convenience and useability to the end user. Also the big downside of CAPTCHAs is that they are not usable by the visually impared.

Abandon Passwords

This is easier said than done but there are lots of password alternatives that are much harder to break than passwords. Things like certificate exchanges, smart cards, card space, and security key tokens offer better security but all have their downsides.

 

Filed Under: Security

Securing PHP

Jul 3

Much to my disappointment PHP installs with developer settings by default. This means that the default installation has some potential security holes that need to be tightened after the install.

Any security person will tell you that an application should install in a minimal and locked down  state. I would say 95% of people don’t look to secure something after they install it, they expect it to be secure out of the box. This is what IIS now does and you have to enable any features over the baseline you want.

Doing some simple lockdowns are not hard in PHP though. I am not going to talk about every security feature in the config file, just the defaults that I feel should be changed:

safe_mode=On [Default=Off]
Turning this on makes it so that any file your php file attempts to open MUST have the same UID as the php file that is executing. It also disables or restricts many methods that access or manipulate the filesystem.

safe_mode_gid=Off [Default=Off]
Same as safe_mode but checks the GID instead of the UID. I keep this setting at its default Off state as I want to keep the access restricted to only a user.

open_basedir=[path] [Default=blank]
Restricts PHP to only access files and folders within that path. If all your sites exist in /usr/home/web then I would set open_basedir=/usr/home/web

expose_php=Off [Default=On]
PHP will not write information about itself to HTTP headers. This can help prevent a vulnerable version from being discovered by automatic scripts.

display_errors=Off [Default=On]
By turning this off error messages are not returned to the browser. This prevents information disclosure which is often a precursor to an attack.

log_errors=On [Default=Off]
turning this on logs all the errors to a file or syslog (as specified in the error_log variable)

disabled_functions=show_source, system, shell_exec, passthru, exec, phpinfo, popen, proc_open  [Default=Blank]
This allows you to completely disable certain functions in the PHP runtime that could be potentially used to exploit your system.

enable_dl=Off [Default=On]
Disables the loading of a PHP extension at runtime (i.e. dl(‘myexploit.so’);).

allow_url_fopen=Off [Default=On]
Disables using fopen to open a URL. When left on it is possible it could be exploited to download exploit code from a remote server.

upload_tmp_dir=/var/tmp/php/tmp  [Default=/var/tmp]
I change this so that automated attacks can not find any uploaded files in the default directory. It also enables you to add customized security around the directory that is restricted to its purpose.

session.save_path=/var/tmp/php/sessions [Default=/var/tmp]
Whenever a session is created it is saved to the disk. This could potentially expose the session IDs of all current sessions if an attacker can enumerate them. Changing the folder that the session files are saved to can reduce this risk.

There are also a few limits that you may want to adjust to suit your environment. I find the default memory limit quite high (128MB) but this will differ from environment to environment:

max_execution_time = 30     ; Maximum execution time of each script, in seconds
max_input_time = 60     ; Maximum amount of time each script may spend parsing request data
memory_limit = 128M      ; Maximum amount of memory a script may consume (128MB)

Using Apache to provide additional security

Many php systems ship with files that are used by the application but should never be served out to the application. The common ones are .inc, .sql, and .conf (or .config) files. Also some editors create temp files that end in a ~ and may not get cleaned up properly. We can change our Apache config to deny these files from ever being served:

<FilesMatch “\.(inc|sql|config|conf |.*~)$”>
  Order allow,deny
  Deny from all
</FilesMatch>

One of the issues is that with safe_mode set to on an attacker could still write to all files that are owned by that user. Lets take the following example

/usr/home/web/user1/index.php   Owner: nobody
/usr/home/web/user2/index.php   Owner: nobody
/usr/home/web/user3/attack.php  Owner: nobody

Even with safe_mode=On and open_basedir=/usr/home/web, running attack.php could alter index.php in user1 or user2’s directory. I know it is not common to have this kind of scenario where the same user owns all the files but it is quite possible.

I saw a nice workaround somewhere that used Apache to set the open_basedir for each virtual host that looked something like this:

<VirtualHost www.user1.com:80>
  <Location />
    php_admin_value open_basedir “/usr/home/web/user1″
  </Location>
</VirtualHost>

This would basically lock every user into their own home directory which is exactly what you would want in a shared environment.

Suhosin

Suhosin is a two part hardening add-on to PHP. One part patches PHP to help prevent buffer overflows or format string vulnerabilities. The second part is a PHP extension that adds a host of other protections and features. More info on Suhosin can be found on their website.

Filed Under: Security

Iterative Hashing: Less Secure Is More Secure (in theory)

Apr 23

*DISCLAIMER: This is only a theoretical idea. I have not confirmed that this could increase security of an iterative hash. Please take that into account when reading this.

I was explaining iterative hashing the other day and came up with an interesting theory: Using a weak algorithm may result in a stronger hash. The reason for this is collisions that can happen in algorithms like SHA0, SHA1, and MD5 (a collision is when two separate strings yield the exact same hash). By using a collisionable algorithm in an iterative hash we could potentially throw an attacker way off.

  Valid Attacker
Original Data HelloIAmData 56r335u8425
iteration 1 dfti34548247 fskwrtujrwf
iteration 2 est84354u544 rtietyrt3487
iteration 700 er54djrt5ejh 458432423uitd
iteration 701 dfsujweru5 6483247435u
iteration 702 ase6ae4rha ase6ae4rha
iteration 1000 a473uj4w5h a473uj4w5h

Iteration 701 is where things break down. The hash we had from iteration 702 (ase6ae4rha) has a collision on it. Both dfsujweru5 and 6483247435u will create that hash. In this case the attacker broke ase6ae4rha with 6483247435u not dfsujweru5. Now the attacker tries to break 6483247435u and the hash that results from that which has now put them on the totally wrong path and they will never crack this hash.

Now don’t run out and start using a lesser algorithm based on this information collisions do not happen that often. The collisions in SHA1 are only considered theoretically possible as it would take 2^69 operations to find a collision that matches an existing hash (for SHA0 it would take 2^39 operations).

As I do not have the processing power required to do this I can not calculate the chances of this actually happening. Nor can I vouch for if this is a feasible defence strategy.

Filed Under: Security

Annoying Brute Forcers

Feb 17

Had an interesting thought today. If someone tries to brute force your login screen then why not after so many failed logins redirect them to a page that looks legitimate. This would cause the tool they are using to report that they cracked the password and logged in. The attacker would then have physically verify the login only to see some garbage page and start all over again. This would probably make a script kiddie attack some other site as they would probably not have the programming knowledge to alter the brute forcing engine.

I would have it so that after 10-20 failed logins to redirect to the fake page so that legitimate users have a very low change of being redirected to it.

Just an interesting thought / theory.

Filed Under: Security

Building Your Own Password Based Authentication System

Feb 16

Many times we need to have a way for users to authenticate with a system and that is usually done with a username/password combination. A lot of times we have to build our own or use some pre built system (i.e. Forms Authentication).

Now I am not a fan of passwords. I find that they are usually easy to guess and brute forcing them has become faster and faster. Passwords are dying and there are other options but they will differ from implementation to implementation.

If you have to build a password based authentication system then there are some minimum requirements that I feel are required:

Require Complex Passwords
Complex passwords drastically increase the difficulty of breaking a system. Allowing users to put in dictionary words means that it can be broken into in minutes with a dictionary brute force tool. Be careful of your rules though. Having password requirements that result in passwords too complex to remember means more people will write it down.

Store Passwords Properly
So many people store passwords in plain text. Use a hashing algorithm with a good random salt (for more info see my post on hashing for passwords) . Better yet use an iterative hash that will hash your hash multiple times that makes it take a huge amount of time to crack.

Ensure That Data Is Encrypted In Transit
There are many many sites that have a login page unprotected by SSL/TLS. If the credentials are transmitted in plain text to the server then it is easy to sniff the data off the wire. SSL certs are cheap and a quick way to protect data in transit!

Also be careful what happens with the data once it arrives at the server. Does it go across the wire in your network to the database server? Is that connection encrypted?

Password Change Policy
Passwords are getting easier to crack and if you have all the time in the world it becomes much easier. Brute forcing a password over the web may take months (or it may take minutes) but forcing users to change their password every X number of days helps prevent this.

Record and Monitor Failed Login Attempts
Most people don’t log failed logins and even those that do rarely look at the log of failed attempts. If you don’t know that people are trying to break into your system then how can you hope to prevent them from succeeding? If you see someone trying to brute force in you can respond by blocking their IP address and prevent any other attacks they may try.

Don’t Let People Try To Break In Forever
If a user fails to login successfully for X times in a set period something should prevent them or slow them down from trying again.

Account lockout is one way to do this but an attacker could intentionally lock out an account and deny service to a legitimate user that way! Also the lockouts need to be cleared by an administrator which could take time to contact that person and have them clear the flag. Also if an attacker goes after the admin account this could cause a lockout of the only person that can clear the flag! This is why in Windows the Administrator account has no lockout policy. This is a crappy scenario as the one account you REALLY want to crack has no lockout while the crappy accounts with fewer privileges do have a lockout policy.

A better technique in my opinion is tar pitting. Tar pitting is a technique of slowing attempts down. So if someone fails to login more than 3 times we may delay processing another login request for 10-15 seconds. If they keep failing we may increase that timeout. We would not want to algorithmically grow the timeout though (i.e. for each failed login add a 2 second delay). If we did then an attacker may fail logins on purpose so that a legitimate user would have to wait 26 days until they could login (which would also hold server resources for that period too which could lead to a much broader denial of service attack).

Ensure The Password Reset Mechanism Is Secure
One area that is exploited more and more is the password reset ability. The systems where it asks you to answer 2-3 personal questions are fairly easy to attack if you know something about the victim. For example Sarah Palin’s account was hijacked because the personal questions she chose were all over the media (i.e. Where did you go to high school? What was your Mothers maiden name? What is your favourite book?). These “personal” questions are also fairly easy to retrieve via social engineering as people don’t feel that their favourite book is something they should consider sensitive information.

I personally like how ING bank does PIN resets. I need to provide personal information like a SIN plus the amount of my last transfer/deposit to my account. Once I reset my pin I get both an email and a physical letter mailed to me notifying that my PIN has been changed. It is really important to pick a methodology of password resets that use information an attacker could not guess or easily learn.

Conclusion
Those are my BASICS for a login system. It will take a lot of time and resources to build a system that does all of this and that is why I like either leveraging windows authentication or other technologies (like certificates, cardspace, smart cards, passkey devices). It is really not an easy task to build something like this. The authentication used in Windows has been developed and evolved by countless developers over the years and they have though about this kind of stuff way more than we would ever want to.

There is also a great chapter on password systems in the book 19 Deadly Sins Of Software Security that goes into much greater depth (yes there is way more on this subject) then I have.

Filed Under: Security