The Request With Too Many Parameters — Java Bug Hunt
Modelled on the hash-collision denial-of-service advisory of December 2011 (oCERT-2011-003), presented by Alexander Klink and Julian Wälde at the 28th Chaos…
- Language: Java
- Layer: Backend
- Difficulty: Easy
- Concepts: Security, Parsing, Limits
- Modelled on: Hash-collision DoS · oCERT-2011-003
- Visible tests: a normal form parses; a body over the cap is refused
- Reward: 50 XP for a complete fix
Briefing
Modelled on the hash-collision denial-of-service advisory of December 2011 (oCERT-2011-003), presented by Alexander Klink and Julian Wälde at the 28th Chaos Communication Congress. The hash tables that web platforms — PHP, Java application servers, Python, ASP.NET and others — used to hold request parameters could be pushed into their worst case by a request carrying very many parameters, so parsing a single POST body could tie up a CPU for a long time. Among the mitigations, PHP 5.3.9 added max_input_vars (default 1000) and Tomcat added a maximum parameter count: stop accepting parameters past a cap.
This reconstruction's form parser has a maxParams argument but never enforces it.
Fix FormParser.parse so a body with more parameters than the cap is rejected, while normal parsing stays exactly as it is.
Bug report
BUG-HASHDOS · Priority: High · Reported by: platform security
FormParser.parse(body, maxParams) -> LinkedHashMap in first-seen order:
- the body is split on "&"; empty segments are ignored and do not count
- each segment splits at its FIRST "=": key before, value after (the value may itself contain "="); a segment with no "=" is a key with value ""
- a repeated key overwrites the earlier value but still counts as a parameter
- if the number of counted parameters exceeds maxParams, throw TooManyParametersException (the whole request is refused; exactly maxParams parameters is fine)
- parse(body) uses Limits.MAX_INPUT_VARS (1000)
Observed: a body with 200,000 parameters was parsed in full.
Logs
[http] POST /login body=4.1MB params=200000
[http] worker 7 busy for 94s parsing form bodyThe code as shipped
src/http/FormParser.java (editable)
class FormParser {
// Parses an application/x-www-form-urlencoded body (this service does no
// percent-decoding). Later duplicates overwrite earlier ones.
static Map<String, String> parse(String body, int maxParams) {
Map<String, String> params = new LinkedHashMap<>();
for (String pair : body.split("&")) {
if (pair.isEmpty()) continue;
int eq = pair.indexOf('=');
String key = eq < 0 ? pair : pair.substring(0, eq);
String value = eq < 0 ? "" : pair.substring(eq + 1);
params.put(key, value);
}
return params;
}
static Map<String, String> parse(String body) {
return parse(body, Limits.MAX_INPUT_VARS);
}
}
Read-only context: src/http/Limits.java.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More Java bug hunts.