spring

A Cucumber Scenario for Session Fixation Attacks

Tuesday, March 16th, 2010 | Uncategorized | No Comments

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 mod_jk. 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:

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.

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.

Tags: , , , , , , ,

Avoiding ambiguities when using @RequestMapping

Sunday, February 14th, 2010 | Uncategorized | No Comments

I’ve recently been using the param attribute of the @RequestMapping annotation from Spring MVC.

Take the case of a search feature for a website. If a ‘refine’ parameter is present, the user should be shown a search form to refine their criteria. However if the refine parameter is not present the user is shown the search results for the query.

@RequestMapping(value="/search", method=RequestMethod.GET)
public class SearchController {

  // Handles search?query=dog&refine=true
  @RequestMapping(params="refine=true")
  public void refine() { ... }

  // Handles search?query=dog
  @RequestMapping
  public void search() { ... }

}

While this code will initially work, there is some ambiguity in the way the URLs are matched. The order in which the @RequestMapping mappings are defined in the class file is actually determining which method will be called. If we were to define the search() method first, then a request to search?query=dog&refine=true would satisfy the conditions for the search() method’s @RequestMapping and thus the params="refine=true" on the refine() method has no bearing on the outcome of the request.

To safeguard the controller against the potential reordering of methods in a class (which in usual Java programming has no affect on the outcome of running code), we need to ensure the parameter mapping is explicit.

// Match if 'refine' parameter is present
@RequestMapping(params="refine=true")
public void refine() { ... }
// Match if 'refine' parameter is not present
@RequestMapping(params="!refine=true")
public void search() { ... }

By explicitly checking the refine parameter is not present for the search method’s request mapping (!refine=true), the declaration order of our @RequestMapping annotations in the class file has no bearing on which method handles the request thus making our code robust to the reordering methods. Similar precautions should be taken with the other attributes of @RequestMapping including method and headers.

Tags: , , , , , ,