-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SONARHTML-183 Rule S5247: Disabling auto-escaping in template engines…
… is security-sensitive (#257)
- Loading branch information
1 parent
aee1b2c
commit 825531d
Showing
9 changed files
with
249 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,24 @@ | ||
{ | ||
"project:external_webkit-jb-mr1/Tools/QueueStatusServer/templates/dashboard.html": [ | ||
28, | ||
31 | ||
], | ||
"project:external_webkit-jb-mr1/Tools/QueueStatusServer/templates/includes/singlequeuestatus.html": [ | ||
6, | ||
8 | ||
], | ||
"project:external_webkit-jb-mr1/Tools/QueueStatusServer/templates/patch.html": [ | ||
9, | ||
9, | ||
15, | ||
16 | ||
], | ||
"project:external_webkit-jb-mr1/Tools/QueueStatusServer/templates/queuestatus.html": [ | ||
35, | ||
36, | ||
66 | ||
], | ||
"project:external_webkit-jb-mr1/Tools/QueueStatusServer/templates/recentstatus.html": [ | ||
46 | ||
] | ||
} |
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
61 changes: 61 additions & 0 deletions
61
...-plugin/src/main/java/org/sonar/plugins/html/checks/security/DisabledAutoescapeCheck.java
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,61 @@ | ||
/* | ||
* SonarSource HTML analyzer :: Sonar Plugin | ||
* Copyright (c) 2010-2023 SonarSource SA and Matthijs Galesloot | ||
* [email protected] | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.sonar.plugins.html.checks.security; | ||
|
||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
import org.sonar.check.Rule; | ||
import org.sonar.plugins.html.checks.AbstractPageCheck; | ||
import org.sonar.plugins.html.node.TextNode; | ||
|
||
/* | ||
Note: While this rule covers Jinja2/Django templates, the HTML analyzer is not meant to explicitly support these templating engine and will only cover basic cases. | ||
Any more elaborate support of these engines should be done in a dedicated sensor with a dedicated parser. | ||
*/ | ||
@Rule(key = "S5247") | ||
public class DisabledAutoescapeCheck extends AbstractPageCheck { | ||
|
||
private static final String MESSAGE = "Make sure disabling auto-escaping feature is safe here."; | ||
private static final Pattern pattern = Pattern.compile("\\{%\\s*autoescape\\s+(false|off)\\s*%\\}|\\|safe\\s*\\}\\}"); | ||
|
||
@Override | ||
public void characters(TextNode textNode) { | ||
Matcher matcher = pattern.matcher(textNode.getCode()); | ||
if (!matcher.find()) { | ||
return; | ||
} | ||
var lines = textNode.getCode().lines() | ||
.collect(Collectors.toList()); | ||
boolean raisedWithPreciseLocation = false; | ||
for (int i=0; i<lines.size(); i++) { | ||
Matcher lineMatcher = pattern.matcher(lines.get(i)); | ||
while (lineMatcher.find()) { | ||
int issueLine = i + textNode.getStartLinePosition(); | ||
int startColumn = i != 0 ? lineMatcher.start() : (textNode.getStartColumnPosition() + lineMatcher.start()); | ||
int endColumn = i != 0 ? lineMatcher.end() : (textNode.getStartColumnPosition() + lineMatcher.end()); | ||
createViolation(issueLine, startColumn, issueLine, endColumn, MESSAGE); | ||
raisedWithPreciseLocation = true; | ||
} | ||
} | ||
if (!raisedWithPreciseLocation) { | ||
// If no precise location can be found for the issue (the node only contains violations spanning multiple lines), the issue is raised on the whole text node | ||
createViolation(textNode, MESSAGE); | ||
} | ||
} | ||
} |
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
45 changes: 45 additions & 0 deletions
45
sonar-html-plugin/src/main/resources/org/sonar/l10n/web/rules/Web/S5247.html
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,45 @@ | ||
<p>To reduce the risk of cross-site scripting attacks, templating systems, such as <code>Twig</code>, <code>Django</code>, <code>Smarty</code>, | ||
<code>Groovy's template engine</code>, allow configuration of automatic variable escaping before rendering templates. When escape occurs, characters | ||
that make sense to the browser (eg: <a>) will be transformed/replaced with escaped/sanitized values (eg: & lt;a& gt; ).</p> | ||
<p>Auto-escaping is not a magic feature to annihilate all cross-site scripting attacks, it depends on <a | ||
href="https://twig.symfony.com/doc/3.x/filters/escape.html">the strategy applied</a> and the context, for example a "html auto-escaping" strategy | ||
(which only transforms html characters into <a href="https://developer.mozilla.org/en-US/docs/Glossary/Entity">html entities</a>) will not be relevant | ||
when variables are used in a <a href="https://en.wikipedia.org/wiki/HTML_attribute">html attribute</a> because '<code>:</code>' character is not | ||
escaped and thus an attack as below is possible:</p> | ||
<pre> | ||
<a href="{{ myLink }}">link</a> // myLink = javascript:alert(document.cookie) | ||
<a href="javascript:alert(document.cookie)">link</a> // JS injection (XSS attack) | ||
</pre> | ||
<h2>Ask Yourself Whether</h2> | ||
<ul> | ||
<li> Templates are used to render web content and | ||
<ul> | ||
<li> dynamic variables in templates come from untrusted locations or are user-controlled inputs </li> | ||
<li> there is no local mechanism in place to sanitize or validate the inputs. </li> | ||
</ul> </li> | ||
</ul> | ||
<p>There is a risk if you answered yes to any of those questions.</p> | ||
<h2>Recommended Secure Coding Practices</h2> | ||
<p>Enable auto-escaping by default and continue to review the use of inputs in order to be sure that the chosen auto-escaping strategy is the right | ||
one.</p> | ||
<h2>Sensitive Code Example</h2> | ||
<pre> | ||
<!-- Django templates --> | ||
<p>{{ variable|safe }}</p><!-- Sensitive --> | ||
{% autoescape off %}<!-- Sensitive --> | ||
|
||
<!-- Jinja2 templates --> | ||
<p>{{ variable|safe }}</p><!-- Sensitive --> | ||
{% autoescape false %}<!-- Sensitive --> | ||
</pre> | ||
<h2>See</h2> | ||
<ul> | ||
<li> <a href="https://owasp.org/Top10/A03_2021-Injection/">OWASP Top 10 2021 Category A3</a> - Injection </li> | ||
<li> <a href="https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md">OWASP Cheat | ||
Sheet</a> - XSS Prevention Cheat Sheet </li> | ||
<li> <a href="https://owasp.org/www-project-top-ten/2017/A7_2017-Cross-Site_Scripting_(XSS)">OWASP Top 10 2017 Category A7</a> - Cross-Site | ||
Scripting (XSS) </li> | ||
<li> <a href="https://cwe.mitre.org/data/definitions/79">MITRE, CWE-79</a> - Improper Neutralization of Input During Web Page Generation | ||
('Cross-site Scripting') </li> | ||
</ul> | ||
|
42 changes: 42 additions & 0 deletions
42
sonar-html-plugin/src/main/resources/org/sonar/l10n/web/rules/Web/S5247.json
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,42 @@ | ||
{ | ||
"title": "Disabling auto-escaping in template engines is security-sensitive", | ||
"type": "SECURITY_HOTSPOT", | ||
"code": { | ||
"impacts": { | ||
"SECURITY": "MEDIUM" | ||
}, | ||
"attribute": "COMPLETE" | ||
}, | ||
"status": "ready", | ||
"remediation": { | ||
"func": "Constant\/Issue", | ||
"constantCost": "5min" | ||
}, | ||
"tags": [ | ||
"cwe" | ||
], | ||
"defaultSeverity": "Major", | ||
"ruleSpecification": "RSPEC-5247", | ||
"sqKey": "S5247", | ||
"scope": "Main", | ||
"securityStandards": { | ||
"CWE": [ | ||
79 | ||
], | ||
"OWASP": [ | ||
"A7" | ||
], | ||
"OWASP Top 10 2021": [ | ||
"A3" | ||
], | ||
"PCI DSS 3.2": [ | ||
"6.5.7" | ||
], | ||
"PCI DSS 4.0": [ | ||
"6.2.4" | ||
], | ||
"ASVS 4.0": [ | ||
"5.3.3" | ||
] | ||
} | ||
} |
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 |
---|---|---|
|
@@ -17,6 +17,7 @@ | |
"S4084", | ||
"S4645", | ||
"S5148", | ||
"S5247", | ||
"S5254", | ||
"S5255", | ||
"S5256", | ||
|
46 changes: 46 additions & 0 deletions
46
...gin/src/test/java/org/sonar/plugins/html/checks/security/DisabledAutoescapeCheckTest.java
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,46 @@ | ||
/* | ||
* SonarSource HTML analyzer :: Sonar Plugin | ||
* Copyright (c) 2010-2023 SonarSource SA and Matthijs Galesloot | ||
* [email protected] | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.sonar.plugins.html.checks.security; | ||
|
||
import java.io.File; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.extension.RegisterExtension; | ||
import org.sonar.plugins.html.checks.CheckMessagesVerifierRule; | ||
import org.sonar.plugins.html.checks.TestHelper; | ||
import org.sonar.plugins.html.visitor.HtmlSourceCode; | ||
|
||
class DisabledAutoescapeCheckTest { | ||
@RegisterExtension | ||
public CheckMessagesVerifierRule checkMessagesVerifier = new CheckMessagesVerifierRule(); | ||
|
||
@Test | ||
void test_jinja() { | ||
HtmlSourceCode sourceCode = TestHelper.scan(new File("src/test/resources/checks/jinjaAutoescape.html"), new DisabledAutoescapeCheck()); | ||
|
||
checkMessagesVerifier.verify(sourceCode.getIssues()) | ||
.next().atLocation(6, 35, 6, 57).withMessage("Make sure disabling auto-escaping feature is safe here.") | ||
.next().atLocation(7, 35, 7, 55).withMessage("Make sure disabling auto-escaping feature is safe here.") | ||
.next().atLocation(8, 35, 8, 55).withMessage("Make sure disabling auto-escaping feature is safe here.") | ||
.next().atLocation(9, 34, 11, 40).withMessage("Make sure disabling auto-escaping feature is safe here.") | ||
.next().atLocation(12, 42, 12, 49).withMessage("Make sure disabling auto-escaping feature is safe here.") | ||
.next().atLocation(13, 43, 13, 51).withMessage("Make sure disabling auto-escaping feature is safe here.") | ||
.next().atLocation(16, 12, 16, 32).withMessage("Make sure disabling auto-escaping feature is safe here.") | ||
.next().atLocation(19, 12, 19, 32).withMessage("Make sure disabling auto-escaping feature is safe here.") | ||
.next().atLocation(19, 60, 19, 80).withMessage("Make sure disabling auto-escaping feature is safe here."); | ||
} | ||
} |
24 changes: 24 additions & 0 deletions
24
sonar-html-plugin/src/test/resources/checks/jinjaAutoescape.html
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,24 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<body> | ||
<main class="container"> | ||
<center> | ||
<p style="font-size:2em;"> {% autoescape false %}{{xss}}{% endautoescape %} </p> | ||
<p style="font-size:2em;"> {% autoescape off %}{{xss2}}{% endautoescape %} </p> | ||
<p style="font-size:2em;"> {%autoescape false%}{{xss3}}{% endautoescape %} </p> | ||
<p style="font-size:2em;"> {%autoescape | ||
false%} | ||
{{xss4}}{% endautoescape %} </p> | ||
<p style="font-size:2em;"> {{hello|safe}}</p> | ||
<p style="font-size:2em;"> {{hello2|safe }}</p> | ||
<p style="font-size:2em;"> {{thisissafe}}</p> | ||
<p style="font-size:2em;"> bla | ||
{%autoescape false%}{{xss4}}{% endautoescape %} | ||
bla </p> | ||
<p style="font-size:2em;"> bla | ||
{%autoescape false%}{{xss5}}{% endautoescape %} {%autoescape false%}{{xss6}}{% endautoescape %} | ||
bla </p> | ||
</center> | ||
</main> | ||
</body> | ||
</html> |