I <3 Steve McConnell*
Coding Horror
programming and human factors
by Jeff Atwood

February 05, 2007

What You Have, What You Know, What You Are

I'm no fan of the classic login/password scheme. I can barely remember any of the zillion logins and passwords I have. More often than not, I end up using the "forgot password" link. Which means, in effect, that my email account is my global password. And if you're like most people, your email password isn't very secure. As Bruce Schneier recently observed:

We used to quip that "password" is the most common password. Now it's "password1." Who said users haven't learned anything about security?

It's a depressing state of affairs. Switching to passphrases helps, but is a band-aid at best.

The relentless increase in phishing attacks may soon force some changes on this front. I saw in the news that PayPal is switching to two-factor authentication. Specifically, they're providing users with a keyfob that produces a new six-digit code every 30 seconds. Users will now have to type in their name, password, and a valid code from the keyfob.

securid token

The PayPal system isn't SecurID, but I'm sure the implementation is very similar. There's a matching seed value stored on the server for each keyfob, so the server can calculate what the correct code should be. If the user enters the correct password and the correct code (within 30 seconds), they're allowed in.

So what's the value in doing this? It's more hassle and more expense. Well, consider that all security is based on three things:

What you have

What you know

What you are

We all use logins and passwords. That's something we know. When we enter the code from the keyfob, we've added something we have to the mix. That's two factor authentication, and it increases security dramatically.

But even with the keyfob, we haven't quite removed the risk of phishing entirely. All we've done is make the window of opportunity smaller. If a phishing site can relay the user-provided data to the server in real time (or close enough), they will still be authenticated.

A common form of local two-factor authentication is the Smart Card.

Smartcards

Smart cards have an embedded microprocessor that uniquely identifies each card, a private key of sorts. Some even have the ability to store data. The secrets on each card stay secret because it's impossible to extract the data without destroying the chip in the process. Since smart cards are read by hardware on your PC, they're of no use online. But they can dramatically enhance security locally. For example, Windows has embedded support for smart cards; it's possible to log into the operating system using nothing but a smart card and a short PIN code. The PIN code is still a password of sorts, but it's much shorter and easier to remember.

Once you switch over to smart cards, it's no longer possible to log in using a traditional username and password. Your underlying password becomes a randomly generated 64-character string. As you can imagine, this is a huge boon for local security compared to user-selected passwords. I don't personally care for smart cards, but I can certainly understand why organizations choose to use them.

But two-factor authentication, although more secure, isn't a panacea. Bruce Schneier is quick to remind us that two-factor authentication is vulnerable to two primary forms of attack:

Man-in-the-Middle attack. An attacker puts up a fake bank website and entices user to that website. User types in his password, and the attacker in turn uses it to access the bank's real website. Done right, the user will never realize that he isn't at the bank's website. Then the attacker either disconnects the user and makes any fraudulent transactions he wants, or passes along the user's banking transactions while making his own transactions at the same time.

Trojan attack. Attacker gets Trojan installed on user's computer. When user logs into his bank's website, the attacker piggybacks on that session via the Trojan to make any fraudulent transaction he wants.

We already knew about the man-in-the-middle attack; we refer to it as real-time phishing. As for trojans, it might be a little unfair to blame two-factor authentication for not protecting the user from a compromised system. I'm not sure any security measures can work on a compromised system with trojan keyloggers and screenloggers installed.

Despite Schneier's skepticism, I think two-factor authentication is worthwhile. Anything that moves the security bar beyond the hopelessly insecure and ineffective username/password combos we're currently stuck with is a welcome change.

Posted by Jeff Atwood    View blog reactions

 

« Windows Vista Media Center The Software "Check Engine" Light »

 

Comments

Good post on basic security.

Anyway, it's worth mentioning that you can use a keyring with a master password instead of your mailbox.

MyKey_ on February 7, 2007 12:04 AM

Ad smartcard authentication:

At a former employer of mine, they wanted to use a card+PIN authentication system for their fleet of NT4 workstations. The bad news? The custom login program was dynamically linked against MFC, and did nothing to validate the DLL. Since MFC was one of the few components available in source form, it was not difficult to embed a backdoor that would be called by the secure login application.

Whoops.

Anonymous Cowherd on February 7, 2007 12:30 AM

A global id (ie. http://openid.net/) could save you a lot of trouble. Also there are many services (like http://www.agatra.com/index.php?) that can help you with your password management.

It's an issue of trust :)

Goran on February 7, 2007 12:57 AM

I've been using Bloomberg with three-factor authentication:

(1) a login name / password screen
(2) a smart card reading your fingerprint
(3) correctly submitted (1) will pop a algorithmically freshing block on the screen, which the smart card reads it and gives you an one-time password

It's pretty elegant way to integrate all 3 factors. And some forensic detection system works on 'where you are' too.

Kevin.

Kevin Lee on February 7, 2007 01:11 AM

You know the lost passwordt procedure where you have to answer a question only you know the answer to (What's you mother's maiden name, for example)? My company recently rolled out something like it, only with a slight twist that makes it useless.

First of all, users have to provide both the "question" and the "answer". This is fine, and some websites offer the same option, but that is where sanity ends.

When a user wants to retrieve their password, they have to enter BOTH the "question" and "answer" manually. Not only that, but both parts are also displayed as asterixes instead of plain text, and are case-sensitive. Much like normal passwords, yes.

So, in essence, when you've forgotten your original password, which can be only 6-8 characters in length, and you want to retrieve it, you need to enter TWO additional passwords, which both have to be at least 10 characters long.

Of course, when I asked why is was reasonable to expect users to REMEMBER two long passwords to retrieve a single short password they FORGOT, I ran into the usual Large Corporation wall of bureaucracy.

Jeroen on February 7, 2007 02:10 AM

It seems to me that a protocol for a web site to authenticate to a smart card attached to a PC is possible. Why not? I imagine most smart cards just return a simple number. However, a more sophisticated card (maybe a USB device) could handle a challenge/response or public key encryption based authentication. The private key would never be revealed outside the device. A session key would be encrypted by the site and decrypted by the device. This session key would then be used by the PC for communications with the site. Sort of like SSH, but doing the session exchange on the device. And the server would only communicate with known devices. The device could also only communicate with known servers.

Of course, you'd still want a second or third factor for your security. And you'd want access anomaly detection (e.g., user logs in from California at 3:40pm, then at 7:00pm logs in from China, an immediate lockout should occur).


Cryptnotic on February 7, 2007 02:16 AM

Pedantic, but I'd guess 'Password1' was probably more popular than 'password1' these days.

James Savin on February 7, 2007 02:30 AM

Hoorah for two-factor authentication!

But don't be fooled into thinking a fingerprint reader is secure:
http://www.yubanet.com/cgi-bin/artman/exec/

Grant Holliday on February 7, 2007 02:55 AM

Here's the actual link:
http://tinyurl.com/cumk7

Grant Holliday on February 7, 2007 02:59 AM

Regarding the two-factor auth you mentioned and its vulnerability to screen/key loggers, the cadillac solution is probably use challenge-based token. This way, the website requires you to enter your name/password and displays a short challenge code, which you type in your small device. Your device will display a number which you will inform the website. Naturally, the challenge codes are not very likely to repeat, thus avoiding screenlogger attacks.

João on February 7, 2007 03:53 AM

If there's one thing in this world that keeps me up at night, it's that my brokerage account is protected only by a UserID/Password. Like many people, all that I have in this cruel world is contained therein. WTF, Fidelity?

(Unfortunately due to some strange regulatory restrictions with one of my clients, I can't switch away from Fidelity...)

Dave Markle on February 7, 2007 04:42 AM

Dave: Never mind the Fidelity. Everyone knows you're supposed to keep a 20 in your sock and the rest under a tarp in your attic.

Eam on February 7, 2007 05:43 AM

While it won't give you much better security, KeePass is a good software for managing passwords: it will randomly generate passwords for you and store them in an encrypted file. It helps for those myriads of web sites that ask for passwords, at the very least you can use that application to manage complex passwords without having to remember them.

http://keepass.info/

Of course, you still have the master keepass password to worry about, but at least it's only one password and not dozens of them.

Bruno Navert on February 7, 2007 05:57 AM

I like the idea of having one of those key-fob SecurID-type things. But, the problem is what happens when you have a bunch of systems that use them? I already have four or five of those darn "special" shopper discount cards on my keyring. How am I going to fit it into my pocket with a half a dozen SecurID-type fobs, too? For example, right now, I have to keep track of accounts at: a brokerage (2 accounts -- used to be 3 accounts), a bank (3 accounts), another bank (2 accounts), and since it's mentioned in the article, 1 ebay and one paypal account. So, without counting any non-financial stuff and assuming the fobs can't be consolidated, that's 8 to 10 different fobs. Throw in at least a couple more for work systems, health systems, and insurance systems. Well, just remind me to buy stock in SecurID and the key-ring industry.

David A. Lessnau on February 7, 2007 06:17 AM

I work for the government, and our smart cards have some sort of certificate on them (PKI?) that is protected with a password. Secure sites then require a client cert, which is located on the card. So in order to log in, I need the card, the password to the card, and my username and password to the site.

matthew on February 7, 2007 06:41 AM

When you state:

"The secrets on each card stay secret because it's impossible to extract the data without destroying the chip in the process."

I think that's a little ambiguous. If you couldn't extract the data, wouldn't it be worthless?

You continue by stating:

"Since smart cards are read by hardware on your PC..."

Which seems to contradict the previous statement. Maybe it's completely coherent, and it is just too early in the morning for me to think. :P

David H. on February 7, 2007 06:43 AM

This seems like a good idea to include a 2-factor authentication. I just can't wait until we are able to integrate the most unused factor in password security to this day: What we are.

Kyle Korleski on February 7, 2007 06:51 AM

It's interesting that the US is just now talking about this. For the past five years I've been using what they call here in Indonesia a KEY. The pic of a lady on my bank's homepage is holding one (FYI, the last update to this site's structure was in 2000). http://www.klikbca.com/default.html?langID=2

It most closely resembles a tiny calculator with 10 digits and a red function key. When making a simple online transaction like paying your electric bill, the bank will just ask you to press 1 and enter the code thats displayed on the KEY. For more complex transactions like transferring money it will put you through an extra step before hand telling you to press 2, enter a code from the website, then you enter the reply code from the device.

I only need this to make online transactions. Without it I can only check my balance & exchange rates, etc. The only problem as someone previously posted is that you have to bring it with you. So I can't access my account anytime/anywhere like I can from my US accounts.

I feel sorry for all the people I know that have 3 or 4 bank accounts that each use KEYs.

Alhasib on February 7, 2007 06:52 AM

David H, I'm not sure. After doing a bunch of research, I'm still a little fuzzy on how smart cards actually work. And there's not much quality information on the internet about them. It does seem to me that rogue software could read the smartcard just as well as the "trusted" software if your system is compromised.

Anyone have any good links or *specifics* on why a smart card is inherently more secure than, say, a USB key?

> I just can't wait until we are able to integrate the most unused factor in password security to this day: What we are.

Well, except that information can never be changed, which is sort of a problem too. If a password or keyfob is lost, they can be invalidated. We can't invalidate your DNA or your fingerprint..

Jeff Atwood on February 7, 2007 07:16 AM

> the cadillac solution is probably use challenge-based token. This way, the website requires you to enter your name/password and displays a short challenge code, which you type in your small device.

This is something that RSA has proposed; basically they are packaging their software to run on a variety of handheld devices, eg, your smartphone, or something else you already carry around with you:

http://www.rsa.com/press_release.aspx?id=6508
--
RSA Security (Nasdaq: RSAS)today announced a series of initiatives designed to enable a broad range of devices to deliver RSA SecurID® two-factor authentication capabilities. [..] extension of the RSA SecurID Ready partner program, which is designed to encourage device and software manufacturers to embed the RSA SecurID algorithm within their own solutions. RSA Security is already working with several flagship partners including M-Systems, Motorola, RedCannon Security, Renesas and SanDisk
--

I can see the attraction. If you were using a challenge-response smartphone instead of a dumb keyfob, *Both* your computer and your smartphone would have to be compromised for attackers to log in as you. But the bad news is that can only protect you from trojans. Real-time phishing still works in that scenario.

We'd have to come up with something that couldn't be relayed in real time by phishers.

Jeff Atwood on February 7, 2007 07:29 AM

I'm shocked that Paypal can implement key fobs for only $5. We use RSA fobs for connecting to our VPN and those run a cool $1,000 each. What happened to allow the sharp drop in cost?

Chris J on February 7, 2007 08:00 AM

Eam:
I put a 20 in my sock last year, and now I have a 26-dollar-and-seventy-two-cent bill. Stupid compound interest.

Todd Derscheid on February 7, 2007 08:16 AM

I've used the RSA soft-token (software based token vs the keyfob)
and it tends to drift in time, so I have to call Security to get it reset on the server. This is a significant slowdown while trying to login to the servers during an emergency.
Also, wouldn't it be prone to scripting?

It would be unless you use some kind of webcam and OCR setup (hmmmmmmmm)

-E

Eric on February 7, 2007 08:38 AM

Did you see MythBusters hack a fingerprint reader with a photocopy of a fingerprint? Don't bet the bank on that technology.

My little RSA token scheme - just like the one pictured - has some odd moments. Sometimes it asks me to enter the next number and I have to wait almost a minute for that to come up.

Jim on February 7, 2007 09:00 AM

Nice! You didn't mention however that some banks are doing the picture recognition feature.

Katelyn on February 7, 2007 09:28 AM

Why no mention of CardSpace? Instead of managing a separate username and password with each vendor who stores all my information, I can just present a certified CardSpace identity.

There's still concern over workstation login security, but my moving beyond simple HTML form elements to a mature digital identity system, the problem of identity management seems to simplify quite a bit.

Jon Galloway on February 7, 2007 09:52 AM

I think I recall Schneier mentioning methods that do work even in cases where the end-user computer is heavily infected with malware. Namely behavioral pattern matching at the provider site (bank, credit card company etc.).

For instance if you normally make purchases ranging from $5-$50, then a $1000 purchase should raise a flag. The bank could then call you to check if this is authentic. Demanding that the attacker has access to your phone really makes the attack more difficult, although it won't stop subtle attacks that simply steal the "right" amount.

Einar on February 7, 2007 10:02 AM

Perhaps a simpler baby step to more security is for sites to disallow trivial passwords via password strength algorithms.

Ben Kruger on February 7, 2007 10:22 AM

>The secrets on each card stay secret because it's impossible to extract the data without destroying the chip in the process.
That is the theoretical idea. Researchers have managed to reproduce the contents of the cards with things like examining power consumption. Non-destructive methods for making educated guesses about what goes on inside the chips. But this sort of thing takes well funded universities. The best devices for programming smart cards have been yanked off the market due to the legal efforts of the satellite tv providers. There used to be a book, with a smartcard, on the java smartcard api, but that too is off the market.

Europe is more than a decade ahead of the US in smartcard deployment and usage. That's partly due to the lack of a sue-happy satellite provider combined with cheap online verification. We're used to cheap phone service here, thus credit card charges can be validated quickly with a short phone call (the swipe terminals usually use 300 or 1200 baud because the whole transaction is quicker than when you have to go through modem training). In Europe, the transactions had to be do-able in places where phone connectivity was unavailable. So they went with smart cards starting in the 80s.

>We use RSA fobs for connecting to our VPN and those run a cool $1,000 each.
Ah, the fobs run about $50 each, the server software starts about $3k. The fancier fobs with usb or number pads run closer to $100 apiece in low quantities.

One of the problems with this stuff is the incredible difficulty with getting a development environment set up to actually work with it and wrestle the bugs to the ground. I've been trying to get something out of my local RSA reps to no avail. I get follow up calls from their HQ, and I tell them what I want, they say thanks, and hang up.

We develop software at our company. Some desktop, some web based. Some of our larger financial clients want to integrate our security with theirs. An ideal solution would be to use the existing infrastructure they have, and use their existing tokens to authenticate against their security regime.

I'd like some sort of development version. Maybe with 2 fobs, maybe with one of each sex (RSA has quite a few). Maybe a "knob" on a web page or web service that can be set to each possible setting: bad password, wrong token value, expired token, locked out account and other things like that. But you can't get that. All you can do is purchase a 25 user server app for $3k and then you have to purchase tokens 25 at a time (for $50 a pop). I wouldn't mind coughing up $100 or $200 for a dev verion out of my own pocket. Spending thousands of dollars for a dev environment? FTS, I need a new car far more than that. And the management says "we already have one on our network, use that one."

The sales reps don't know anything about that RSA SecureID Ready program, or they don't want to talk to me about it. From my end of the phone, it seems the same.

As for sharing the fobs between applications, the server end takes a digital certificate type thing. Adding a user means buying a new fob, and adding another user license to the server. Could be $100/user total.

Theoretically, you could buy one fob, and to use it with a new bank, send them the digital cert with the details on your fob. That might make sense, so banks won't do it.

Hmm. Re-reading this, it looks like I'm all wound up about something (Gee, Peter, why don't you tell us how you *really* feel).

Peter on February 7, 2007 11:57 AM

Sources for smartcard technology:

http://www.pcscworkgroup.com/specifications/specdownload.php

In general, smart card interfaces are realized by the exchange of formatted application protocol data units (APDUs) over a serial interface. Advanced smart cards can include implementations of asymmetric crypto algorithms, including DSA and RSA. Since storage a processing power are limited, elliptic curve cryptography is fairly popular in security applications. Vendors of ECC-capable smart cards include these guys:

http://www.gi-de.com/

Hope that helps.

Anonymous Cowherd on February 7, 2007 12:20 PM

Speaking of security, you really ought to change to anti-spam word from "orange" to something else.

Gabriel J. Smolnycki on February 7, 2007 12:55 PM

You could give this tool a try: http://www.dekart.com/products/access_control/password_manager/

It can use up to three factors (including biometry), and the second factor is a USB disk, thus you don't have to pay for a smart card and a smart card reader. It can generate complex passwords for different sites, so there is no need to actually memorize the credentials.

Alex on February 7, 2007 01:38 PM


I suggest the CAPCHA should be "orange1" from now on.

Brendan Dowling on February 7, 2007 02:17 PM

Jeff,

Hard to believe I don't see more on your blog from this guy...

https://www.grc.com/passwords.htm

steve on February 7, 2007 02:18 PM

Am I the only old enough to remember when the Internet was benign? And now we HARDWARE passwording just to buy Superman #1????

Internet commerce is on the edge of collapse if this continues.

Either most folk will opt out just because it's a pain in the butt, or most folk will opt out because a PC with cujones enough to run Vista over a personal T1 along with the necessary firewall machine to keep the bad guys away cost so much that only Bill Gates will be able to afford to use eBay. OK, a little hyperbolic. But I'd bet a fiver on it.

BuggyFunBunny on February 7, 2007 05:09 PM

There is a bank here in Australia that has implemented an optional security option for internet banking whereby every transaction sends a unique code via SMS to your phone. The transaction will be processed when you enter the SMS code correctly. This just adds another practical cheap layer of authentication protection.

Darch on February 7, 2007 06:05 PM

Peter,
$50 for the RSA fobs is interesting. When our group was told they ran $1000 each (purchased in packs of 5 for $5K) I was shocked. It's nerve-racking carrying that thing around.

Chris J on February 7, 2007 06:13 PM

Chris, one reseller is here: http://www.securehq.com/vendors.wml&vendorid=31&adv=GG

$1k per token is astonishingly wow. I wonder who was trying to sell that. And what they were trying to do.

Peter on February 7, 2007 08:32 PM

At least Man-in-middle attacks with two-phase authentication force the fraudulent site to do all their frauds in one login session. They will not be able to surmise the secret key sequence from one or two logins. This will presumably force the cons into much smaller frauds, as it would be easy for banks to put limits on what can be done in one session. One of my banks already requires me to allow a day or two after setting up a 'new payment' (i.e. transfer of funds outside of my own accounts). With 2-phase this would be quite strong security.

I used to use a SecureId for my work login. Worked fine for me, even with time-drift: Although the code changes every 30 seconds, the computer can work out the surrounding 'n' codes - say 2 minutes forward and back from the correct time (car alarms work somewhat like this, to allow for you pressing the remote when out of range of the vehicle). Even outside of that range, it could still potentially validate you by asking for two codes in succession (though I don't know if it actually does this, but it could be done to allow more time-drift), and if you login frequently it could monitor the implied time-drift from the code you enter, and use that offset for the next time you log in.

Nij
Anyway, the system I used was quite an old one (thick credit card style), so the battery ran out before timing became an issue ;)

Nij on February 8, 2007 05:31 AM

Wow if you made 6.72 in interest on $20 in a year, I'd like to put some money in your sock too.

Eam:
I put a 20 in my sock last year, and now I have a 26-dollar-and-seventy-two-cent bill. Stupid compound interest.
Todd Derscheid on February 7, 2007 08:16 AM

Anom on February 8, 2007 08:24 AM

Did you ever see the online bank ING Direct password system? They had images that made up a numeric keyboard. The image names changed on every refresh. So you mouse clicked your numeric password and the image names were stored in a comma-delimited string form var. I assume that the image names corresponidng to each number were stored in a session hash table which would then be used to verify the password.

When you clicked on each number you'd see a password textbox add a * to it. The javascript was just adding an 'A' everytime to give the user an indication that the click had been registered.

E.R. on February 8, 2007 09:24 AM

Jeff / David H. - Smart cards are trusted processors, whereas a USB memory keys are just a storage mechanism. Have a look at the "How Stuff Works" entry on smart cards: http://computer.howstuffworks.com/question332.htm

Ideally, you use a smart card that can generate its own public/private key pair. You sign the smart card's public key w/ your enterprise CA and enroll the certificate into your enterprise PKI (publish into Active Directory, etc). The card can accept challenges and emit responses, and PIN entry by the user authenticates the user to the smart card, and permits the processor in the smart card to perform cryptographic operations using the private key. In a more advanced smart card, the private key would be encrypted with a symmetric algorithm using the user's PIN, and entry of the PIN would cause the private key to be decrypted into volatile RAM on the card that would be erased when the card was removed from the reader.

It would be really, really nice if we'd start using smart cards in place of what we currently use mag-stripe cards for in the US. Our GSM cell phones already provide a great basis for a smart card based payment infrastructure, if we could get anybody to agree on standards to use it.

Evan on February 8, 2007 05:16 PM

As Evan pointed out, there is a processor and public/private key encryption going on.

One thing he didn't emphasize that is important, is that the private key never leaves the card. The host computer may send a message or hash of a message to the fob to be encrypted, but the private bit is never visible outside. Because of this, without the fob plugged in, you can't send properly encrypted messages, which means the attacker has to do the dirty work RIGHT THERE AND THEN. (Annoying but somewhat common exception: if the fob was used to encrypt a temporary symmetric key which is used for all further communication in this session, the attacker may be able to "keep the session alive" for later use)

I believe a "man in the middle" attack is mostly thwarted by digital certificates, to the level that you trust the issuers (I'll use verisign as an example). Your browser knows who verisign is (contains their certificate), and can communicate securely with them to validate that your connection is encrypted DIRECTLY to the REAL jkl.com (jay-kay-ell.com). The weakness involved is related to whether you are browsing to jk1.com (jay-kay-number one.com) who verisign accidentally issued a certificate to, even though they are phishing for customers of jkl.com.

Of course, all of that doesn't help you if you (your destination) doesn't use https, if you "click through" the warning dialogs about "hostname does not match certificate", or don't type in the name of the domain you are going to by hand.

I think a compromised PC is the real vulnerability for two-factor setups at the current time.

greenup on February 9, 2007 02:51 PM

Oh, I suppose I should have mentioned I was using jkl.com and jk1.com as examples too. I have no idea what those sites might be about, but the first thing I thought of (xyz.com) didn't have something easily mistaken like {1,l,0,O} in it.

greenup on February 9, 2007 03:24 PM

Aha, I thought that might be the case. Thanks evan and greenup. The smartcard information available on the web is, er, not good.

So a smartcard is a great way of Keeping Private Keys Private:
http://www.codinghorror.com/blog/archives/000501.html

Jeff Atwood on February 10, 2007 02:44 AM

security anecdote:

Friday morning, email from ábove...

"As from Monday, ALL EMPLOYEES will be required to produce their electronic swipe card in order to enter the building"

"Employee electronic swipe cards will be issued on Thursday"

:)

Jonny on February 16, 2007 05:44 AM

Great hackers take hours to breach security.
Brute hackers take 15 minutes to get into the system, of which 10 is spent on attaching security admin to a chair with scotch tape.

Brute hacker on November 28, 2007 05:24 AM

That does no good if the security admin cannot override things on his own. ;)

Zian on March 5, 2008 01:50 AM

Needmypassword.com is a great way to store all of your usernames, passwords, and urls. Imagine only having to remember one password to gain instant access to all of your log-in needs! Needmypassword.com is safe and secure so you don't have to worry about anyone seeing your information except for you. It is also free and easy to use, so sign up now!

Danielle De Nora on May 6, 2008 01:03 PM







(hear it spoken)


(no HTML)




Content (c) 2008 Jeff Atwood. Logo image used with permission of the author. (c) 1993 Steven C. McConnell. All Rights Reserved.