SONARSEC-3113 Update code example layouts of S5131 (XSS) rule description

This commit is contained in:
Christophe Zurn 2022-07-04 14:52:28 +02:00 committed by Christophe Zürn
parent bb64555a09
commit 7c36d2a006
15 changed files with 97 additions and 59 deletions

View File

@ -6,7 +6,7 @@ The goal is to leave the data intact from the end user's point of view but makes
XSS exploitation techniques vary depending on the HTML context where malicious inputs are injected. For each HTML context, there is a specific encoding to prevent JavaScript code from being interpreted.
The following table summarizes the encoding to apply for each HTML context.
[cols="a,a,a,a"]
[options="header",cols="a,a,a,a"]
|===
| Context
| Code example

View File

@ -1,7 +1,8 @@
=== How to fix it in ASP.NET
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,csharp]
----
@ -18,6 +19,7 @@ public class HelloController : Controller
}
}
----
h| Compliant solution
|
[source,csharp]
----

View File

@ -5,7 +5,7 @@ The recommended way to fix this code is to move the HTML content to the template
[cols="a"]
|===
| ==== Noncompliant Code Example
h| Non-compliant code example
|
[source,csharp]
----
@ -20,12 +20,12 @@ public class HelloController : Controller
}
}
----
|
[source,html]
----
@Html.Raw(ViewData["Hello"])
----
| ==== Compliant Solution
h| Compliant solution
|
[source,csharp]
----
@ -40,7 +40,7 @@ public class HelloController : Controller
}
}
----
|
[source,html]
----
<h1>@ViewData["Name"]</h1>

View File

@ -4,8 +4,9 @@ The following code is vulnerable to cross-site scripting because JSP does not au
User input embedded in HTML code should be HTML-encoded to prevent the injection of additional code. This can be done with the https://owasp.org/www-project-java-encoder/[OWASP Java Encoder] or similar libraries.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,html]
----
@ -18,6 +19,7 @@ User input embedded in HTML code should be HTML-encoded to prevent the injection
</body>
</html>
----
h| Compliant solution
|
[source,html]
----

View File

@ -7,7 +7,7 @@ If embedded in HTML code, it should be HTML-encoded to prevent the injection of
[cols="a"]
|===
| ==== Noncompliant Code Example
h| Non-compliant code example
|
[source,java]
----
@ -19,7 +19,7 @@ public void endpoint(HttpServletRequest request, HttpServletResponse response) t
writer.print(data); // Noncompliant
}
----
| ==== Compliant Solution
h| Compliant solution
|
[source,java]
----
@ -41,7 +41,7 @@ For example, setting the content-type to `text/plain` with the `setContentType`
[cols="a"]
|===
| ==== Noncompliant Code Example
h| Non-compliant code example
|
[source,java]
----
@ -53,7 +53,7 @@ public void endpoint(HttpServletRequest request, HttpServletResponse response) t
writer.print(data); // Noncompliant
}
----
| ==== Compliant Solution
h| Compliant solution
|
[source,java]
----

View File

@ -5,8 +5,9 @@ The following code is vulnerable to cross-site scripting because it returns an H
If you do not intend to send HTML code to clients, the vulnerability can be fixed by specifying the type of data returned in the response.
For example, you can use the `produces` property of the `GetMapping` annotation.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,java]
----
@ -20,6 +21,7 @@ public class ApiController
}
}
----
h| Compliant solution
|
[source,java]
----

View File

@ -4,21 +4,27 @@ The following code is vulnerable to cross-site scripting.
User input embedded in HTML code should be HTML-encoded to prevent the injection of additional code.
[cols="a"]
|===
h| Non-compliant code example
|
[source,html]
----
<body>
<p th:utext="|Hello, ${input}!|" /> <!-- Noncompliant -->
<p>Hello, [(${input})]!</p> <!-- Noncompliant -->
<p th:utext="Hello, ${input}!" /> <!-- Noncompliant -->
<p>Hello, [(${input})]!</p> <!-- Noncompliant -->
</body>
----
h| Compliant solution
|
[source,html]
----
<body>
<p th:text="|Hello, ${input}!|" />
<p th:text="Hello, ${input}!" />
<p>Hello, [[${input}]]!</p>
</body>
----
|===
=== How does this work?

View File

@ -7,7 +7,7 @@ For example, you can use the `JsonResponse` class to safely return JSON messages
[cols="a"]
|===
| ==== Noncompliant Code Example
h| Non-compliant code example
|
[source,javascript]
----
@ -16,7 +16,7 @@ function (req, res) {
res.send(tainted); // Noncompliant
};
----
| ==== Compliant Solution
h| Compliant solution
|
[source,javascript]
----
@ -30,7 +30,7 @@ It is also possible to set the content-type header manually using the `content_t
[cols="a"]
|===
| ==== Noncompliant Code Example
h| Non-compliant code example
|
[source,javascript]
----
@ -38,7 +38,7 @@ function (req, res) {
res.send(req.query.input); // Noncompliant
};
----
| ==== Compliant Solution
h| Compliant solution
|
[source,javascript]
----

View File

@ -5,13 +5,15 @@ The following code is vulnerable to cross-site scripting because it returns an H
User input embedded in HTML code should be HTML-encoded to prevent the injection of additional code.
PHP provides the built-in function `htmlspecialchars` to do this.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,php]
----
echo '<h1>' . $input . '</h1>'; // Noncompliant
----
h| Compliant solution
|
[source,php]
----
@ -24,13 +26,15 @@ If you do not intend to send HTML code to clients, the vulnerability can be fixe
For example, setting the content-type to `text/plain` using the built-in `header` function allows to safely reflect user input since browsers will not try to parse and execute the response.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,php]
----
echo $input; // Noncompliant
----
h| Compliant solution
|
[source,php]
----
@ -53,13 +57,15 @@ By default, `htmlspecialchars` does not encode single quotes, so if `++$input++`
Make sure to set the option `ENT_QUOTES` to encode single quotes.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,php]
----
echo "<img src='" . htmlspecialchars($input) . "'>";
----
h| Compliant solution
|
[source,php]
----
@ -73,8 +79,9 @@ If the HTTP body is sent before `header` is called, no headers will be sent to t
To fix this issue, send the headers before any output.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,php]
----
@ -82,6 +89,7 @@ echo 'No more headers at this point';
header('Content-Type: text/plain');
echo $input;
----
h| Compliant solution
|
[source,php]
----

View File

@ -7,13 +7,13 @@ For example, you can use the `json` method of the `Response` class to safely ret
[cols="a"]
|===
| ==== Noncompliant Code Example
h| Non-compliant code example
|
[source,php]
----
$response = response(json_encode(['data' => $input]), 200); // Noncompliant
----
| ==== Compliant Solution
h| Compliant solution
|
[source,php]
----
@ -25,13 +25,13 @@ It is also possible to set the content-type header manually using the `header` m
[cols="a"]
|===
| ==== Noncompliant Code Example
h| Non-compliant code example
|
[source,php]
----
$response = response($input, 200); // Noncompliant
----
| ==== Compliant Solution
h| Compliant solution
|
[source,php]
----

View File

@ -5,8 +5,9 @@ The following code is vulnerable to cross-site scripting because it returns an H
If you do not intend to send HTML code to clients, the vulnerability can be fixed by specifying the type of data returned in the response.
For example, you can use the class `JsonResponse` to return JSON messages safely.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,php]
----
@ -15,6 +16,7 @@ use Symfony\Component\HttpFoundation\Response;
$response = new Response();
$response->setContent(json_encode(['data' => $input])); // Noncompliant
----
h| Compliant solution
|
[source,php]
----
@ -26,8 +28,9 @@ $response = new JsonResponse(['data' => $input]);
It is also possible to set the content-type manually using the `headers` attribute.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,php]
----
@ -36,6 +39,7 @@ use Symfony\Component\HttpFoundation\Response;
$response = new Response();
$response->setContent($input); // Noncompliant
----
h| Compliant solution
|
[source,php]
----

View File

@ -7,7 +7,7 @@ For example, you can use the `JsonResponse` class to return JSON messages secure
[cols="a"]
|===
| ==== Noncompliant Code Example
h| Non-compliant code example
|
[source,python]
----
@ -18,7 +18,7 @@ def index(request):
json = json.dumps({ "data": request.GET.get("input") })
return HttpResponse(json) # Noncompliant
----
| ==== Compliant Solution
h| Compliant solution
|
[source,python]
----
@ -34,7 +34,7 @@ It is also possible to set the content-type manually with the `content_type` par
[cols="a"]
|===
| ==== Noncompliant Code Example
h| Non-compliant code example
|
[source,python]
----
@ -43,7 +43,7 @@ from django.http import HttpResponse
def index(request):
return HttpResponse(request.GET.get("input")) # Noncompliant
----
| ==== Compliant Solution
h| Compliant solution
|
[source,python]
----

View File

@ -2,8 +2,9 @@
The following code is vulnerable to cross-site scripting because auto-escaping of special HTML characters has been disabled. The recommended way to fix this code is to move the HTML content to the template and to only inject the dynamic value. Therefore, it is not necessary to disable auto-escaping.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,python]
----
@ -14,6 +15,15 @@ def hello(request):
hello = f"<h1>Hello { name }</h1>"
return render(request, 'hello.html', {'hello': hello})
----
[source,html]
----
<!doctype html>
{% autoescape false %}
{{ hello }} <!-- Noncompliant -->
{% endautoescape %}
----
h| Compliant solution
|
[source,python]
----
@ -23,15 +33,7 @@ def hello(request):
name = request.GET.get("name")
return render(request, 'hello.html', {'name': name})
----
|
[source,html]
----
<!doctype html>
{% autoescape false %}
{{ hello }} <!-- Noncompliant -->
{% endautoescape %}
----
|
[source,html]
----
<!doctype html>
@ -51,8 +53,9 @@ Django template auto-escaping only takes care of HTML entity encoding. It does n
Auto-escaping can also be disabled at the application level and introduce XSS vulnerabilities even if `++{% autoescape false %}++` or `++|safe++` are not used.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,python]
----
@ -67,6 +70,7 @@ TEMPLATES = [
},
]
----
h| Compliant solution
|
[source,python]
----
@ -93,14 +97,16 @@ In such a case it is better to add the value to an attribute.
Another option is to use the `++json_script++` filter to insert a data structure that can then be accessed through the JavaScript code.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,html]
----
<!doctype html>
<script> var name = '{{ name }}';</script>
----
h| Compliant solution
|
[source,html]
----

View File

@ -5,8 +5,9 @@ The following code is vulnerable to cross-site scripting because it returns an H
If you do not intend to send HTML code to clients, the vulnerability can be fixed by specifying the type of data returned in the response.
For example, you can use the `jsonify` class to return JSON messages safely.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,python]
----
@ -18,6 +19,7 @@ def index():
json = json.dumps({ "data": request.args.get("input") }) # Noncompliant
return make_response(json)
----
h| Compliant solution
|
[source,python]
----
@ -31,8 +33,9 @@ def index():
It is also possible to set the content-type manually with the `mimetype` parameter when calling the `make_response` function.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,python]
----
@ -42,6 +45,7 @@ from flask import make_response, request
def index():
return make_response(request.args.get("input")) # Noncompliant
----
h| Compliant solution
|
[source,python]
----

View File

@ -3,8 +3,9 @@
The following code is vulnerable to cross-site scripting because auto-escaping of special HTML characters has been disabled.
The recommended way to fix this code is to move the HTML content to the template and to only inject the dynamic value. Therefore, it is not necessary to disable auto-escaping.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,python]
----
@ -15,6 +16,15 @@ def hello(name=None):
hello = f"<h1>Hello { name }</h1>"
return render_template('hello.html', hello=hello)
----
[source,html]
----
<!doctype html>
{% autoescape false %}
{{ hello }} <!-- Noncompliant -->
{% endautoescape %}
----
h| Compliant solution
|
[source,python]
----
@ -24,15 +34,7 @@ from flask import render_template
def hello(name=None):
return render_template('hello.html', name=name)
----
|
[source,html]
----
<!doctype html>
{% autoescape false %}
{{ hello }} <!-- Noncompliant -->
{% endautoescape %}
----
|
[source,html]
----
<!doctype html>
@ -56,8 +58,9 @@ Although auto-escaping drastically decreases the chance of introducing cross-sit
Injecting user-controlled values inside a ``++script++`` is dangerous. In such a case, the best practice is to add the value to an attribute.
Another option is to use the ``++tojson++`` filter to insert a data structure in the JavaScript code at render time.
[cols="a,a"]
[cols="a"]
|===
h| Non-compliant code example
|
[source,html]
----
@ -65,6 +68,7 @@ Another option is to use the ``++tojson++`` filter to insert a data structure in
<script> var name = '{{ name }}';</script>
----
h| Compliant solution
|
[source,html]
----