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[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
public void Run(string binary)
|
||||
{
|
||||
Process p = new Process();
|
||||
p.StartInfo.FileName = binary; // Noncompliant
|
||||
p.StartInfo.FileName = binary;
|
||||
p.Start();
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -36,7 +35,6 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@Controller
|
||||
public class ExampleController
|
||||
@ -14,15 +12,16 @@ public class ExampleController
|
||||
@GetMapping(value = "/exec")
|
||||
public void exec(@RequestParam("command") String command) throws IOException {
|
||||
|
||||
CommandLine cmd = new CommandLine(command); // Noncompliant
|
||||
CommandLine cmd = new CommandLine(command);
|
||||
DefaultExecutor executor = new DefaultExecutor();
|
||||
executor.execute(cmd);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@Controller
|
||||
public class ExampleController
|
||||
@ -42,7 +41,6 @@ public class ExampleController
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@Controller
|
||||
public class ExampleController
|
||||
@ -14,13 +12,14 @@ public class ExampleController
|
||||
@GetMapping(value = "/exec")
|
||||
public void exec(@RequestParam("command") String command) throws IOException {
|
||||
|
||||
Runtime.getRuntime().exec(command); // Noncompliant
|
||||
Runtime.getRuntime().exec(command);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@Controller
|
||||
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++.
|
||||
|
||||
|
@ -3,11 +3,9 @@
|
||||
The following non-compliant code is vulnerable to LDAP injections because untrusted data is
|
||||
concatenated in an LDAP query without prior validation.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -16,15 +14,16 @@ public class ExampleController : Controller
|
||||
DirectoryEntry directory = new DirectoryEntry("LDAP://ou=system");
|
||||
DirectorySearcher search = new DirectorySearcher(directory);
|
||||
|
||||
search.Filter = "(&(uid=" + user + ")(userPassword=" + pass + "))"; // Noncompliant
|
||||
search.Filter = "(&(uid=" + user + ")(userPassword=" + pass + "))";
|
||||
|
||||
return Json(search.FindOne() != null);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -45,7 +44,6 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -3,11 +3,9 @@
|
||||
The following non-compliant code is vulnerable to LDAP injections because untrusted data is
|
||||
concatenated to an LDAP query without prior sanitization or validation.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
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 + "))";
|
||||
|
||||
NamingEnumeration<SearchResult> results = ctx.search("ou=system", filter, new SearchControls()); // Noncompliant
|
||||
NamingEnumeration<SearchResult> results = ctx.search("ou=system", filter, new SearchControls());
|
||||
return results.hasMore();
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public boolean authenticate(HttpServletRequest req, DirContext ctx) throws NamingException {
|
||||
String user = req.getParameter("user");
|
||||
@ -34,7 +33,6 @@ public boolean authenticate(HttpServletRequest req, DirContext ctx) throws Namin
|
||||
return results.hasMore();
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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`]
|
||||
allow sanitizing these characters automatically.
|
||||
|
||||
|
||||
In the compliant solution example, the `search` function allows to safely parameterize the query.
|
||||
|
@ -3,11 +3,9 @@
|
||||
:canonicalization_function: System.IO.Path.GetFullPath
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -16,13 +14,14 @@ public class ExampleController : Controller
|
||||
public void Example(string filename)
|
||||
{
|
||||
string path = Path.Combine(TargetDirectory, filename);
|
||||
System.IO.File.Delete(path); // Noncompliant
|
||||
System.IO.File.Delete(path);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -40,7 +39,6 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -3,11 +3,9 @@
|
||||
:canonicalization_function: java.io.File.getCanonicalPath
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@Controller
|
||||
public class ExampleController
|
||||
@ -18,13 +16,14 @@ public class ExampleController
|
||||
public void delete(@RequestParam("filename") String filename) throws IOException {
|
||||
|
||||
File file = new File(targetDirectory + filename);
|
||||
file.delete(); // Noncompliant
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@Controller
|
||||
public class ExampleController
|
||||
@ -45,7 +44,6 @@ public class ExampleController
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
The following code is vulnerable to XPath injections because untrusted data is
|
||||
concatenated in an XPath query without prior validation.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -17,14 +15,15 @@ public class ExampleController : Controller
|
||||
|
||||
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
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -43,7 +42,6 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -3,11 +3,9 @@
|
||||
The following non-compliant code is vulnerable to XPath injections because untrusted data is
|
||||
concatenated to an XPath query without prior validation.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public boolean authenticate(HttpServletRequest req, XPath xpath, Document doc) throws XPathExpressionException {
|
||||
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 + "']";
|
||||
|
||||
return (boolean)xpath.evaluate(expression, doc, XPathConstants.BOOLEAN); // Noncompliant
|
||||
return (boolean)xpath.evaluate(expression, doc, XPathConstants.BOOLEAN);
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public boolean authenticate(HttpServletRequest req, XPath xpath, Document doc) throws XPathExpressionException {
|
||||
String user = request.getParameter("user");
|
||||
@ -43,7 +42,6 @@ public boolean authenticate(HttpServletRequest req, XPath xpath, Document doc) t
|
||||
}
|
||||
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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
|
||||
sanitization or validation.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
public IActionResult Validate(string regex, string input)
|
||||
{
|
||||
bool match = Regex.IsMatch(input, regex); // Noncompliant
|
||||
bool match = Regex.IsMatch(input, regex);
|
||||
|
||||
return Json(match);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -34,7 +33,6 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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
|
||||
sanitization or validation.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public boolean validate(HttpServletRequest request) {
|
||||
String regex = request.getParameter("regex");
|
||||
String input = request.getParameter("input");
|
||||
|
||||
return input.matches(regex); // Noncompliant
|
||||
return input.matches(regex);
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public boolean validate(HttpServletRequest request) {
|
||||
String regex = request.getParameter("regex");
|
||||
@ -28,7 +27,6 @@ public boolean validate(HttpServletRequest request) {
|
||||
return input.matches(Pattern.quote(regex));
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -18,7 +16,7 @@ public class ExampleController : Controller
|
||||
{
|
||||
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) {
|
||||
Unauthorized();
|
||||
}
|
||||
@ -27,9 +25,10 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -51,7 +50,6 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -18,7 +16,7 @@ public class ExampleController : Controller
|
||||
|
||||
var queryResults = Context
|
||||
.Database
|
||||
.ExecuteSqlCommand(query); // Noncompliant
|
||||
.ExecuteSqlCommand(query);
|
||||
|
||||
if (queryResults == 0)
|
||||
{
|
||||
@ -29,9 +27,10 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -54,7 +53,6 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@RestController
|
||||
public class ApiController
|
||||
@ -24,7 +22,7 @@ public class ApiController
|
||||
|
||||
try {
|
||||
queryProducer
|
||||
.createNativeQuery(query) // Noncompliant
|
||||
.createNativeQuery(query)
|
||||
.getSingleResult();
|
||||
|
||||
} catch (Exception e) {
|
||||
@ -35,9 +33,10 @@ public class ApiController
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@RestController
|
||||
public class ApiController
|
||||
@ -68,7 +67,6 @@ public class ApiController
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@RestController
|
||||
public class ApiController
|
||||
@ -24,7 +22,7 @@ public class ApiController
|
||||
|
||||
try (Statement statement = connection.createStatement()) {
|
||||
|
||||
ResultSet resultSet = statement.executeQuery(query); // Noncompliant
|
||||
ResultSet resultSet = statement.executeQuery(query);
|
||||
|
||||
if (!resultSet.next()) {
|
||||
return new ResponseEntity<>("Unauthorized", HttpStatus.UNAUTHORIZED);
|
||||
@ -35,9 +33,10 @@ public class ApiController
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@RestController
|
||||
public class ApiController
|
||||
@ -68,7 +67,6 @@ public class ApiController
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@RestController
|
||||
public class ApiController
|
||||
@ -24,7 +22,7 @@ public class ApiController
|
||||
|
||||
try {
|
||||
BeanPropertyRowMapper<User> userType = new BeanPropertyRowMapper(User.class);
|
||||
User queryResult = jdbcTemplate.queryForObject(query, userType); // Noncompliant
|
||||
User queryResult = jdbcTemplate.queryForObject(query, userType);
|
||||
|
||||
} catch (Exception e) {
|
||||
return new ResponseEntity<>("Unauthorized", HttpStatus.UNAUTHORIZED);
|
||||
@ -34,9 +32,10 @@ public class ApiController
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@RestController
|
||||
public class ApiController
|
||||
@ -64,7 +63,6 @@ public class ApiController
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
=== How to fix it in ASP.NET
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
@ -19,9 +17,10 @@ public class HelloController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
@ -37,15 +36,12 @@ public class HelloController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
|
||||
=== 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.
|
||||
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[]
|
||||
|
||||
`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 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"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
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"])
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
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>
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,html]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,html,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
<%@page contentType="text/html" pageEncoding="UTF-8"%>
|
||||
<%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
|
||||
@ -19,9 +17,10 @@ h| Non-compliant code example
|
||||
</body>
|
||||
</html>
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,html]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,html,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
<%@page contentType="text/html" pageEncoding="UTF-8"%>
|
||||
<%@taglib prefix="e" uri="https://www.owasp.org/index.php/OWASP_Java_Encoder_Project" %>
|
||||
@ -32,7 +31,6 @@ h| Compliant solution
|
||||
</body>
|
||||
</html>
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
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"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public void endpoint(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
String data = request.getParameter("input");
|
||||
PrintWriter writer = response.getWriter();
|
||||
|
||||
writer.print(data); // Noncompliant
|
||||
writer.print(data);
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
import org.owasp.encoder.Encode;
|
||||
|
||||
@ -33,29 +32,27 @@ public void endpoint(HttpServletRequest request, HttpServletResponse response) t
|
||||
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.
|
||||
|
||||
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"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
public void endpoint(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
String data = request.getParameter("input");
|
||||
PrintWriter writer = response.getWriter();
|
||||
|
||||
writer.print(data); // Noncompliant
|
||||
writer.print(data);
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
public void endpoint(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
@ -66,7 +63,6 @@ public void endpoint(HttpServletRequest request, HttpServletResponse response) t
|
||||
writer.print(data);
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
For example, you can use the `produces` property of the `GetMapping` annotation.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@RestController
|
||||
public class ApiController
|
||||
@ -17,13 +15,14 @@ public class ApiController
|
||||
@GetMapping(value = "/endpoint")
|
||||
public String endpoint(@RequestParam("input") input)
|
||||
{
|
||||
return input; // Noncompliant
|
||||
return input;
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@RestController
|
||||
public class ApiController
|
||||
@ -35,7 +34,6 @@ public class ApiController
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
|
||||
|
||||
=== Pitfalls
|
||||
|
||||
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.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,html]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,html,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
<body>
|
||||
<p th:utext="Hello, ${input}!" /> <!-- Noncompliant -->
|
||||
<p>Hello, [(${input})]!</p> <!-- Noncompliant -->
|
||||
</body>
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,html]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,html,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
<body>
|
||||
<p th:text="Hello, ${input}!" />
|
||||
<p>Hello, [[${input}]]!</p>
|
||||
</body>
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
For example, you can use the `JsonResponse` class to safely return JSON messages.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,javascript]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,javascript,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
function (req, res) {
|
||||
json = JSON.stringify({ "data": req.query.input });
|
||||
res.send(tainted); // Noncompliant
|
||||
res.send(tainted);
|
||||
};
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,javascript]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,javascript,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
function (req, res) {
|
||||
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.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,javascript]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,javascript,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
function (req, res) {
|
||||
res.send(req.query.input); // Noncompliant
|
||||
res.send(req.query.input);
|
||||
};
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,javascript]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,javascript,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
function (req, res) {
|
||||
res.set('Content-Type', 'text/plain');
|
||||
res.send(req.query.input);
|
||||
};
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
PHP provides the built-in function `htmlspecialchars` to do this.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,php]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,php,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
echo '<h1>' . $input . '</h1>'; // Noncompliant
|
||||
echo '<h1>' . $input . '</h1>';
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,php]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,php,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
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.
|
||||
|
||||
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"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,php]
|
||||
[source,php,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
echo $input; // Noncompliant
|
||||
echo $input;
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,php]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,php,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
header('Content-Type: text/plain');
|
||||
echo $input;
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,php]
|
||||
===== Non-compliant code example
|
||||
|
||||
[source,php,diff-id=3,diff-type=noncompliant]
|
||||
----
|
||||
echo "<img src='" . htmlspecialchars($input) . "'>";
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,php]
|
||||
|
||||
===== Compliant solution
|
||||
|
||||
[source,php,diff-id=3,diff-type=compliant]
|
||||
----
|
||||
echo "<img src='" . htmlspecialchars($input, ENT_QUOTES) . "'>";
|
||||
----
|
||||
|===
|
||||
|
||||
==== 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.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,php]
|
||||
===== Non-compliant code example
|
||||
|
||||
[source,php,diff-id=4,diff-type=noncompliant]
|
||||
----
|
||||
echo 'No more headers at this point';
|
||||
header('Content-Type: text/plain');
|
||||
echo $input;
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,php]
|
||||
|
||||
===== Compliant solution
|
||||
|
||||
[source,php,diff-id=4,diff-type=compliant]
|
||||
----
|
||||
header('Content-Type: text/plain');
|
||||
echo $input;
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
For example, you can use the `json` method of the `Response` class to safely return JSON messages.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,php]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,php,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
$response = response(json_encode(['data' => $input]), 200); // Noncompliant
|
||||
$response = response(json_encode(['data' => $input]), 200);
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,php]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,php,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
$response = response()->json(['data' => $input]);
|
||||
----
|
||||
|===
|
||||
|
||||
It is also possible to set the content-type header manually using the `header` method of the `Response` class.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,php]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,php,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
$response = response($input, 200); // Noncompliant
|
||||
$response = response($input, 200);
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,php]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,php,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
$response = response($input, 200)->header('Content-Type', 'text/plain');
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
For example, you can use the class `JsonResponse` to return JSON messages safely.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,php]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,php,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
$response = new Response();
|
||||
$response->setContent(json_encode(['data' => $input])); // Noncompliant
|
||||
$response->setContent(json_encode(['data' => $input]));
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,php]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,php,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
$response = new JsonResponse(['data' => $input]);
|
||||
----
|
||||
|===
|
||||
|
||||
It is also possible to set the content-type manually using the `headers` attribute.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,php]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,php,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
$response = new Response();
|
||||
$response->setContent($input); // Noncompliant
|
||||
$response->setContent($input);
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,php]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,php,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
@ -49,7 +46,6 @@ $response = new Response();
|
||||
$response->headers->set('Content-Type', 'text/plain');
|
||||
$response->setContent($input);
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
For example, you can use the `JsonResponse` class to return JSON messages securely.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,python]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,python,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
from django.http import HttpResponse
|
||||
import json
|
||||
|
||||
def index(request):
|
||||
json = json.dumps({ "data": request.GET.get("input") })
|
||||
return HttpResponse(json) # Noncompliant
|
||||
return HttpResponse(json)
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,python]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,python,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
from django.http import JsonResponse
|
||||
|
||||
@ -28,31 +27,28 @@ def index(request):
|
||||
json = { "data": request.GET.get("input") }
|
||||
return JsonResponse(json)
|
||||
----
|
||||
|===
|
||||
|
||||
It is also possible to set the content-type manually with the `content_type` parameter when creating an `HttpResponse` object.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,python]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,python,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
from django.http import HttpResponse
|
||||
|
||||
def index(request):
|
||||
return HttpResponse(request.GET.get("input")) # Noncompliant
|
||||
return HttpResponse(request.GET.get("input"))
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,python]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,python,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
from django.http import HttpResponse
|
||||
|
||||
def index(request):
|
||||
return HttpResponse(request.GET.get("input"), content_type="text/plain")
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,python]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,python,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
from django.shortcuts import render
|
||||
|
||||
@ -16,16 +14,17 @@ def hello(request):
|
||||
return render(request, 'hello.html', {'hello': hello})
|
||||
----
|
||||
|
||||
[source,html]
|
||||
[source,html,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
<!doctype html>
|
||||
{% autoescape false %}
|
||||
{{ hello }} <!-- Noncompliant -->
|
||||
{% endautoescape %}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,python]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,python,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
from django.shortcuts import render
|
||||
|
||||
@ -34,12 +33,11 @@ def hello(request):
|
||||
return render(request, 'hello.html', {'name': name})
|
||||
----
|
||||
|
||||
[source,html]
|
||||
[source,html,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
<!doctype html>
|
||||
<h1>Hello {{ name }}</h1>
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,python]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,python,diff-id=3,diff-type=noncompliant]
|
||||
----
|
||||
# settings.py
|
||||
TEMPLATES = [
|
||||
@ -70,9 +66,10 @@ TEMPLATES = [
|
||||
},
|
||||
]
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,python]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,python,diff-id=3,diff-type=compliant]
|
||||
----
|
||||
# settings.py
|
||||
TEMPLATES = [
|
||||
@ -86,8 +83,6 @@ TEMPLATES = [
|
||||
]
|
||||
----
|
||||
|
||||
|===
|
||||
|
||||
=== Pitfalls
|
||||
|
||||
==== 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.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,html]
|
||||
===== Non-compliant code example
|
||||
|
||||
[source,html,diff-id=4,diff-type=noncompliant]
|
||||
----
|
||||
<!doctype html>
|
||||
<script> var name = '{{ name }}';</script>
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,html]
|
||||
|
||||
===== Compliant solution
|
||||
|
||||
[source,html,diff-id=4,diff-type=compliant]
|
||||
----
|
||||
<!doctype html>
|
||||
{{ name\|json_script:"name-data" }}
|
||||
<script> var name = JSON.parse(document.getElementById('name-data').textContent);</script>
|
||||
----
|
||||
|===
|
||||
|
||||
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.
|
||||
For example, you can use the `jsonify` class to return JSON messages safely.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,python]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,python,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
from flask import make_response, request
|
||||
import json
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
json = json.dumps({ "data": request.args.get("input") }) # Noncompliant
|
||||
json = json.dumps({ "data": request.args.get("input") })
|
||||
return make_response(json)
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,python]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,python,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
from flask import jsonify, request
|
||||
|
||||
@ -29,25 +28,23 @@ from flask import jsonify, request
|
||||
def index():
|
||||
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.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,python]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,python,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
from flask import make_response, request
|
||||
|
||||
@app.route('/')
|
||||
def index():
|
||||
return make_response(request.args.get("input")) # Noncompliant
|
||||
return make_response(request.args.get("input"))
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,python]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,python,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
from flask import make_response, request
|
||||
|
||||
@ -55,7 +52,6 @@ from flask import make_response, request
|
||||
def index():
|
||||
return make_response(request.args.get("input"), mimetype="text/plain")
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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 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"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,python]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,python,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
from flask import render_template
|
||||
|
||||
@ -17,16 +15,17 @@ def hello(name=None):
|
||||
return render_template('hello.html', hello=hello)
|
||||
----
|
||||
|
||||
[source,html]
|
||||
[source,html,diff-id=2,diff-type=noncompliant]
|
||||
----
|
||||
<!doctype html>
|
||||
{% autoescape false %}
|
||||
{{ hello }} <!-- Noncompliant -->
|
||||
{% endautoescape %}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,python]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,python,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
from flask import render_template
|
||||
|
||||
@ -35,12 +34,11 @@ def hello(name=None):
|
||||
return render_template('hello.html', name=name)
|
||||
----
|
||||
|
||||
[source,html]
|
||||
[source,html,diff-id=2,diff-type=compliant]
|
||||
----
|
||||
<!doctype html>
|
||||
<h1>Hello {{ name }}</h1>
|
||||
----
|
||||
|===
|
||||
|
||||
=== 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.
|
||||
Another option is to use the ``++tojson++`` filter to insert a data structure in the JavaScript code at render time.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,html]
|
||||
===== Non-compliant code example
|
||||
|
||||
[source,html,diff-id=3,diff-type=noncompliant]
|
||||
----
|
||||
<!doctype html>
|
||||
<script> var name = '{{ name }}';</script>
|
||||
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,html]
|
||||
|
||||
===== Compliant solution
|
||||
|
||||
[source,html,diff-id=3,diff-type=compliant]
|
||||
----
|
||||
<!doctype html>
|
||||
<script> var name = {{ name \| tojson }}</script>
|
||||
----
|
||||
|===
|
||||
|
||||
=== Going the extra mile
|
||||
|
||||
|
@ -3,11 +3,9 @@
|
||||
The following code is vulnerable to deserialization attacks because it
|
||||
deserializes HTTP data without validating it first.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class Example : Controller
|
||||
{
|
||||
@ -20,9 +18,10 @@ public class Example : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class Example : Controller
|
||||
{
|
||||
@ -35,7 +34,6 @@ public class Example : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
@ -62,4 +60,3 @@ these capabilities:
|
||||
* `LosFormatter`
|
||||
* `ObjectStateFormatter`
|
||||
|
||||
|
||||
|
@ -3,23 +3,22 @@
|
||||
The following code is vulnerable to deserialization attacks because it
|
||||
deserializes HTTP data without validating it first.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class RequestProcessor {
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
|
||||
ServletInputStream servletIS = request.getInputStream();
|
||||
ObjectInputStream objectIS = new ObjectInputStream(servletIS);
|
||||
Object input = objectIS.readObject(); // Noncompliant
|
||||
Object input = objectIS.readObject();
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class SecureObjectInputStream extends ObjectInputStream {
|
||||
|
||||
@ -47,7 +46,6 @@ public class RequestProcessor {
|
||||
}
|
||||
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
@ -16,15 +14,16 @@ public class ExampleController : Controller
|
||||
[HttpGet]
|
||||
public IActionResult ImageFetch(string location)
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(location); // Noncompliant
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(location);
|
||||
|
||||
return Ok();
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
using System.Web;
|
||||
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[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String location = req.getParameter("url");
|
||||
|
||||
URL url = new URL(location);
|
||||
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // Noncompliant
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String location = req.getParameter("url");
|
||||
@ -33,6 +32,5 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO
|
||||
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[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
@ -20,14 +18,15 @@ public class ExampleController : Controller
|
||||
{
|
||||
if (data != null)
|
||||
{
|
||||
_logger.Info("Log: " + data); // Noncompliant
|
||||
_logger.Info("Log: " + data);
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
using System.Web;
|
||||
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[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
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");
|
||||
if(data != null){
|
||||
logger.log(Level.INFO, "Data: {0} ", data); // Noncompliant
|
||||
logger.log(Level.INFO, "Data: {0} ", data);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
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[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
@ -16,13 +14,14 @@ public class ExampleController : Controller
|
||||
[HttpGet]
|
||||
public void Redirect(string url)
|
||||
{
|
||||
Response.Redirect(url); // Noncompliant
|
||||
Response.Redirect(url);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
using System.Web;
|
||||
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[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String location = req.getParameter("url");
|
||||
resp.sendRedirect(location); // Noncompliant
|
||||
resp.sendRedirect(location);
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
|
||||
String location = req.getParameter("url");
|
||||
@ -28,6 +27,5 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IO
|
||||
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
|
||||
that the expression needs to be interpreted, resulting in code injection.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.DB;
|
||||
@ -24,14 +22,15 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Un
|
||||
DBCollection collection = database.getCollection("exampleCollection");
|
||||
BasicDBObject query = new BasicDBObject();
|
||||
|
||||
query.append("$where", "this.field == \"" + input + "\""); // Noncompliant
|
||||
query.append("$where", "this.field == \"" + input + "\"");
|
||||
|
||||
collection.find(query);
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.DB;
|
||||
@ -52,7 +51,6 @@ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws Un
|
||||
collection.find(query);
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -3,11 +3,9 @@
|
||||
The following code is vulnerable to arbitrary code execution because it compiles
|
||||
and runs HTTP data.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
using System.CodeDom.Compiler;
|
||||
|
||||
@ -17,8 +15,8 @@ public class ExampleController : Controller
|
||||
{
|
||||
string code = @"
|
||||
using System;
|
||||
public class MyClass
|
||||
{
|
||||
public class MyClass
|
||||
{
|
||||
public void MyMethod()
|
||||
{
|
||||
Console.WriteLine(""" + message + @""");
|
||||
@ -28,15 +26,16 @@ public class ExampleController : Controller
|
||||
|
||||
var provider = CodeDomProvider.CreateProvider("CSharp");
|
||||
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");
|
||||
myInstance.GetType().GetMethod("MyMethod").Invoke(myInstance, new object[0]);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
using System.CodeDom.Compiler;
|
||||
|
||||
@ -46,8 +45,8 @@ public class ExampleController : Controller
|
||||
{
|
||||
const string code = @"
|
||||
using System;
|
||||
public class MyClass
|
||||
{
|
||||
public class MyClass
|
||||
{
|
||||
public void MyMethod(string input)
|
||||
{
|
||||
Console.WriteLine(input);
|
||||
@ -63,7 +62,6 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -3,11 +3,9 @@
|
||||
The following code is vulnerable to arbitrary code execution because it compiles
|
||||
and runs HTTP data.
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
import org.codehaus.janino.ScriptEvaluator;
|
||||
|
||||
@ -17,14 +15,15 @@ public class ExampleController
|
||||
@GetMapping(value = "/")
|
||||
public void exec(@RequestParam("message") String message) throws IOException, InvocationTargetException {
|
||||
ScriptEvaluator se = new ScriptEvaluator();
|
||||
se.cook("System.out.println(\" + message \");"); // Noncompliant
|
||||
se.cook("System.out.println(\" + message \");");
|
||||
se.evaluate(null);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
import org.codehaus.janino.ScriptEvaluator;
|
||||
|
||||
@ -40,10 +39,8 @@ public class ExampleController
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
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 {} \;
|
||||
----
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -27,14 +25,15 @@ public class ExampleController : Controller
|
||||
{
|
||||
Process p = new Process();
|
||||
p.StartInfo.FileName = "/usr/bin/find";
|
||||
p.StartInfo.Arguments = "/some/folder -iname " + args; // Noncompliant
|
||||
p.StartInfo.Arguments = "/some/folder -iname " + args;
|
||||
p.Start();
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -49,15 +48,12 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
include::../../common/fix/introduction.adoc[]
|
||||
|
||||
|
||||
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
|
||||
called.
|
||||
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@Controller
|
||||
public class ExampleController
|
||||
@ -14,13 +12,14 @@ public class ExampleController
|
||||
@GetMapping(value = "/find")
|
||||
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
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@Controller
|
||||
public class ExampleController
|
||||
@ -33,12 +32,10 @@ public class ExampleController
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
include::../../common/fix/introduction.adoc[]
|
||||
|
||||
|
||||
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.
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
@Controller
|
||||
public class ExampleController
|
||||
@ -14,13 +12,14 @@ public class ExampleController
|
||||
@GetMapping(value = "/find")
|
||||
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
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
@Controller
|
||||
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++.
|
||||
|
||||
@ -41,6 +39,5 @@ public class ExampleController
|
||||
|
||||
include::../../common/fix/introduction.adoc[]
|
||||
|
||||
|
||||
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.
|
||||
|
@ -5,11 +5,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -20,13 +18,14 @@ public class ExampleController : Controller
|
||||
ZipArchiveEntry entry = entriesEnumerator.Current;
|
||||
string destinationPath = Path.Combine(TargetDirectory, entry.FullName);
|
||||
|
||||
entry.ExtractToFile(destinationPath); // Noncompliant
|
||||
entry.ExtractToFile(destinationPath);
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class ExampleController : Controller
|
||||
{
|
||||
@ -45,7 +44,6 @@ public class ExampleController : Controller
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -5,11 +5,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
public class Example {
|
||||
|
||||
@ -23,13 +21,14 @@ public class Example {
|
||||
|
||||
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
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
public class Example {
|
||||
|
||||
@ -51,7 +50,6 @@ public class Example {
|
||||
}
|
||||
}
|
||||
----
|
||||
|===
|
||||
|
||||
=== How does this work?
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
|
||||
include::../../common/fix/code-rationale.adoc[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,csharp]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
@ -18,16 +16,17 @@ public class ExampleController : Controller
|
||||
{
|
||||
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");
|
||||
}
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,csharp]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,csharp,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
using System.Web;
|
||||
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[]
|
||||
|
||||
[cols="a"]
|
||||
|===
|
||||
h| Non-compliant code example
|
||||
|
|
||||
[source,java]
|
||||
==== Non-compliant code example
|
||||
|
||||
[source,java,diff-id=1,diff-type=noncompliant]
|
||||
----
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
Optional<Cookie> cookieOpt = Arrays.stream(request.getCookies())
|
||||
@ -15,16 +13,17 @@ protected void doGet(HttpServletRequest request, HttpServletResponse response) t
|
||||
|
||||
if (!cookieOpt.isPresent()) {
|
||||
String cookie = request.getParameter("cookie");
|
||||
Cookie cookieObj = new Cookie("jsessionid", cookie); // Noncompliant
|
||||
Cookie cookieObj = new Cookie("jsessionid", cookie);
|
||||
response.addCookie(cookieObj);
|
||||
}
|
||||
|
||||
response.sendRedirect("/welcome.jsp");
|
||||
}
|
||||
----
|
||||
h| Compliant solution
|
||||
|
|
||||
[source,java]
|
||||
|
||||
==== Compliant solution
|
||||
|
||||
[source,java,diff-id=1,diff-type=compliant]
|
||||
----
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
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