Permalink
Browse files

[#1353] Added hash collision attack protection

  • Loading branch information...
1 parent df317c0 commit df9713b3dda751dd626925ba523bcc93eed958c3 @mbknor mbknor committed Jan 9, 2012
@@ -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;
@@ -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;
@@ -67,6 +71,15 @@
// 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('=');
@@ -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 df9713b

Please sign in to comment.