Skip to content

Commit

Permalink
feat(java): HTTP Param Pollution
Browse files Browse the repository at this point in the history
  • Loading branch information
elsapet committed Jan 31, 2024
1 parent 67709b3 commit b4ba9be
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 0 deletions.
86 changes: 86 additions & 0 deletions rules/java/lang/http_parameter_pollution.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
imports:
- java_shared_lang_instance
- java_shared_lang_servlet_request
patterns:
# Version 4.x and greater
- pattern: new $<HTTP_GET>($<USER_INPUT>);
filters:
- variable: HTTP_GET
regex: \A(org\.apache\.http\.client\.methods\.)?HttpGet\z
- variable: USER_INPUT
detection: java_lang_http_parameter_pollution_user_input
scope: result
# Legacy GetMethod
- pattern: new $<GET_METHOD>($<USER_INPUT>);
filters:
- variable: GET_METHOD
regex: \A(org\.apache\.commons\.httpclient\.methods\.)?GetMethod\z
- variable: USER_INPUT
detection: java_lang_http_parameter_pollution_user_input
scope: result
- pattern: $<GET_METHOD>.setQueryString($<USER_INPUT>);
filters:
- variable: GET_METHOD
detection: java_shared_lang_instance
scope: cursor
filters:
- variable: JAVA_SHARED_LANG_INSTANCE_TYPE
regex: \A(org\.apache\.commons\.httpclient\.methods\.)?GetMethod\z
- variable: USER_INPUT
detection: java_lang_http_parameter_pollution_user_input
scope: result
auxiliary:
- id: java_lang_http_parameter_pollution_user_input
sanitizer: java_lang_http_parameter_pollution_sanitizer
patterns:
- pattern: $<JAVA_SHARED_LANG_USER_INPUT_REQUEST>.getParameter();
filters:
- variable: JAVA_SHARED_LANG_USER_INPUT_REQUEST
detection: java_shared_lang_servlet_request
scope: cursor
- id: java_lang_http_parameter_pollution_sanitizer
patterns:
- pattern: $<CLASS>.encode($<!>$<_>);
filters:
- variable: CLASS
regex: \A(java\.net\.)?URLEncoder\z
- pattern: $<PATH_SEGMENT_ESCAPER>.escape($<!>$<_>);
filters:
- variable: PATH_SEGMENT_ESCAPER
regex: \A((com\.google\.common\.net\.)?UrlEscapers\.)?urlPathSegmentEscaper\(\)\z
languages:
- java
metadata:
description: "Possible HTTP Parameter Pollution detected."
remediation_message: |
## Description
Unsanitized user input is being used to construct a URL.
This can lead to HTTP Parameter Pollution (HPP) attacks, where an attacker overrides the
value of a URL or request parameter, to manipulate requests or retrieve otherwise hidden information.
## Remediations
❌ Never use direct or unsanitized user input when constructing URLs or URL parameters. Seek alternatives instead.
For example, use a map to convert user input to an appropriate parameter.
```java
HashMap<String, String> lookupTable = new HashMap<>();
// ... populate hash map
String rawUserInput = request.getParameter("someParam")
String value = lookupTable.getOrDefault(rawUserInput, "someDefault") ;
HttpGet httpget = new HttpGet("https://example.com/?param="+value);
```
✅ Always sanitize user input
```java
String rawUserInput = request.getParameter("someParam");
String encoded = java.net.URLEncoder.encode(rawUserInput, StandardCharsets.UTF_8);
```
cwe_id:
- 88
id: java_lang_http_parameter_pollution
documentation_url: https://docs.bearer.com/reference/rules/java_lang_http_parameter_pollution
18 changes: 18 additions & 0 deletions tests/java/lang/http_parameter_pollution/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const {
createNewInvoker,
getEnvironment,
} = require("../../../helper.js")
const { ruleId, ruleFile, testBase } = getEnvironment(__dirname)

describe(ruleId, () => {
const invoke = createNewInvoker(ruleId, ruleFile, testBase)

test("http_parameter_pollution", () => {
const testCase = "main.java"

const results = invoke(testCase)

expect(results.Missing).toEqual([])
expect(results.Extra).toEqual([])
})
})
40 changes: 40 additions & 0 deletions tests/java/lang/http_parameter_pollution/testdata/main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import org.apache.http.client.methods.HttpGet;
// legacy
import org.apache.commons.httpclient.methods.GetMethod;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import static com.google.common.net.UrlEscapers.urlPathSegmentEscaper;

public class Foo extends HttpServlet {
public void bad(HttpServletRequest req, HttpServletResponse res) {
String externalParam = req.getParameter("foo");

// bearer:expected java_lang_http_parameter_pollution
HttpGet httpget2 = new HttpGet("http://example.com?param=" + externalParam);
}

public void legacyBad(HttpServletRequest req, HttpServletResponse res) {
String externalParam = req.getParameter("bar");

// bearer:expected java_lang_http_parameter_pollution
GetMethod get = new GetMethod("http://example.com?param=" + externalParam);
// bearer:expected java_lang_http_parameter_pollution
get.setQueryString("param=" + externalParam);
}

public void ok(HttpServletRequest req, HttpServletResponse response) {
String externalParam = req.getParameter("baz");
String escapedParam = urlPathSegmentEscaper().escape(externalParam);

HttpGet escaped = new HttpGet("http://example.com?param=" + escapedParam);

GetMethod get = new GetMethod("http://example.com?param=" + URLEncoder.encode(externalParam));

String escapedParam2 = UrlEscapers.urlPathSegmentEscaper().escape(externalParam);
GetMethod get = new GetMethod("http://example.com?param=" + escapedParam2);
get.setQueryString("param=" + escapedParam2);
}
}

0 comments on commit b4ba9be

Please sign in to comment.