Add documentation

This commit is contained in:
Joe Farebrother
2024-04-05 13:54:44 +01:00
parent 8636a50190
commit daa31b5bb7
4 changed files with 58 additions and 35 deletions

View File

@@ -0,0 +1,41 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>Directly writing user input (for example, an HTTP request parameter) to an HTTP header
can lead to an HTTP response-splitting vulnerability.</p>
<p>If user-controlled input is used in an HTTP header that allows line break characters, an attacker can
inject additional headers or control the response body, leading to vulnerabilities such as XSS or cache poisoning.
</p>
</overview>
<recommendation>
Ensure that user input containing line break characters is not written to an HTTP header.
</recommendation>
<example>
In the following example, the case marked BAD writes user input to the header name.
In the GOOD case, input is first escaped to not contain any line break characters.
<sample src="examples/header_injection.py" />
</example>
<references>
<li>
SecLists.org: <a href="https://seclists.org/bugtraq/2005/Apr/187">HTTP response splitting</a>.
</li>
<li>
OWASP:
<a href="https://www.owasp.org/index.php/HTTP_Response_Splitting">HTTP Response Splitting</a>.
</li>
<li>
Wikipedia: <a href="http://en.wikipedia.org/wiki/HTTP_response_splitting">HTTP response splitting</a>.
</li>
<li>
CAPEC: <a href="https://capec.mitre.org/data/definitions/105.html">CAPEC-105: HTTP Request Splitting</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,17 @@
@app.route("/example_bad")
def example_bad():
rfs_header = request.args["rfs_header"]
response = Response()
custom_header = "X-MyHeader-" + rfs_header
# BAD: User input is used as part of the header name.
response.headers[custom_header] = "HeaderValue"
return response
@app.route("/example_good")
def example_bad():
rfs_header = request.args["rfs_header"]
response = Response()
custom_header = "X-MyHeader-" + rfs_header.replace("\n", "").replace("\r","").replace(":","")
# GOOD: Line break characters are removed from the input.
response.headers[custom_header] = "HeaderValue"
return response

View File

@@ -1,26 +0,0 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>If an HTTP Header is built using string concatenation or string formatting, and the
components of the concatenation include user input, a user
is likely to be able to manipulate the response.</p>
</overview>
<recommendation>
<p>User input should not be included in an HTTP Header.</p>
</recommendation>
<example>
<p>In the following example, the code appends a user-provided value into a header.</p>
<sample src="header_injection.py" />
</example>
<references>
<li>OWASP: <a href="https://owasp.org/www-community/attacks/HTTP_Response_Splitting">HTTP Response Splitting</a>.</li>
<li>Python Security: <a href="https://python-security.readthedocs.io/vuln/http-header-injection.html">HTTP header injection</a>.</li>
<li>SonarSource: <a href="https://rules.sonarsource.com/python/RSPEC-5167">RSPEC-5167</a>.</li>
</references>
</qhelp>

View File

@@ -1,9 +0,0 @@
from flask import Response, request, Flask, make_response
@app.route("/flask_Response")
def flask_Response():
rfs_header = request.args["rfs_header"]
response = Response()
response.headers['HeaderName'] = rfs_header
return response