rapaul.com

A technical blog written by Richard Paul

A Cucumber Scenario for Session Fixation Attacks

When working on a Spring project I was alerted via the logs that my login handling was susceptible to Session Fixation Attacks. It was nice of Spring to alert me of this, and it seems like the problem is due to the Apache httpd connection via modjk. But before diving into a solution I decided to write a simple acceptance test using Cucumber. This allows me to first prove the security hole is present, easily tell when I have fixed it and has the additional benefit of being able to add the check to a set of automated regression tests to ensure it never happens again.

The countermeasure built into Spring uses the Identity Confirmation technique. This basically involves invalidating a user’s session when they login and creating a new session with a different JSESSIONID. It turns out to be fairly easy to write a test for this in Cucumber. Firstly I wrote the plain text scenario:

1
2
3
4
Scenario: Avoiding Session Fixation Attacks through Identity Confirmation
Given I have a session ID
When I sign in
Then I should have a different session ID

The next step is to write the step definitions. Cuke4Duke provides Cucumber support for JVM languages and makes it easy to write reusable step definitions. As I’m a fan of the expressiveness of Groovy I chose to write the step definitions using the GroovyDsl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import org.openqa.selenium.By
import static org.junit.Assert.*
import static org.junit.matchers.JUnitMatchers.*
import static org.hamcrest.CoreMatchers.*

this.metaClass.mixin(cuke4duke.GroovyDsl)

def sessionId

Given(~'I have a session ID') {
  browser.get("$host/signin")
  sessionId = getSessionId()
}

When(~'I sign in') {
  def signinForm = browser.findElement(By.name('signin'))
  signinForm.findElement(By.name('j_username')).sendKeys('testing@example.com')
  signinForm.findElement(By.name('j_password')).sendKeys('123456')
  signinForm.submit()
}

Then(~'I should have a different session ID') {
  assertThat(getSessionId(), is(not(sessionId)));
}

def getSessionId() {
  browser.manage().cookies.find() { it.name == 'JSESSIONID' }.value
}

The browser variable is injected via env.groovy as an instance of WebDriver which provides the methods to find elements and manage cookies.

def sessionId simply declares a variable allowing sharing of state between the steps so we can check the session ID has been changed.

Comments