Skip to content

Commit

Permalink
[playframework#1353] Added hash collision attack protection
Browse files Browse the repository at this point in the history
  • Loading branch information
mbknor committed Jan 9, 2012
1 parent aa04c80 commit ee22619
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
13 changes: 13 additions & 0 deletions framework/src/play/data/parsing/UrlEncodedParser.java
Expand Up @@ -9,6 +9,7 @@
import java.util.Map;

import play.Logger;
import play.Play;
import play.exceptions.UnexpectedException;
import play.mvc.Http;
import play.utils.Utils;
Expand All @@ -17,6 +18,9 @@
* Parse url-encoded requests.
*/
public class UrlEncodedParser extends DataParser {

// Sets the maximum count of accepted POST params - protection against Hash collision DOS attacks
private static final int maxParams = Integer.parseInt(Play.configuration.getProperty("http.maxParams", "1000")); // 0 == no limit

boolean forQueryString = false;

Expand Down Expand Up @@ -67,6 +71,15 @@ public Map<String, String[]> parse(InputStream is) {
// NB: _charset_ must always be used with accept-charset and it must have the same value

String[] keyValues = data.split("&");


// to prevent the Play-server from being vulnerable to POST hash collision DOS-attack (Denial of Service through hash table multi-collisions),
// we should by default not parse the params into HashMap if the count exceeds a maximum limit
if(maxParams != 0 && keyValues.length > maxParams) {
Logger.warn("Number of request parameters %d is higher than maximum of %d, aborting. Can be configured using 'http.maxParams'", keyValues.length, maxParams);
throw new RuntimeException("Too many parameters!");
}

for (String keyValue : keyValues) {
// split this key-value on the first '='
int i = keyValue.indexOf('=');
Expand Down
17 changes: 17 additions & 0 deletions samples-and-tests/just-test-cases/test/RestTest.java
Expand Up @@ -151,4 +151,21 @@ public void testWSAsyncWithException() {
assertEquals("ok", res);
}

// Test our "Denial of Service through hash table multi-collisions"-protection
@Test
public void testPostHashCollisionProtection() {
// generate some post data with 1000 params
// PS: these keys does not have hash-colition, but our protection is only looking at the count
Map<String, Object> manyParams = new HashMap<String, Object>();
for ( int i=0; i < 1000; i++) {
manyParams.put("a"+i, ""+i);
}

assertEquals("POST", WS.url("http://localhost:9003/Rest/echoHttpMethod").params(manyParams).post().getString());

// now add one more to push the limit
manyParams.put("anotherone", "x");
assertEquals(500, (int)WS.url("http://localhost:9003/Rest/echoHttpMethod").params(manyParams).post().getStatus());
}

}

0 comments on commit ee22619

Please sign in to comment.