Session Exploit Testing with Capybara

January 27, 2013

A little while back at work we needed to write a feature that would test some fairly complicated session exchanging logic. I dreaded the task of testing it because I was certain it was going to be painful. I’d probably have to monkey around in Capybara internals to mutate the cookie jar the way an attacker would. It turns out Capybara handles this quite elegantly.

Identifying the Attack Vector

In short, our problem is that all of our clients have their own domain without their own SSL cert. That’s fine, but when it comes to checkout and sensitive account actions, they needed to be transferred over to our secure domain, which will have a different, secure-only session cookie.

One of the attack vectors we focused on was an attacker sniffing out a token from when a user was browsing insecure pages on the site and parleying that token into the secure parts of the site to steal private information, check out, etc. An attacker would sniff that session, set it as their own in their own browser and then try to do nefarious stuff.

Capybara has Named Sessions!

After doing it the hard way, we learned that Capybara comes with multiple session support out of the box. In any given test, Capybara can maintain multiple browser sessions.

A security test you’d write in cucumber may look like this:

Given I am browsing the site
  And I add some stuff to my cart
 When an attacker attempts to steal my cart
 Then they should not have a cart
  But I should still see my cart

And some of the steps could look like

When "an attacker attempts to steal my cart" do
  stolen_session_id = Capybara.current_session.driver.request.cookies['_session_id']

  Capybara.using_session(:attacker) do
    page.driver.browser.set_cookie("_session_id=#{stolen_session_id}")
  end
end

If you have lots of different steps featuring the attacker, you may even want to extract it to a method:

  def as_attacker(&block)
    Capybara.using_session(attacker, &block)
  end