Home Page Design and Cross Site Request Forgery

Feb 22, 2010
Episode 13
Nick gives some quick tips on how to design home pages and Jim goes in depth on CSRF or cross site request forgery.
Spotlight

Home Page Design

Your homepage should be simple and easy to understand for your audience. For most websites the homepage is the most highly trafficked part of the site. This means that all the stakeholders, like the marketing department, business people, and web designers, are all going to have their own opinions about what should go there. If the homepage gets too cluttered up, then nobody wins.

Goals

The question to ask when designing your home page is, what are the goals of your site? What do you want the user to watch, or buy, or do next? It's impossible to predict really, but keeping your goal in mind will help guide every decision you make.

Next you need to consider a goal of a different kind. What will a new visitor want, and what will a returning visitor want? It can be tricky, but you need to facilitate both. Amazon.com does an outstanding job of this. They have a large image of a major promotion for new visitors, but for returning visitors, they also show product recomamendations. New visitors are usually just going to want to browse, but returning visitors probably have a more specific task in mind. Think about what that might be.

Layout

Often times, it's a good idea to create a very different layout for your homepage, versus the rest of the site. The theming should feel the same, but because the goals of a homepage are often so different than the site's content, you need a design that can direct visitors to what they want, more quickly. Also keep in mind that the homepage might be a visitor's first impression of your brand. It's important to get across the spirit of your message, your colors, your logo, and other pertinent information.

Lastly, be sure to have a call to action. It should take the user to the most important part of your site, like a pricing page. In the case of Doctype, our new home page has large clickable areas that take you to the latest episode.

Copy

Your home page has to answer three things:

  • Where am I?
  • Why should I stay?
  • Why should I come back?

By writing clear, easy to understand copy, you can answer all these questions in just a sentence or two. On the homepage of Doctype for example, the most prominent sentence is the tagline: "The Show for People Who Make Websites" - Even if you don't know anything about web design, it gives you some idea of what the site is about. In smaller text, it says "New Episode Every Tuesday" - This gives the viewer a reason to come back later on, by letting them know when we release new content they might be interested in.

Resources

Cross Site Request Forgery

When building web applications, security must be a top concern in order for our users to trust our services. Typically web applications utilize a login system based on browser cookies. While this adds a layer of security, there are several attack strategies that try to circumvent it.

In Episode 3 of Doctype we looked at the Cross Domain policies of Ajax in browsers, and how it helps protect us.

This week we are going to look at an attack known as Cross Site Request Forgery, or CSRF.

Background

Most login schemes rely on cookies to remember which account a they are logged into. This is pretty secure because browsers won’t reveal the cookie information of one site to another.

Most attacks focus on either gaining access to the cookie itself, or getting a browser that already has a valid cookie to perform actions on the attacker’s behalf.

We are going to use twitter.But twitter has already put in place the precautions we are going to show you.

In our examples, I am going to try to make a tweet from Nick’s account. Nick will have logged into twitter recently, so will have an active session in his browser.

GET vs POST

Imagine if the url for tweeting were functional through a GET request.

For instance the url

http://twitter.com/update?status=I+got+hacked

One conceivable way I could make a tweet from Nick’s account is to send him an email with a url I have created to make the tweet, and some text that will entice him to click it

<a href="http://twitter.com/update?status=I+got+hacked">
  YOU HAVE TO SEE THIS!!!!
</a>

Hopefully Nick won’t be cautious enough to review the URL before he clicks it. When he does, we will make a request to Twitter to update his status. Because he still has a valid cookie, it will go through.

Now, he will probably also notice he is on twitter, and will probably see the tweet i made on his behalf, and delete it. But here is why it is SO important that any action that has side effects be only allowed through post requests.

Instead of getting him to click a link directly to twitter, I could create a page with that URL inside of an Image tag

<img src="http://twitter.com/update?status=I+got+hacked">

When he views the page, the browser will make a GET request trying to fetch the image. It will send all of twitter’s cookies with the request, so it will be authenticated, and create the tweet. Nick will be none the wiser, the only evidence is a broken image that could be easily hidden.

Image tags, along with script tags, iframes, and link tags will only request using GET, so if you make your important actions only accessible from POST requests, you protect from this kind of attack.

Authenticity Tokens

Just refusing GET requests does not protect you fully.

<form action="http://twitter.com/update" method="post">
  <input type="hidden" name="status" value="I got hacked">
</form>

<script type="text/javascript">
  $('form').submit();
</script>

My malicious page page could have just as easily created a form with twitter as the action, a POST method, and the fields in hidden inputs, and submitted it through JavaScript. It would be a POST request being sent from Nick’s browser withe Nick’s credentials, and would create the tweet successfully.

<form action="/update" method="post">
  <input type="hidden" name="authenticity_token" 
         value="<?php echo auth_token() ?>">

  <input type="text" name="status" value="I got hacked">
  <input type="submit" value="Update">
</form>


//Process /update
if( is_valid_auth_token($_POST['authenticity_token']) ){
  //Valid Request
}else{
  //Invalid
}

To protect against this attack, we want to create a secret value, an authenticity token, that an attacker could not possibly guess. Then we put that value as a hidden field in any of our legitimate forms. When we process our forms, we check for that authenticity token, if it is missing, or invalid, we discard the request.

When we generate our auth token, we must ensure tree things:

  1. It is impossible for an attacker to predict
  2. It is unique to the user
  3. It will not change from one request to another for a given user

A common approach is to hash a piece of information that is unique to the user, and wouldn’t be easily discovered by the attacker.

For instance a session ID is ideal since it is already pretty random, and it is concealed from the outside world.

function auth_token(){
  return md5(session_id());
}

You could also salt the hash with some secret string to make it more difficult to spoof the hash

function auth_token(){
  return md5(session_id() . "some secret string");
}

When you check the auth token, you just need to check that the token sent is the same as the one you calculate yourself.

function is_valid_auth_token($sent_token){
  return $sent_token == auth_token();
}

Now that an attacker cannot figure out a valid authenticity token, he can not easily trick another browser to make a request by crafting his own form.

Resources