September 23, 2008
Cross-Site Request Forgeries and You
As the web becomes more and more pervasive, so do web-based security vulnerabilities. I talked a little bit about the most common web vulnerability, cross-site scripting, in Protecting Your Cookies: HttpOnly. Although XSS is incredibly dangerous, it's a fairly straightforward exploit to understand. Do not allow users to insert arbitrary HTML on your site. The name of the XSS game is sanitizing user input. If you stick to a whitelist based approach -- only allow input that you know to be good, and immediately discard anything else -- then you're usually well on your way to solving any XSS problems you might have.
I thought we had our website vulnerabilies licked with XSS. I was wrong. Steve Sanderson explains:
Since XSS gets all the limelight, few developers pay much attention to another form of attack that's equally destructive and potentially far easier to exploit. Your application can be vulnerable to cross-site request forgery (CSRF) attacks not because you the developer did something wrong (as in, failing to encode outputs leads to XSS), but simply because of how the whole Web is designed to work. Scary!
It turns out I didn't understand how cross-site request forgery, also known as XSRF or CSRF, works. It's not complicated, necessarily, but it's more.. subtle.. than XSS.
Let's say we allow users to post images on our forum. What if one of our users posted this image?
<img src="http://foo.com/logout">
Not really an image, true, but it will force the target URL to be retrieved by any random user who happens to browse that page -- using their browser credentials! From the webserver's perspective, there is no difference whatsoever between a real user initiated browser request and the above image URL retrieval.
If our logout page was a simple HTTP GET that required no confirmation, every user who visited that page would immediately be logged out. That's XSRF in action. Not necessarily dangerous, but annoying. Not too difficult to envision much more destructive versions of this technique, is it?
There are two obvious ways around this sort of basic XSRF attack:
- Use a HTTP POST form submission for logout, not a garden variety HTTP GET.
- Make the user confirm the logout.
Easy fix, right? We probably should never have never done either of these things in the first place. Duh!
Not so fast. Even with both of the above fixes, you are still vulnerable to XSRF attacks. Let's say I took my own advice, and converted the logout form to a HTTP POST, with a big button titled "Log Me Out" confirming the action. What's to stop a malicious user from placing a form like this on their own website ..
<body onload="document.getElementById('f').submit()">
<form id="f" action="http://foo.com/logout" method="post">
<input name="Log Me Out" value="Log Me Out" />
</form>
</body>
.. and then convincing other users to click on it?
Remember, the browser will happily act on this request, submitting this form along with all necessary cookies and credentials directly to your website. Blam. Logged out. Exactly as if they had clicked on the "Log Me Out" button themselves.
Sure, it takes a tiny bit more social engineering to convince users to visit some random web page, but it's not much. And the possibilities for attack are enormous: with XSRF, malicious users can initiate any arbitrary action they like on a target website. All they need to do is trick unwary users of your website -- who already have a validated user session cookie stored in their browser -- into clicking on their links.
So what can we do to protect our websites from these kinds of cross site request forgeries?
- Check the referrer. The HTTP referrer, or HTTP "referer" as it is now permanently misspelled, should always come from your own domain. You could reject any form posts from alien referrers. However, this is risky, as some corporate proxies strip the referrer from all HTTP requests as an anonymization feature. You would end up potentially blocking legitimate users. Furthermore, spoofing the referrer value is extremely easy. All in all, a waste of time. Don't even bother with referrer checks.
- Secret hidden form value. Send down a unique server form value with each form -- typically tied to the user session -- and validate that you get the same value back in the form post. The attacker can't simply scrape your remote form as the target user through JavaScript, thanks to same-domain request limits in the
XmlHttpRequestfunction. - Double submitted cookies. It's sort of ironic, but another way to prevent XSRF, essentially a cookie-based exploit, is to add more cookies! Double submitting means sending the cookie both ways in every form request: first as a traditional header value, and again as a form value -- read via JavaScript and inserted. The trick here is that remote
XmlHttpRequestcalls can't read cookies. If either of the values don't match, discard the input as spoofed. The only downside to this approach is that it does require your users to have JavaScript enabled, otherwise their own form submissions will be rejected.
If your web site is vulnerable to XSRF, you're in good company. Digg, GMail, and Wikipedia have all been successfully attacked this way before.
Maybe you're already protected from XSRF. Some web frameworks provide built in protection for XSRF attacks, usually through unique form tokens. But do you know for sure? Don't make the same mistake I did! Understand how XSRF works and ensure you're protected before it becomes a problem.
September 18, 2008
Bill Gates and Code Complete
By now I'm sure you've at least heard of, if not already seen, the new Windows Vista advertisements featuring Bill Gates and Jerry Seinfeld. They haven't been well received, to put it mildly, but the latest commercial is actually not bad in its longer 4 minute version:
On the whole, I'd call these ads opaque bordering on inane. Rumor has it the entire thing has been cancelled. It wasn't entirely unsuccessful, I suppose; the goal of advertising is to get people talking about it. Even if every one of those conversations starts with "what the hell were they thinking", hey -- it's a conversation. About an ad. The ad agencies have won.
I guess Microsoft figured it had to do something to counter the long running "I'm a Mac, I'm a PC" ads from Apple. I secretly love these ads, because the hidden subtext is that if you use a PC, you're as cool as John Hodgman:
My problem with these ads begins with the casting. As the Mac character, Justin Long (who was in the forgettable movie Dodgeball and the forgettabler TV show Ed) is just the sort of unshaven, hoodie-wearing, hands-in-pockets hipster we've always imagined when picturing a Mac enthusiast. He's perfect. Too perfect. It's like Apple is parodying its own image while also cementing it. If the idea was to reach out to new types of consumers (the kind who aren't already evangelizing for Macs), they ought to have used a different type of actor.Meanwhile, the PC is played by John Hodgman -- contributor to The Daily Show and This American Life, host of an amusing lecture series, and all-around dry-wit extraordinaire. Even as he plays the chump in these Apple spots, his humor and likability are evident. (Look at that hilariously perfect pratfall he pulls off in the spot titled "Viruses.") The ads pose a seemingly obvious question -- would you rather be the laid-back young dude or the portly old dweeb? -- but I found myself consistently giving the "wrong" answer: I'd much sooner associate myself with Hodgman than with Long.
The sleight of hand breaks down a bit when you realize that Hodgman actually uses Macs, but that's advertising for you: a giant pack of lies. In other breaking news, water still wet, sky still blue.
The reason I bring this up is not to fan the eternal flame of platform wars, but to highlight one interesting little detail in the ad. At about 1:05, you'll see Gates reading a bedtime story to the family's son from some obscure technical tome or other. But not just any technical tome -- he's reading from the book that this very blog is named after, my all-time favorite programming book, Steve McConnell's Code Complete.
You can use [the table driven method] approach in any object-oriented language. It's less error-prone, more maintainable and more efficient than lengthy if statements, case statements or copious subclasses. The fact that a design uses inheritance and polymorphism doesn't make it a good design. The rote object-oriented design described earlier in the "Object-Oriented Approach" section would require as much code as a rote functional design -- or more.
The above is excerpted from Chapter 18 of "Table-Driven Methods", on page 423. You might argue that I have an unhealthy fascination with Steve McConnell and Code Complete. You wouldn't be wrong.
I'm probably preaching to the choir here, but I doubt it's a coincidence that Gates chose that particular book; I'm sure it's one of his all time favorite books, too.
Hat tip to Matthew Eckstein for pointing this one out!
September 16, 2008
Stack Overflow: None of Us is as Dumb as All of Us
I'm in no way trying to conflate this with the meaning of my last blog post, but after a six month gestation, we just gave birth to a public website.
Of course, I'm making a sly little joke here about community, but I really believe in this stuff. Stack Overflow is, as much as I could make it, an effort of collective programmer community.
Here's the original vision statement for Stack Overflow from back in April:
So what is stackoverflow?From day one, my blog has been about putting helpful information out into the world. I never had any particular aspirations for this blog to become what it is today; I'm humbled and gratified by its amazing success. It has quite literally changed my life. Blogs are fantastic resources, but as much as I might encourage my fellow programmers to blog, not everyone has the time or inclination to start a blog. There's far too much great programming information trapped in forums, buried in online help, or hidden away in books that nobody buys any more. We'd like to unlock all that. Let's create something that makes it easy to participate, and put it online in a form that is trivially easy to find.
Are you familiar with the movie pitch formula?
Stackoverflow is sort of like the anti-experts-exchange (minus the nausea-inducing sleaze and quasi-legal search engine gaming) meets wikipedia meets programming reddit. It is by programmers, for programmers, with the ultimate intent of collectively increasing the sum total of good programming knowledge in the world. No matter what programming language you use, or what operating system you call home. Better programming is our goal.
Although reaction has generally been positive, there has been a bit of backlash. Some have promoted the idea that Stack Overflow will only contribute to the increasing dumbenation of the world's developers. I think this is, in a word, horsecrap. I liked Joel's response to this in podcast 21 (mp3):
And it is true that we are all, as developers, hopelessly incompetent. The goal of a site like Stack Overflow is to somehow share the correct knowledge wherever it may be as it is scattered throughout the universe, and to cause that to be voted up and to be spread amongst us. There's this big universe of dumb programmers, and I'm one of them, and we all have a little bit of knowledge. I may know how to do this thing in VB6 which may be useful to somebody one day who's trying to maintain some ridiculously old piece of crap code. We all have these little tiny pieces of information and if we can just contribute a little bit, that information gets amplified, and maybe a thousand other dumb developers will benefit from my one little piece of good information.
And here's my response, from the same podcast episode, to all those who turn up their noses at community sites like this, preferring the input of "experts":
The idea that you have all these experts waiting in the wings to do stuff is an illusion in my experience. There's really just a bunch of amateurs muddling along trying to do things together. The people that are truly experts are too busy to even help, right? And if the experts are too busy to help, what difference does it really make if there are experts at all. Because the whole point of this endeavor is helping other developers, and whether you're an expert or not, if you have no time to help, you're not really contributing to the solution.
Stack Overflow is by no means done. We're still technically in public beta. But I believe what we have -- the confluence of wiki, discussion, blog, and reddit/digg ranking systems -- is a fair representation of our original vision for Stack Overflow.
It's a place where a busy programmer can invest a few minutes with as little friction as possible, and get something tangible from the community in return.
But who cares what I think; my opinion holds no particular weight. I'm just a member. This is our site. You tell me: how dumb are we?
September 7, 2008
Spawning a New Process
I don't usually talk about my personal life here, but I have to make an exception in this case.
I debated for days which geeky reference I would use as a synonym for "we're having a baby". The title is the best I could do. I'm truly sorry.
As an aside, this is something my wife and I have worked at for a number of years, and was only truly possible through the Miracle of Sciencetm. Despite the best of intentions, you really start to resent all those teenage couples who manage to get pregnant so awkwardly and accidentally. Oh, that's right! You have sex! It's so obvious in retrospect!
Not that managing to procreate is anything special compared to programming. Just ask the inestimable Richard Stallman:
It doesn't take special talents to reproduce -- even plants can do it. On the other hand, contributing to a program like Emacs takes real skill. That is really something to be proud of.It helps more people, too.
At any rate, I'm looking forward to stocking our unborn child's mind with all my insane, crazy ideas. I think Dave Eggers said it best in A Heartbreaking Work of Staggering Genius, describing a road trip he took with his younger brother after the death of his parents:
His brain is my laboratory, my depository. Into it I can stuff the books I choose, the television shows, the movies, my opinion about elected officials, historical events, neighbors, passersby. He is my twenty-four-hour classroom, my captive audience, forced to ingest everything I deem worthwhile. He is a lucky, lucky boy! And no one can stop me. He is mine, and you cannot stop me, cannot stop us. Try to stop us, you pu**y! You can't stop us from singing, and you can't stop us from making fart sounds, from putting our hands out the window to test the aerodynamics of different hand formations, from wiping the contents of our noses under the front of our seats.We cannot be stopped from looking with pity upon all the world's sorry inhabitants, they unblessed by our charms, unchallenged by our trials, unscarred and thus weak, gelatinous. You cannot stop me from telling Toph to make comments about and faces at the people in the next lane.
It's unfair. The matchups, Us. v. Them (or you) are unfair. We are dangerous. We are daring and immortal. Fog whips up from under the cliffs and billows over the highway. Blue breaks from beyond the fog and sun suddenly screams from the blue.
I guess what I'm trying to say is that, with any luck, he or she will be scarred for life. That's a proud family tradition where I come from.
