Modify All Current Education Rules: Support intuitive view (#1256)
This commit is contained in:
parent
16919a7fc1
commit
8815e23ae8
@ -2,25 +2,24 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
public void Run(string binary)
|
public void Run(string binary)
|
||||||
{
|
{
|
||||||
Process p = new Process();
|
Process p = new Process();
|
||||||
p.StartInfo.FileName = binary; // Noncompliant
|
p.StartInfo.FileName = binary;
|
||||||
p.Start();
|
p.Start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -36,7 +35,6 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -14,15 +12,16 @@ public class ExampleController
|
|||||||
@GetMapping(value = "/exec")
|
@GetMapping(value = "/exec")
|
||||||
public void exec(@RequestParam("command") String command) throws IOException {
|
public void exec(@RequestParam("command") String command) throws IOException {
|
||||||
|
|
||||||
CommandLine cmd = new CommandLine(command); // Noncompliant
|
CommandLine cmd = new CommandLine(command);
|
||||||
DefaultExecutor executor = new DefaultExecutor();
|
DefaultExecutor executor = new DefaultExecutor();
|
||||||
executor.execute(cmd);
|
executor.execute(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -42,7 +41,6 @@ public class ExampleController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -14,13 +12,14 @@ public class ExampleController
|
|||||||
@GetMapping(value = "/exec")
|
@GetMapping(value = "/exec")
|
||||||
public void exec(@RequestParam("command") String command) throws IOException {
|
public void exec(@RequestParam("command") String command) throws IOException {
|
||||||
|
|
||||||
Runtime.getRuntime().exec(command); // Noncompliant
|
Runtime.getRuntime().exec(command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -36,7 +35,6 @@ public class ExampleController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
++java.lang.Runtime++ is sometimes used over ++java.lang.ProcessBuilder++ due to ease of use. Flexibility in methods often introduces security issues as edge cases are easily missed. The compliant solution logic is also applied to ++java.lang.ProcessBuilder++.
|
++java.lang.Runtime++ is sometimes used over ++java.lang.ProcessBuilder++ due to ease of use. Flexibility in methods often introduces security issues as edge cases are easily missed. The compliant solution logic is also applied to ++java.lang.ProcessBuilder++.
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
The following non-compliant code is vulnerable to LDAP injections because untrusted data is
|
The following non-compliant code is vulnerable to LDAP injections because untrusted data is
|
||||||
concatenated in an LDAP query without prior validation.
|
concatenated in an LDAP query without prior validation.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -16,15 +14,16 @@ public class ExampleController : Controller
|
|||||||
DirectoryEntry directory = new DirectoryEntry("LDAP://ou=system");
|
DirectoryEntry directory = new DirectoryEntry("LDAP://ou=system");
|
||||||
DirectorySearcher search = new DirectorySearcher(directory);
|
DirectorySearcher search = new DirectorySearcher(directory);
|
||||||
|
|
||||||
search.Filter = "(&(uid=" + user + ")(userPassword=" + pass + "))"; // Noncompliant
|
search.Filter = "(&(uid=" + user + ")(userPassword=" + pass + "))";
|
||||||
|
|
||||||
return Json(search.FindOne() != null);
|
return Json(search.FindOne() != null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -45,7 +44,6 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
The following non-compliant code is vulnerable to LDAP injections because untrusted data is
|
The following non-compliant code is vulnerable to LDAP injections because untrusted data is
|
||||||
concatenated to an LDAP query without prior sanitization or validation.
|
concatenated to an LDAP query without prior sanitization or validation.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
public boolean authenticate(HttpServletRequest req, DirContext ctx) throws NamingException {
|
public boolean authenticate(HttpServletRequest req, DirContext ctx) throws NamingException {
|
||||||
|
|
||||||
@ -16,13 +14,14 @@ public boolean authenticate(HttpServletRequest req, DirContext ctx) throws Namin
|
|||||||
|
|
||||||
String filter = "(&(uid=" + user + ")(userPassword=" + pass + "))";
|
String filter = "(&(uid=" + user + ")(userPassword=" + pass + "))";
|
||||||
|
|
||||||
NamingEnumeration<SearchResult> results = ctx.search("ou=system", filter, new SearchControls()); // Noncompliant
|
NamingEnumeration<SearchResult> results = ctx.search("ou=system", filter, new SearchControls());
|
||||||
return results.hasMore();
|
return results.hasMore();
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public boolean authenticate(HttpServletRequest req, DirContext ctx) throws NamingException {
|
public boolean authenticate(HttpServletRequest req, DirContext ctx) throws NamingException {
|
||||||
String user = req.getParameter("user");
|
String user = req.getParameter("user");
|
||||||
@ -34,7 +33,6 @@ public boolean authenticate(HttpServletRequest req, DirContext ctx) throws Namin
|
|||||||
return results.hasMore();
|
return results.hasMore();
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
@ -46,5 +44,4 @@ and
|
|||||||
https://www.javadoc.io/doc/org.owasp.esapi/esapi/latest/org/owasp/esapi/Encoder.html#encodeForLDAP-java.lang.String-[`encodeForLDAP`]
|
https://www.javadoc.io/doc/org.owasp.esapi/esapi/latest/org/owasp/esapi/Encoder.html#encodeForLDAP-java.lang.String-[`encodeForLDAP`]
|
||||||
allow sanitizing these characters automatically.
|
allow sanitizing these characters automatically.
|
||||||
|
|
||||||
|
|
||||||
In the compliant solution example, the `search` function allows to safely parameterize the query.
|
In the compliant solution example, the `search` function allows to safely parameterize the query.
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
:canonicalization_function: System.IO.Path.GetFullPath
|
:canonicalization_function: System.IO.Path.GetFullPath
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -16,13 +14,14 @@ public class ExampleController : Controller
|
|||||||
public void Example(string filename)
|
public void Example(string filename)
|
||||||
{
|
{
|
||||||
string path = Path.Combine(TargetDirectory, filename);
|
string path = Path.Combine(TargetDirectory, filename);
|
||||||
System.IO.File.Delete(path); // Noncompliant
|
System.IO.File.Delete(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -40,7 +39,6 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
:canonicalization_function: java.io.File.getCanonicalPath
|
:canonicalization_function: java.io.File.getCanonicalPath
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -18,13 +16,14 @@ public class ExampleController
|
|||||||
public void delete(@RequestParam("filename") String filename) throws IOException {
|
public void delete(@RequestParam("filename") String filename) throws IOException {
|
||||||
|
|
||||||
File file = new File(targetDirectory + filename);
|
File file = new File(targetDirectory + filename);
|
||||||
file.delete(); // Noncompliant
|
file.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -45,7 +44,6 @@ public class ExampleController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
The following code is vulnerable to XPath injections because untrusted data is
|
The following code is vulnerable to XPath injections because untrusted data is
|
||||||
concatenated in an XPath query without prior validation.
|
concatenated in an XPath query without prior validation.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -17,14 +15,15 @@ public class ExampleController : Controller
|
|||||||
|
|
||||||
String expression = "/users/user[@name='" + user + "' and @pass='" + pass + "']";
|
String expression = "/users/user[@name='" + user + "' and @pass='" + pass + "']";
|
||||||
|
|
||||||
return Json(doc.SelectSingleNode(expression) != null); // Noncompliant
|
return Json(doc.SelectSingleNode(expression) != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -43,7 +42,6 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
The following non-compliant code is vulnerable to XPath injections because untrusted data is
|
The following non-compliant code is vulnerable to XPath injections because untrusted data is
|
||||||
concatenated to an XPath query without prior validation.
|
concatenated to an XPath query without prior validation.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
public boolean authenticate(HttpServletRequest req, XPath xpath, Document doc) throws XPathExpressionException {
|
public boolean authenticate(HttpServletRequest req, XPath xpath, Document doc) throws XPathExpressionException {
|
||||||
String user = request.getParameter("user");
|
String user = request.getParameter("user");
|
||||||
@ -15,12 +13,13 @@ public boolean authenticate(HttpServletRequest req, XPath xpath, Document doc) t
|
|||||||
|
|
||||||
String expression = "/users/user[@name='" + user + "' and @pass='" + pass + "']";
|
String expression = "/users/user[@name='" + user + "' and @pass='" + pass + "']";
|
||||||
|
|
||||||
return (boolean)xpath.evaluate(expression, doc, XPathConstants.BOOLEAN); // Noncompliant
|
return (boolean)xpath.evaluate(expression, doc, XPathConstants.BOOLEAN);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public boolean authenticate(HttpServletRequest req, XPath xpath, Document doc) throws XPathExpressionException {
|
public boolean authenticate(HttpServletRequest req, XPath xpath, Document doc) throws XPathExpressionException {
|
||||||
String user = request.getParameter("user");
|
String user = request.getParameter("user");
|
||||||
@ -43,7 +42,6 @@ public boolean authenticate(HttpServletRequest req, XPath xpath, Document doc) t
|
|||||||
}
|
}
|
||||||
|
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -4,25 +4,24 @@ The following non-compliant code is vulnerable to Regex Denial of Service
|
|||||||
because untrusted data is used as a regex to scan a string without prior
|
because untrusted data is used as a regex to scan a string without prior
|
||||||
sanitization or validation.
|
sanitization or validation.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
public IActionResult Validate(string regex, string input)
|
public IActionResult Validate(string regex, string input)
|
||||||
{
|
{
|
||||||
bool match = Regex.IsMatch(input, regex); // Noncompliant
|
bool match = Regex.IsMatch(input, regex);
|
||||||
|
|
||||||
return Json(match);
|
return Json(match);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -34,7 +33,6 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -4,22 +4,21 @@ The following non-compliant code is vulnerable to Regex Denial of Service
|
|||||||
because untrusted data is used as a regex to scan a string without prior
|
because untrusted data is used as a regex to scan a string without prior
|
||||||
sanitization or validation.
|
sanitization or validation.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
public boolean validate(HttpServletRequest request) {
|
public boolean validate(HttpServletRequest request) {
|
||||||
String regex = request.getParameter("regex");
|
String regex = request.getParameter("regex");
|
||||||
String input = request.getParameter("input");
|
String input = request.getParameter("input");
|
||||||
|
|
||||||
return input.matches(regex); // Noncompliant
|
return input.matches(regex);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public boolean validate(HttpServletRequest request) {
|
public boolean validate(HttpServletRequest request) {
|
||||||
String regex = request.getParameter("regex");
|
String regex = request.getParameter("regex");
|
||||||
@ -28,7 +27,6 @@ public boolean validate(HttpServletRequest request) {
|
|||||||
return input.matches(Pattern.quote(regex));
|
return input.matches(Pattern.quote(regex));
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -18,7 +16,7 @@ public class ExampleController : Controller
|
|||||||
{
|
{
|
||||||
var query = "SELECT * FROM users WHERE user = '" + use + "' AND pass = '" + pass + "'";
|
var query = "SELECT * FROM users WHERE user = '" + use + "' AND pass = '" + pass + "'";
|
||||||
|
|
||||||
var result = connection.QueryFirst<User>(query); // Noncompliant
|
var result = connection.QueryFirst<User>(query);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
Unauthorized();
|
Unauthorized();
|
||||||
}
|
}
|
||||||
@ -27,9 +25,10 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -51,7 +50,6 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -18,7 +16,7 @@ public class ExampleController : Controller
|
|||||||
|
|
||||||
var queryResults = Context
|
var queryResults = Context
|
||||||
.Database
|
.Database
|
||||||
.ExecuteSqlCommand(query); // Noncompliant
|
.ExecuteSqlCommand(query);
|
||||||
|
|
||||||
if (queryResults == 0)
|
if (queryResults == 0)
|
||||||
{
|
{
|
||||||
@ -29,9 +27,10 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -54,7 +53,6 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
@RestController
|
@RestController
|
||||||
public class ApiController
|
public class ApiController
|
||||||
@ -24,7 +22,7 @@ public class ApiController
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
queryProducer
|
queryProducer
|
||||||
.createNativeQuery(query) // Noncompliant
|
.createNativeQuery(query)
|
||||||
.getSingleResult();
|
.getSingleResult();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -35,9 +33,10 @@ public class ApiController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
@RestController
|
@RestController
|
||||||
public class ApiController
|
public class ApiController
|
||||||
@ -68,7 +67,6 @@ public class ApiController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
@RestController
|
@RestController
|
||||||
public class ApiController
|
public class ApiController
|
||||||
@ -24,7 +22,7 @@ public class ApiController
|
|||||||
|
|
||||||
try (Statement statement = connection.createStatement()) {
|
try (Statement statement = connection.createStatement()) {
|
||||||
|
|
||||||
ResultSet resultSet = statement.executeQuery(query); // Noncompliant
|
ResultSet resultSet = statement.executeQuery(query);
|
||||||
|
|
||||||
if (!resultSet.next()) {
|
if (!resultSet.next()) {
|
||||||
return new ResponseEntity<>("Unauthorized", HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>("Unauthorized", HttpStatus.UNAUTHORIZED);
|
||||||
@ -35,9 +33,10 @@ public class ApiController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
@RestController
|
@RestController
|
||||||
public class ApiController
|
public class ApiController
|
||||||
@ -68,7 +67,6 @@ public class ApiController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
@RestController
|
@RestController
|
||||||
public class ApiController
|
public class ApiController
|
||||||
@ -24,7 +22,7 @@ public class ApiController
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
BeanPropertyRowMapper<User> userType = new BeanPropertyRowMapper(User.class);
|
BeanPropertyRowMapper<User> userType = new BeanPropertyRowMapper(User.class);
|
||||||
User queryResult = jdbcTemplate.queryForObject(query, userType); // Noncompliant
|
User queryResult = jdbcTemplate.queryForObject(query, userType);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return new ResponseEntity<>("Unauthorized", HttpStatus.UNAUTHORIZED);
|
return new ResponseEntity<>("Unauthorized", HttpStatus.UNAUTHORIZED);
|
||||||
@ -34,9 +32,10 @@ public class ApiController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
@RestController
|
@RestController
|
||||||
public class ApiController
|
public class ApiController
|
||||||
@ -64,7 +63,6 @@ public class ApiController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
=== How to fix it in ASP.NET
|
=== How to fix it in ASP.NET
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -19,9 +17,10 @@ public class HelloController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -37,15 +36,12 @@ public class HelloController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
If the HTTP response is HTML code, it is highly recommended to use https://docs.microsoft.com/en-us/aspnet/web-pages/overview/getting-started/introducing-razor-syntax-c[Razor-based view templates] to generate it.
|
If the HTTP response is HTML code, it is highly recommended to use https://docs.microsoft.com/en-us/aspnet/web-pages/overview/getting-started/introducing-razor-syntax-c[Razor-based view templates] to generate it.
|
||||||
This template engine separates the view from the business logic and automatically encodes the output of variables, drastically reducing the risk of cross-site scripting vulnerabilities.
|
This template engine separates the view from the business logic and automatically encodes the output of variables, drastically reducing the risk of cross-site scripting vulnerabilities.
|
||||||
|
|
||||||
|
|
||||||
include::../../common/fix/data_encoding.adoc[]
|
include::../../common/fix/data_encoding.adoc[]
|
||||||
|
|
||||||
`System.Web.HttpUtility.HtmlEncode` is the recommended method to encode HTML entities.
|
`System.Web.HttpUtility.HtmlEncode` is the recommended method to encode HTML entities.
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
The following code is vulnerable to cross-site scripting because auto-escaping of special HTML characters has been disabled.
|
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.
|
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"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
@ -21,13 +19,14 @@ public class HelloController : Controller
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
[source,html]
|
[source,html,diff-id=2,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
@Html.Raw(ViewData["Hello"])
|
@Html.Raw(ViewData["Hello"])
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|
||||||
@ -41,11 +40,10 @@ public class HelloController : Controller
|
|||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
[source,html]
|
[source,html,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
<h1>@ViewData["Name"]</h1>
|
<h1>@ViewData["Name"]</h1>
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -4,11 +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.
|
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"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,html,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,html]
|
|
||||||
----
|
----
|
||||||
<%@page contentType="text/html" pageEncoding="UTF-8"%>
|
<%@page contentType="text/html" pageEncoding="UTF-8"%>
|
||||||
<%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
|
<%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
|
||||||
@ -19,9 +17,10 @@ h| Non-compliant code example
|
|||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,html]
|
|
||||||
|
[source,html,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
<%@page contentType="text/html" pageEncoding="UTF-8"%>
|
<%@page contentType="text/html" pageEncoding="UTF-8"%>
|
||||||
<%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
|
<%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
|
||||||
@ -32,7 +31,6 @@ h| Compliant solution
|
|||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -5,23 +5,22 @@ The following code is vulnerable to cross-site scripting because it returns an H
|
|||||||
Third-party data, such as user input, is not to be trusted.
|
Third-party data, such as user input, is not to be trusted.
|
||||||
If embedded in HTML code, it 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.
|
If embedded in HTML code, it 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"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
public void endpoint(HttpServletRequest request, HttpServletResponse response) throws IOException
|
public void endpoint(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||||
{
|
{
|
||||||
String data = request.getParameter("input");
|
String data = request.getParameter("input");
|
||||||
PrintWriter writer = response.getWriter();
|
PrintWriter writer = response.getWriter();
|
||||||
|
|
||||||
writer.print(data); // Noncompliant
|
writer.print(data);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
import org.owasp.encoder.Encode;
|
import org.owasp.encoder.Encode;
|
||||||
|
|
||||||
@ -33,29 +32,27 @@ public void endpoint(HttpServletRequest request, HttpServletResponse response) t
|
|||||||
writer.print(Encode.forHtml(data));
|
writer.print(Encode.forHtml(data));
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
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 with the content-type header.
|
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 with the content-type header.
|
||||||
|
|
||||||
For example, setting the content-type to `text/plain` with the `setContentType` function allows to safely reflect user input because browsers will not try to parse and execute the response.
|
For example, setting the content-type to `text/plain` with the `setContentType` function allows to safely reflect user input because browsers will not try to parse and execute the response.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=2,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
public void endpoint(HttpServletRequest request, HttpServletResponse response) throws IOException
|
public void endpoint(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||||
{
|
{
|
||||||
String data = request.getParameter("input");
|
String data = request.getParameter("input");
|
||||||
PrintWriter writer = response.getWriter();
|
PrintWriter writer = response.getWriter();
|
||||||
|
|
||||||
writer.print(data); // Noncompliant
|
writer.print(data);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public void endpoint(HttpServletRequest request, HttpServletResponse response) throws IOException
|
public void endpoint(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||||
{
|
{
|
||||||
@ -66,7 +63,6 @@ public void endpoint(HttpServletRequest request, HttpServletResponse response) t
|
|||||||
writer.print(data);
|
writer.print(data);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -5,11 +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.
|
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.
|
For example, you can use the `produces` property of the `GetMapping` annotation.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
@RestController
|
@RestController
|
||||||
public class ApiController
|
public class ApiController
|
||||||
@ -17,13 +15,14 @@ public class ApiController
|
|||||||
@GetMapping(value = "/endpoint")
|
@GetMapping(value = "/endpoint")
|
||||||
public String endpoint(@RequestParam("input") input)
|
public String endpoint(@RequestParam("input") input)
|
||||||
{
|
{
|
||||||
return input; // Noncompliant
|
return input;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
@RestController
|
@RestController
|
||||||
public class ApiController
|
public class ApiController
|
||||||
@ -35,7 +34,6 @@ public class ApiController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
@ -48,7 +46,6 @@ Thus, the response is not vulnerable to reflected cross-site scripting.
|
|||||||
|
|
||||||
For example, setting the content-type to `text/plain` allows to safely reflect user input since browsers will not try to parse and execute the response.
|
For example, setting the content-type to `text/plain` allows to safely reflect user input since browsers will not try to parse and execute the response.
|
||||||
|
|
||||||
|
|
||||||
=== Pitfalls
|
=== Pitfalls
|
||||||
|
|
||||||
include::../../common/pitfalls/content-types.adoc[]
|
include::../../common/pitfalls/content-types.adoc[]
|
||||||
|
@ -4,27 +4,25 @@ 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.
|
User input embedded in HTML code should be HTML-encoded to prevent the injection of additional code.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,html,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,html]
|
|
||||||
----
|
----
|
||||||
<body>
|
<body>
|
||||||
<p th:utext="Hello, ${input}!" /> <!-- Noncompliant -->
|
<p th:utext="Hello, ${input}!" /> <!-- Noncompliant -->
|
||||||
<p>Hello, [(${input})]!</p> <!-- Noncompliant -->
|
<p>Hello, [(${input})]!</p> <!-- Noncompliant -->
|
||||||
</body>
|
</body>
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,html]
|
|
||||||
|
[source,html,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
<body>
|
<body>
|
||||||
<p th:text="Hello, ${input}!" />
|
<p th:text="Hello, ${input}!" />
|
||||||
<p>Hello, [[${input}]]!</p>
|
<p>Hello, [[${input}]]!</p>
|
||||||
</body>
|
</body>
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -5,49 +5,45 @@ 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.
|
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 `JsonResponse` class to safely return JSON messages.
|
For example, you can use the `JsonResponse` class to safely return JSON messages.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,javascript,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,javascript]
|
|
||||||
----
|
----
|
||||||
function (req, res) {
|
function (req, res) {
|
||||||
json = JSON.stringify({ "data": req.query.input });
|
json = JSON.stringify({ "data": req.query.input });
|
||||||
res.send(tainted); // Noncompliant
|
res.send(tainted);
|
||||||
};
|
};
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,javascript]
|
|
||||||
|
[source,javascript,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
function (req, res) {
|
function (req, res) {
|
||||||
res.json({ "data": req.query.input });
|
res.json({ "data": req.query.input });
|
||||||
};
|
};
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
It is also possible to set the content-type header manually using the `content_type` parameter when creating an `HttpResponse` object.
|
It is also possible to set the content-type header manually using the `content_type` parameter when creating an `HttpResponse` object.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,javascript,diff-id=2,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,javascript]
|
|
||||||
----
|
----
|
||||||
function (req, res) {
|
function (req, res) {
|
||||||
res.send(req.query.input); // Noncompliant
|
res.send(req.query.input);
|
||||||
};
|
};
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,javascript]
|
|
||||||
|
[source,javascript,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
function (req, res) {
|
function (req, res) {
|
||||||
res.set('Content-Type', 'text/plain');
|
res.set('Content-Type', 'text/plain');
|
||||||
res.send(req.query.input);
|
res.send(req.query.input);
|
||||||
};
|
};
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -5,43 +5,38 @@ 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.
|
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.
|
PHP provides the built-in function `htmlspecialchars` to do this.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,php,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,php]
|
|
||||||
----
|
----
|
||||||
echo '<h1>' . $input . '</h1>'; // Noncompliant
|
echo '<h1>' . $input . '</h1>';
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,php]
|
|
||||||
|
[source,php,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
echo '<h1>' . htmlspecialchars($input) . '</h1>';
|
echo '<h1>' . htmlspecialchars($input) . '</h1>';
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
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 with the content-type header.
|
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 with the content-type header.
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
|
==== Non-compliant code example
|
||||||
|
|
||||||
[cols="a"]
|
[source,php,diff-id=2,diff-type=noncompliant]
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
|
||||||
|
|
|
||||||
[source,php]
|
|
||||||
----
|
----
|
||||||
echo $input; // Noncompliant
|
echo $input;
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,php]
|
|
||||||
|
[source,php,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
header('Content-Type: text/plain');
|
header('Content-Type: text/plain');
|
||||||
echo $input;
|
echo $input;
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
@ -57,21 +52,19 @@ By default, `htmlspecialchars` does not encode single quotes, so if `++$input++`
|
|||||||
|
|
||||||
Make sure to set the option `ENT_QUOTES` to encode single quotes.
|
Make sure to set the option `ENT_QUOTES` to encode single quotes.
|
||||||
|
|
||||||
[cols="a"]
|
===== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,php,diff-id=3,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,php]
|
|
||||||
----
|
----
|
||||||
echo "<img src='" . htmlspecialchars($input) . "'>";
|
echo "<img src='" . htmlspecialchars($input) . "'>";
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
===== Compliant solution
|
||||||
[source,php]
|
|
||||||
|
[source,php,diff-id=3,diff-type=compliant]
|
||||||
----
|
----
|
||||||
echo "<img src='" . htmlspecialchars($input, ENT_QUOTES) . "'>";
|
echo "<img src='" . htmlspecialchars($input, ENT_QUOTES) . "'>";
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
==== Headers and output
|
==== Headers and output
|
||||||
|
|
||||||
@ -79,24 +72,22 @@ 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.
|
To fix this issue, send the headers before any output.
|
||||||
|
|
||||||
[cols="a"]
|
===== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,php,diff-id=4,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,php]
|
|
||||||
----
|
----
|
||||||
echo 'No more headers at this point';
|
echo 'No more headers at this point';
|
||||||
header('Content-Type: text/plain');
|
header('Content-Type: text/plain');
|
||||||
echo $input;
|
echo $input;
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
===== Compliant solution
|
||||||
[source,php]
|
|
||||||
|
[source,php,diff-id=4,diff-type=compliant]
|
||||||
----
|
----
|
||||||
header('Content-Type: text/plain');
|
header('Content-Type: text/plain');
|
||||||
echo $input;
|
echo $input;
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== Going the extra mile
|
=== Going the extra mile
|
||||||
|
|
||||||
|
@ -5,39 +5,35 @@ 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.
|
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 `json` method of the `Response` class to safely return JSON messages.
|
For example, you can use the `json` method of the `Response` class to safely return JSON messages.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,php,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,php]
|
|
||||||
----
|
----
|
||||||
$response = response(json_encode(['data' => $input]), 200); // Noncompliant
|
$response = response(json_encode(['data' => $input]), 200);
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,php]
|
|
||||||
|
[source,php,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
$response = response()->json(['data' => $input]);
|
$response = response()->json(['data' => $input]);
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
It is also possible to set the content-type header manually using the `header` method of the `Response` class.
|
It is also possible to set the content-type header manually using the `header` method of the `Response` class.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,php,diff-id=2,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,php]
|
|
||||||
----
|
----
|
||||||
$response = response($input, 200); // Noncompliant
|
$response = response($input, 200);
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,php]
|
|
||||||
|
[source,php,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
$response = response($input, 200)->header('Content-Type', 'text/plain');
|
$response = response($input, 200)->header('Content-Type', 'text/plain');
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -5,43 +5,40 @@ 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.
|
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.
|
For example, you can use the class `JsonResponse` to return JSON messages safely.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,php,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,php]
|
|
||||||
----
|
----
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
$response = new Response();
|
$response = new Response();
|
||||||
$response->setContent(json_encode(['data' => $input])); // Noncompliant
|
$response->setContent(json_encode(['data' => $input]));
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,php]
|
|
||||||
|
[source,php,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
|
||||||
$response = new JsonResponse(['data' => $input]);
|
$response = new JsonResponse(['data' => $input]);
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
It is also possible to set the content-type manually using the `headers` attribute.
|
It is also possible to set the content-type manually using the `headers` attribute.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,php,diff-id=2,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,php]
|
|
||||||
----
|
----
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
$response = new Response();
|
$response = new Response();
|
||||||
$response->setContent($input); // Noncompliant
|
$response->setContent($input);
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,php]
|
|
||||||
|
[source,php,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
@ -49,7 +46,6 @@ $response = new Response();
|
|||||||
$response->headers->set('Content-Type', 'text/plain');
|
$response->headers->set('Content-Type', 'text/plain');
|
||||||
$response->setContent($input);
|
$response->setContent($input);
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -5,22 +5,21 @@ 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.
|
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 `JsonResponse` class to return JSON messages securely.
|
For example, you can use the `JsonResponse` class to return JSON messages securely.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,python,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,python]
|
|
||||||
----
|
----
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
import json
|
import json
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
json = json.dumps({ "data": request.GET.get("input") })
|
json = json.dumps({ "data": request.GET.get("input") })
|
||||||
return HttpResponse(json) # Noncompliant
|
return HttpResponse(json)
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,python]
|
|
||||||
|
[source,python,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
|
|
||||||
@ -28,31 +27,28 @@ def index(request):
|
|||||||
json = { "data": request.GET.get("input") }
|
json = { "data": request.GET.get("input") }
|
||||||
return JsonResponse(json)
|
return JsonResponse(json)
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
It is also possible to set the content-type manually with the `content_type` parameter when creating an `HttpResponse` object.
|
It is also possible to set the content-type manually with the `content_type` parameter when creating an `HttpResponse` object.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,python,diff-id=2,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,python]
|
|
||||||
----
|
----
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
return HttpResponse(request.GET.get("input")) # Noncompliant
|
return HttpResponse(request.GET.get("input"))
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,python]
|
|
||||||
|
[source,python,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
|
|
||||||
def index(request):
|
def index(request):
|
||||||
return HttpResponse(request.GET.get("input"), content_type="text/plain")
|
return HttpResponse(request.GET.get("input"), content_type="text/plain")
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +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.
|
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"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,python,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,python]
|
|
||||||
----
|
----
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
@ -16,16 +14,17 @@ def hello(request):
|
|||||||
return render(request, 'hello.html', {'hello': hello})
|
return render(request, 'hello.html', {'hello': hello})
|
||||||
----
|
----
|
||||||
|
|
||||||
[source,html]
|
[source,html,diff-id=2,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
{% autoescape false %}
|
{% autoescape false %}
|
||||||
{{ hello }} <!-- Noncompliant -->
|
{{ hello }} <!-- Noncompliant -->
|
||||||
{% endautoescape %}
|
{% endautoescape %}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,python]
|
|
||||||
|
[source,python,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
||||||
@ -34,12 +33,11 @@ def hello(request):
|
|||||||
return render(request, 'hello.html', {'name': name})
|
return render(request, 'hello.html', {'name': name})
|
||||||
----
|
----
|
||||||
|
|
||||||
[source,html]
|
[source,html,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<h1>Hello {{ name }}</h1>
|
<h1>Hello {{ name }}</h1>
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
@ -53,11 +51,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.
|
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"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,python,diff-id=3,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,python]
|
|
||||||
----
|
----
|
||||||
# settings.py
|
# settings.py
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
@ -70,9 +66,10 @@ TEMPLATES = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,python]
|
|
||||||
|
[source,python,diff-id=3,diff-type=compliant]
|
||||||
----
|
----
|
||||||
# settings.py
|
# settings.py
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
@ -86,8 +83,6 @@ TEMPLATES = [
|
|||||||
]
|
]
|
||||||
----
|
----
|
||||||
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== Pitfalls
|
=== Pitfalls
|
||||||
|
|
||||||
==== Variables in script blocks
|
==== Variables in script blocks
|
||||||
@ -97,24 +92,22 @@ 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.
|
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"]
|
===== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,html,diff-id=4,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,html]
|
|
||||||
----
|
----
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<script> var name = '{{ name }}';</script>
|
<script> var name = '{{ name }}';</script>
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
===== Compliant solution
|
||||||
[source,html]
|
|
||||||
|
[source,html,diff-id=4,diff-type=compliant]
|
||||||
----
|
----
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
{{ name\|json_script:"name-data" }}
|
{{ name\|json_script:"name-data" }}
|
||||||
<script> var name = JSON.parse(document.getElementById('name-data').textContent);</script>
|
<script> var name = JSON.parse(document.getElementById('name-data').textContent);</script>
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
include::../../common/pitfalls/validation.adoc[]
|
include::../../common/pitfalls/validation.adoc[]
|
||||||
|
|
||||||
|
@ -5,23 +5,22 @@ 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.
|
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.
|
For example, you can use the `jsonify` class to return JSON messages safely.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,python,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,python]
|
|
||||||
----
|
----
|
||||||
from flask import make_response, request
|
from flask import make_response, request
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
json = json.dumps({ "data": request.args.get("input") }) # Noncompliant
|
json = json.dumps({ "data": request.args.get("input") })
|
||||||
return make_response(json)
|
return make_response(json)
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,python]
|
|
||||||
|
[source,python,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
from flask import jsonify, request
|
from flask import jsonify, request
|
||||||
|
|
||||||
@ -29,25 +28,23 @@ from flask import jsonify, request
|
|||||||
def index():
|
def index():
|
||||||
return jsonify({ "data": request.args.get("input") })
|
return jsonify({ "data": request.args.get("input") })
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
It is also possible to set the content-type manually with the `mimetype` parameter when calling the `make_response` function.
|
It is also possible to set the content-type manually with the `mimetype` parameter when calling the `make_response` function.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,python,diff-id=2,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,python]
|
|
||||||
----
|
----
|
||||||
from flask import make_response, request
|
from flask import make_response, request
|
||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
return make_response(request.args.get("input")) # Noncompliant
|
return make_response(request.args.get("input"))
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,python]
|
|
||||||
|
[source,python,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
from flask import make_response, request
|
from flask import make_response, request
|
||||||
|
|
||||||
@ -55,7 +52,6 @@ from flask import make_response, request
|
|||||||
def index():
|
def index():
|
||||||
return make_response(request.args.get("input"), mimetype="text/plain")
|
return make_response(request.args.get("input"), mimetype="text/plain")
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
The following code is vulnerable to cross-site scripting because auto-escaping of special HTML characters has been disabled.
|
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.
|
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"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,python,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,python]
|
|
||||||
----
|
----
|
||||||
from flask import render_template
|
from flask import render_template
|
||||||
|
|
||||||
@ -17,16 +15,17 @@ def hello(name=None):
|
|||||||
return render_template('hello.html', hello=hello)
|
return render_template('hello.html', hello=hello)
|
||||||
----
|
----
|
||||||
|
|
||||||
[source,html]
|
[source,html,diff-id=2,diff-type=noncompliant]
|
||||||
----
|
----
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
{% autoescape false %}
|
{% autoescape false %}
|
||||||
{{ hello }} <!-- Noncompliant -->
|
{{ hello }} <!-- Noncompliant -->
|
||||||
{% endautoescape %}
|
{% endautoescape %}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,python]
|
|
||||||
|
[source,python,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
from flask import render_template
|
from flask import render_template
|
||||||
|
|
||||||
@ -35,12 +34,11 @@ def hello(name=None):
|
|||||||
return render_template('hello.html', name=name)
|
return render_template('hello.html', name=name)
|
||||||
----
|
----
|
||||||
|
|
||||||
[source,html]
|
[source,html,diff-id=2,diff-type=compliant]
|
||||||
----
|
----
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<h1>Hello {{ name }}</h1>
|
<h1>Hello {{ name }}</h1>
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
@ -58,24 +56,22 @@ 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.
|
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.
|
Another option is to use the ``++tojson++`` filter to insert a data structure in the JavaScript code at render time.
|
||||||
|
|
||||||
[cols="a"]
|
===== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,html,diff-id=3,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,html]
|
|
||||||
----
|
----
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<script> var name = '{{ name }}';</script>
|
<script> var name = '{{ name }}';</script>
|
||||||
|
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
===== Compliant solution
|
||||||
[source,html]
|
|
||||||
|
[source,html,diff-id=3,diff-type=compliant]
|
||||||
----
|
----
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<script> var name = {{ name \| tojson }}</script>
|
<script> var name = {{ name \| tojson }}</script>
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== Going the extra mile
|
=== Going the extra mile
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
The following code is vulnerable to deserialization attacks because it
|
The following code is vulnerable to deserialization attacks because it
|
||||||
deserializes HTTP data without validating it first.
|
deserializes HTTP data without validating it first.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class Example : Controller
|
public class Example : Controller
|
||||||
{
|
{
|
||||||
@ -20,9 +18,10 @@ public class Example : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class Example : Controller
|
public class Example : Controller
|
||||||
{
|
{
|
||||||
@ -35,7 +34,6 @@ public class Example : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
@ -62,4 +60,3 @@ these capabilities:
|
|||||||
* `LosFormatter`
|
* `LosFormatter`
|
||||||
* `ObjectStateFormatter`
|
* `ObjectStateFormatter`
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,23 +3,22 @@
|
|||||||
The following code is vulnerable to deserialization attacks because it
|
The following code is vulnerable to deserialization attacks because it
|
||||||
deserializes HTTP data without validating it first.
|
deserializes HTTP data without validating it first.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
public class RequestProcessor {
|
public class RequestProcessor {
|
||||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
|
||||||
ServletInputStream servletIS = request.getInputStream();
|
ServletInputStream servletIS = request.getInputStream();
|
||||||
ObjectInputStream objectIS = new ObjectInputStream(servletIS);
|
ObjectInputStream objectIS = new ObjectInputStream(servletIS);
|
||||||
Object input = objectIS.readObject(); // Noncompliant
|
Object input = objectIS.readObject();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class SecureObjectInputStream extends ObjectInputStream {
|
public class SecureObjectInputStream extends ObjectInputStream {
|
||||||
|
|
||||||
@ -47,7 +46,6 @@ public class RequestProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -16,15 +14,16 @@ public class ExampleController : Controller
|
|||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IActionResult ImageFetch(string location)
|
public IActionResult ImageFetch(string location)
|
||||||
{
|
{
|
||||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(location); // Noncompliant
|
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(location);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -50,6 +49,5 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
include::../../common/fix/how-does-this-work.adoc[]
|
include::../../common/fix/how-does-this-work.adoc[]
|
@ -2,23 +2,22 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
String location = req.getParameter("url");
|
String location = req.getParameter("url");
|
||||||
|
|
||||||
URL url = new URL(location);
|
URL url = new URL(location);
|
||||||
|
|
||||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Noncompliant
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
String location = req.getParameter("url");
|
String location = req.getParameter("url");
|
||||||
@ -33,6 +32,5 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO
|
|||||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
include::../../common/fix/how-does-this-work.adoc[]
|
include::../../common/fix/how-does-this-work.adoc[]
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -20,14 +18,15 @@ public class ExampleController : Controller
|
|||||||
{
|
{
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
_logger.Info("Log: " + data); // Noncompliant
|
_logger.Info("Log: " + data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -47,6 +46,5 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
include::../../common/fix/how-does-this-work.adoc[]
|
include::../../common/fix/how-does-this-work.adoc[]
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
private static final Logger logger = Logger.getLogger("Logger");
|
private static final Logger logger = Logger.getLogger("Logger");
|
||||||
|
|
||||||
@ -14,13 +12,14 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
|
|||||||
|
|
||||||
String data = request.getParameter("data");
|
String data = request.getParameter("data");
|
||||||
if(data != null){
|
if(data != null){
|
||||||
logger.log(Level.INFO, "Data: {0} ", data); // Noncompliant
|
logger.log(Level.INFO, "Data: {0} ", data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
private static final Logger logger = Logger.getLogger("Logger");
|
private static final Logger logger = Logger.getLogger("Logger");
|
||||||
|
|
||||||
@ -33,6 +32,5 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
include::../../common/fix/how-does-this-work.adoc[]
|
include::../../common/fix/how-does-this-work.adoc[]
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -16,13 +14,14 @@ public class ExampleController : Controller
|
|||||||
[HttpGet]
|
[HttpGet]
|
||||||
public void Redirect(string url)
|
public void Redirect(string url)
|
||||||
{
|
{
|
||||||
Response.Redirect(url); // Noncompliant
|
Response.Redirect(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -42,6 +41,5 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
include::../../common/fix/how-does-this-work.adoc[]
|
include::../../common/fix/how-does-this-work.adoc[]
|
@ -2,20 +2,19 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
String location = req.getParameter("url");
|
String location = req.getParameter("url");
|
||||||
resp.sendRedirect(location); // Noncompliant
|
resp.sendRedirect(location);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||||
String location = req.getParameter("url");
|
String location = req.getParameter("url");
|
||||||
@ -28,6 +27,5 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO
|
|||||||
resp.sendRedirect(location);
|
resp.sendRedirect(location);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
include::../../common/fix/how-does-this-work.adoc[]
|
include::../../common/fix/how-does-this-work.adoc[]
|
@ -4,11 +4,9 @@ The following code is vulnerable to NoSQL injections because untrusted data is
|
|||||||
concatenated to the `$where` operator. This operator indicates to the backend
|
concatenated to the `$where` operator. This operator indicates to the backend
|
||||||
that the expression needs to be interpreted, resulting in code injection.
|
that the expression needs to be interpreted, resulting in code injection.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
@ -24,14 +22,15 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Un
|
|||||||
DBCollection collection = database.getCollection("exampleCollection");
|
DBCollection collection = database.getCollection("exampleCollection");
|
||||||
BasicDBObject query = new BasicDBObject();
|
BasicDBObject query = new BasicDBObject();
|
||||||
|
|
||||||
query.append("$where", "this.field == \"" + input + "\""); // Noncompliant
|
query.append("$where", "this.field == \"" + input + "\"");
|
||||||
|
|
||||||
collection.find(query);
|
collection.find(query);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
@ -52,7 +51,6 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Un
|
|||||||
collection.find(query);
|
collection.find(query);
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
The following code is vulnerable to arbitrary code execution because it compiles
|
The following code is vulnerable to arbitrary code execution because it compiles
|
||||||
and runs HTTP data.
|
and runs HTTP data.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
using System.CodeDom.Compiler;
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
@ -28,15 +26,16 @@ public class ExampleController : Controller
|
|||||||
|
|
||||||
var provider = CodeDomProvider.CreateProvider("CSharp");
|
var provider = CodeDomProvider.CreateProvider("CSharp");
|
||||||
var compilerParameters = new CompilerParameters { ReferencedAssemblies = { "System.dll", "System.Runtime.dll" } };
|
var compilerParameters = new CompilerParameters { ReferencedAssemblies = { "System.dll", "System.Runtime.dll" } };
|
||||||
var compilerResults = provider.CompileAssemblyFromSource(compilerParameters, code); // Noncompliant
|
var compilerResults = provider.CompileAssemblyFromSource(compilerParameters, code);
|
||||||
object myInstance = compilerResults.CompiledAssembly.CreateInstance("MyClass");
|
object myInstance = compilerResults.CompiledAssembly.CreateInstance("MyClass");
|
||||||
myInstance.GetType().GetMethod("MyMethod").Invoke(myInstance, new object[0]);
|
myInstance.GetType().GetMethod("MyMethod").Invoke(myInstance, new object[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
using System.CodeDom.Compiler;
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
@ -63,7 +62,6 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -3,11 +3,9 @@
|
|||||||
The following code is vulnerable to arbitrary code execution because it compiles
|
The following code is vulnerable to arbitrary code execution because it compiles
|
||||||
and runs HTTP data.
|
and runs HTTP data.
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
import org.codehaus.janino.ScriptEvaluator;
|
import org.codehaus.janino.ScriptEvaluator;
|
||||||
|
|
||||||
@ -17,14 +15,15 @@ public class ExampleController
|
|||||||
@GetMapping(value = "/")
|
@GetMapping(value = "/")
|
||||||
public void exec(@RequestParam("message") String message) throws IOException, InvocationTargetException {
|
public void exec(@RequestParam("message") String message) throws IOException, InvocationTargetException {
|
||||||
ScriptEvaluator se = new ScriptEvaluator();
|
ScriptEvaluator se = new ScriptEvaluator();
|
||||||
se.cook("System.out.println(\" + message \");"); // Noncompliant
|
se.cook("System.out.println(\" + message \");");
|
||||||
se.evaluate(null);
|
se.evaluate(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
import org.codehaus.janino.ScriptEvaluator;
|
import org.codehaus.janino.ScriptEvaluator;
|
||||||
|
|
||||||
@ -40,10 +39,8 @@ public class ExampleController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
include::../../common/fix/introduction.adoc[]
|
include::../../common/fix/introduction.adoc[]
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,11 +15,9 @@ In this particular case, an attacker may remove files in `/some/folder` with the
|
|||||||
'*' -exec rm -rf {} \;
|
'*' -exec rm -rf {} \;
|
||||||
----
|
----
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -27,14 +25,15 @@ public class ExampleController : Controller
|
|||||||
{
|
{
|
||||||
Process p = new Process();
|
Process p = new Process();
|
||||||
p.StartInfo.FileName = "/usr/bin/find";
|
p.StartInfo.FileName = "/usr/bin/find";
|
||||||
p.StartInfo.Arguments = "/some/folder -iname " + args; // Noncompliant
|
p.StartInfo.Arguments = "/some/folder -iname " + args;
|
||||||
p.Start();
|
p.Start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -49,15 +48,12 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
include::../../common/fix/introduction.adoc[]
|
include::../../common/fix/introduction.adoc[]
|
||||||
|
|
||||||
|
|
||||||
Here `ArgumentList` takes care of escaping the passed arguments and internally
|
Here `ArgumentList` takes care of escaping the passed arguments and internally
|
||||||
creates a single string given to the operating system when `System.Diagnostics.Process.Start()` is
|
creates a single string given to the operating system when `System.Diagnostics.Process.Start()` is
|
||||||
called.
|
called.
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -14,13 +12,14 @@ public class ExampleController
|
|||||||
@GetMapping(value = "/find")
|
@GetMapping(value = "/find")
|
||||||
public void find(@RequestParam("filename") String filename) throws IOException {
|
public void find(@RequestParam("filename") String filename) throws IOException {
|
||||||
|
|
||||||
CommandLine cmd = new CommandLine("/usr/bin/find . -iname " + filename); // Noncompliant
|
CommandLine cmd = new CommandLine("/usr/bin/find . -iname " + filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -33,12 +32,10 @@ public class ExampleController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
include::../../common/fix/introduction.adoc[]
|
include::../../common/fix/introduction.adoc[]
|
||||||
|
|
||||||
|
|
||||||
Here `org.apache.commons.exec.CommandLine.addArguments(String[] addArguments)` takes care of escaping the passed arguments and internally
|
Here `org.apache.commons.exec.CommandLine.addArguments(String[] addArguments)` takes care of escaping the passed arguments and internally
|
||||||
creates a single string given to the operating system to be executed.
|
creates a single string given to the operating system to be executed.
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -14,13 +12,14 @@ public class ExampleController
|
|||||||
@GetMapping(value = "/find")
|
@GetMapping(value = "/find")
|
||||||
public void find(@RequestParam("filename") String filename) throws IOException {
|
public void find(@RequestParam("filename") String filename) throws IOException {
|
||||||
|
|
||||||
Runtime.getRuntime().exec("/usr/bin/find . -iname " + filename); // Noncompliant
|
Runtime.getRuntime().exec("/usr/bin/find . -iname " + filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
@Controller
|
@Controller
|
||||||
public class ExampleController
|
public class ExampleController
|
||||||
@ -33,7 +32,6 @@ public class ExampleController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
++java.lang.Runtime++ is sometimes used over ++java.lang.ProcessBuilder++ due to ease of use. Flexibility in methods often introduces security issues as edge cases are easily missed. The compliant solution logic is also applied to ++java.lang.ProcessBuilder++.
|
++java.lang.Runtime++ is sometimes used over ++java.lang.ProcessBuilder++ due to ease of use. Flexibility in methods often introduces security issues as edge cases are easily missed. The compliant solution logic is also applied to ++java.lang.ProcessBuilder++.
|
||||||
|
|
||||||
@ -41,6 +39,5 @@ public class ExampleController
|
|||||||
|
|
||||||
include::../../common/fix/introduction.adoc[]
|
include::../../common/fix/introduction.adoc[]
|
||||||
|
|
||||||
|
|
||||||
Here `java.lang.Runtime.exec(String[] cmdarray)` takes care of escaping the passed arguments and internally
|
Here `java.lang.Runtime.exec(String[] cmdarray)` takes care of escaping the passed arguments and internally
|
||||||
creates a single string given to the operating system to be executed.
|
creates a single string given to the operating system to be executed.
|
||||||
|
@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -20,13 +18,14 @@ public class ExampleController : Controller
|
|||||||
ZipArchiveEntry entry = entriesEnumerator.Current;
|
ZipArchiveEntry entry = entriesEnumerator.Current;
|
||||||
string destinationPath = Path.Combine(TargetDirectory, entry.FullName);
|
string destinationPath = Path.Combine(TargetDirectory, entry.FullName);
|
||||||
|
|
||||||
entry.ExtractToFile(destinationPath); // Noncompliant
|
entry.ExtractToFile(destinationPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class ExampleController : Controller
|
public class ExampleController : Controller
|
||||||
{
|
{
|
||||||
@ -45,7 +44,6 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
public class Example {
|
public class Example {
|
||||||
|
|
||||||
@ -23,13 +21,14 @@ public class Example {
|
|||||||
|
|
||||||
File file = new File(targetDirectory + entry.getName());
|
File file = new File(targetDirectory + entry.getName());
|
||||||
|
|
||||||
Files.copy(inputStream, file.toPath(), StandardCopyOption.REPLACE_EXISTING); // Noncompliant
|
Files.copy(inputStream, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
public class Example {
|
public class Example {
|
||||||
|
|
||||||
@ -51,7 +50,6 @@ public class Example {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
=== How does this work?
|
=== How does this work?
|
||||||
|
|
||||||
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,csharp]
|
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -18,16 +16,17 @@ public class ExampleController : Controller
|
|||||||
{
|
{
|
||||||
if (Request.Cookies["ASP.NET_SessionId"] == null)
|
if (Request.Cookies["ASP.NET_SessionId"] == null)
|
||||||
{
|
{
|
||||||
Response.Cookies.Append("ASP.NET_SessionId", cookie); // Noncompliant
|
Response.Cookies.Append("ASP.NET_SessionId", cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
return View("Welcome");
|
return View("Welcome");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,csharp]
|
|
||||||
|
[source,csharp,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using System.Web.Mvc;
|
using System.Web.Mvc;
|
||||||
@ -46,6 +45,5 @@ public class ExampleController : Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
include::../../common/fix/how-does-this-work.adoc[]
|
include::../../common/fix/how-does-this-work.adoc[]
|
@ -2,11 +2,9 @@
|
|||||||
|
|
||||||
include::../../common/fix/code-rationale.adoc[]
|
include::../../common/fix/code-rationale.adoc[]
|
||||||
|
|
||||||
[cols="a"]
|
==== Non-compliant code example
|
||||||
|===
|
|
||||||
h| Non-compliant code example
|
[source,java,diff-id=1,diff-type=noncompliant]
|
||||||
|
|
|
||||||
[source,java]
|
|
||||||
----
|
----
|
||||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||||
Optional<Cookie> cookieOpt = Arrays.stream(request.getCookies())
|
Optional<Cookie> cookieOpt = Arrays.stream(request.getCookies())
|
||||||
@ -15,16 +13,17 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
|
|||||||
|
|
||||||
if (!cookieOpt.isPresent()) {
|
if (!cookieOpt.isPresent()) {
|
||||||
String cookie = request.getParameter("cookie");
|
String cookie = request.getParameter("cookie");
|
||||||
Cookie cookieObj = new Cookie("jsessionid", cookie); // Noncompliant
|
Cookie cookieObj = new Cookie("jsessionid", cookie);
|
||||||
response.addCookie(cookieObj);
|
response.addCookie(cookieObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
response.sendRedirect("/welcome.jsp");
|
response.sendRedirect("/welcome.jsp");
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
h| Compliant solution
|
|
||||||
|
|
==== Compliant solution
|
||||||
[source,java]
|
|
||||||
|
[source,java,diff-id=1,diff-type=compliant]
|
||||||
----
|
----
|
||||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||||
Optional<Cookie> cookieOpt = Arrays.stream(request.getCookies())
|
Optional<Cookie> cookieOpt = Arrays.stream(request.getCookies())
|
||||||
@ -38,6 +37,5 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|===
|
|
||||||
|
|
||||||
include::../../common/fix/how-does-this-work.adoc[]
|
include::../../common/fix/how-does-this-work.adoc[]
|
Loading…
x
Reference in New Issue
Block a user