-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add http response splitting rule
- Loading branch information
Showing
5 changed files
with
139 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
imports: | ||
- python_shared_common_user_input | ||
- python_shared_lang_http_server_handler | ||
patterns: | ||
- pattern: $<HANDLER>.send_header($<...>$<USER_INPUT>$<...>) | ||
filters: | ||
- variable: HANDLER | ||
detection: python_shared_lang_http_server_handler | ||
scope: cursor | ||
- variable: USER_INPUT | ||
detection: python_lang_http_response_splitting_user_input | ||
scope: result | ||
auxiliary: | ||
- id: python_lang_http_response_splitting_user_input | ||
sanitizer: python_lang_http_response_splitting_sanitizer | ||
patterns: | ||
- pattern: $<UNSANITIZED_USER_INPUT> | ||
filters: | ||
- variable: UNSANITIZED_USER_INPUT | ||
detection: python_shared_common_user_input | ||
scope: cursor | ||
- id: python_lang_http_response_splitting_sanitizer | ||
patterns: | ||
- pattern: $<ORIGINAL>.replace($<SOURCE>, $<REPLACEMENT>) | ||
focus: ORIGINAL | ||
filters: | ||
- variable: SOURCE | ||
string_regex: "\\r\\n|\\\\r\\\\n" | ||
- not: | ||
variable: REPLACEMENT | ||
string_regex: "\\r\\n|\\\\r\\\\n" | ||
languages: | ||
- python | ||
severity: high | ||
metadata: | ||
description: "Unsanitized user input in HTTP response (XSS)" | ||
remediation_message: |- | ||
## Description | ||
Including unsanitized user input in a HTTP response could allow an attacker inject Carriage Return Line Feed (CRLF) characters into the response. An entirely attacker-controlled response can then be returned, creating a cross-site scripting (XSS) vulnerability. | ||
## Remediations | ||
- **Do not** include user input in cookies or other HTTP headers without proper sanitization. This can prevent attackers from exploiting the input to manipulate the response. | ||
- **Do** remove CRLF sequences from user input to mitigate the risk of response splitting and XSS attacks. Use the following code snippet as a reference for sanitizing input in Java: | ||
```python | ||
input = request.getParameter("data"); | ||
var sanitized = input.replaceAll("\r\n", ""); | ||
cookie.setValue(sanitized); | ||
``` | ||
cwe_id: | ||
- 79 | ||
id: python_lang_http_response_splitting | ||
documentation_url: https://docs.bearer.com/reference/rules/python_lang_http_response_splitting |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
type: shared | ||
languages: | ||
- python | ||
imports: | ||
- python_shared_lang_instance | ||
- python_shared_lang_import2 | ||
patterns: | ||
- pattern: $<INSTANCE> | ||
filters: | ||
- variable: INSTANCE | ||
detection: python_shared_lang_instance | ||
scope: cursor_strict | ||
filters: | ||
- variable: CLASS | ||
detection: python_shared_lang_import2 | ||
scope: cursor | ||
filters: | ||
- variable: MODULE1 | ||
values: [http] | ||
- variable: MODULE2 | ||
values: [server] | ||
- variable: NAME | ||
values: [BaseHTTPRequestHandler] | ||
metadata: | ||
description: "Python http.server handler instance" | ||
id: python_shared_lang_http_server_handler |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,15 @@ | ||
type: shared | ||
languages: | ||
- python | ||
imports: | ||
- python_shared_lang_http_server_handler | ||
patterns: | ||
- input($<...>) | ||
- pattern: $<HANDLER>.path | ||
filters: | ||
- variable: HANDLER | ||
detection: python_shared_lang_http_server_handler | ||
scope: cursor | ||
metadata: | ||
description: "Python lang user input." | ||
id: python_shared_lang_user_input |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
const { | ||
createNewInvoker, | ||
getEnvironment, | ||
} = require("../../../helper.js") | ||
const { ruleId, ruleFile, testBase } = getEnvironment(__dirname) | ||
|
||
describe(ruleId, () => { | ||
const invoke = createNewInvoker(ruleId, ruleFile, testBase) | ||
|
||
test("http_response_splitting", () => { | ||
const testCase = "main.py" | ||
|
||
const results = invoke(testCase) | ||
|
||
expect(results).toEqual({ | ||
Missing: [], | ||
Extra: [] | ||
}) | ||
}) | ||
}) |
32 changes: 32 additions & 0 deletions
32
tests/python/lang/http_response_splitting/testdata/main.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# this file is also testing the shared instance rule | ||
|
||
from http.server import BaseHTTPRequestHandler | ||
|
||
class WebRequestHandler(BaseHTTPRequestHandler, Foo): | ||
def do_GET(self): | ||
self.send_header("ok", "ok") | ||
|
||
# bearer:expected python_lang_http_response_splitting | ||
self.send_header(self.path, "ok") | ||
|
||
def do_POST(self): | ||
self.send_header(self.path.replace("\r\n", ""), "ok") | ||
self.send_header("ok", self.path.replace("\r\n", "")) | ||
|
||
# bearer:expected python_lang_http_response_splitting | ||
self.send_header("ok", self.path) | ||
|
||
|
||
# contrived examples for testing instance rule | ||
class Other: | ||
def m(self, x: BaseHTTPRequestHandler) -> string: | ||
# bearer:expected python_lang_http_response_splitting | ||
x.send_header(input(), "ok") | ||
|
||
y = BaseHTTPRequestHandler(foo) | ||
# bearer:expected python_lang_http_response_splitting | ||
y.send_header(input(), "ok") | ||
|
||
def m(self, z: BaseHTTPRequestHandler = default) -> string: | ||
# bearer:expected python_lang_http_response_splitting | ||
z.send_header(input(), "ok") |