diff --git a/docs/codeql/codeql-language-guides/customizing-library-models-for-java.rst b/docs/codeql/codeql-language-guides/customizing-library-models-for-java.rst index 37e1fb35450..707ae531fc1 100644 --- a/docs/codeql/codeql-language-guides/customizing-library-models-for-java.rst +++ b/docs/codeql/codeql-language-guides/customizing-library-models-for-java.rst @@ -349,6 +349,7 @@ The following sink kinds are supported: - **response-splitting**: A sink that can be used for HTTP response splitting, such as in calls to **HttpServletResponse.setHeader**. - **sql-injection**: A sink that can be used for SQL injection, such as in a **Statement.executeQuery** call. - **template-injection**: A sink that can be used for server side template injection, such as in a **Velocity.evaluate** call. +- **trust-boundary-violation**: A sink that can be used to cross a trust boundary, such as in a **HttpSession.setAttribute** call. - **url-redirection**: A sink that can be used to redirect the user to a malicious URL, such as in a **Response.temporaryRedirect** call. - **xpath-injection**: A sink that can be used for XPath injection, such as in a **XPath.evaluate** call. - **xslt-injection**: A sink that can be used for XSLT injection, such as in a **Transformer.transform** call. diff --git a/java/ql/lib/ext/generated/org.apache.commons.lang.model.yml b/java/ql/lib/ext/generated/org.apache.commons.lang.model.yml index 56f9c251388..d2cb3011569 100644 --- a/java/ql/lib/ext/generated/org.apache.commons.lang.model.yml +++ b/java/ql/lib/ext/generated/org.apache.commons.lang.model.yml @@ -1604,8 +1604,6 @@ extensions: - ["org.apache.commons.lang", "SerializationUtils", "serialize", "(Serializable,OutputStream)", "summary", "df-generated"] - ["org.apache.commons.lang", "StringEscapeUtils", "escapeCsv", "(String)", "summary", "df-generated"] - ["org.apache.commons.lang", "StringEscapeUtils", "escapeCsv", "(Writer,String)", "summary", "df-generated"] - - ["org.apache.commons.lang", "StringEscapeUtils", "escapeHtml", "(String)", "summary", "df-generated"] - - ["org.apache.commons.lang", "StringEscapeUtils", "escapeHtml", "(Writer,String)", "summary", "df-generated"] - ["org.apache.commons.lang", "StringEscapeUtils", "escapeJava", "(String)", "summary", "df-generated"] - ["org.apache.commons.lang", "StringEscapeUtils", "escapeJava", "(Writer,String)", "summary", "df-generated"] - ["org.apache.commons.lang", "StringEscapeUtils", "escapeJavaScript", "(String)", "summary", "df-generated"] diff --git a/java/ql/lib/ext/javax.servlet.http.model.yml b/java/ql/lib/ext/javax.servlet.http.model.yml index 6485ea22a2e..c2d76a2ea7a 100644 --- a/java/ql/lib/ext/javax.servlet.http.model.yml +++ b/java/ql/lib/ext/javax.servlet.http.model.yml @@ -26,6 +26,8 @@ extensions: - ["javax.servlet.http", "HttpServletResponse", False, "addHeader", "", "", "Argument[0..1]", "response-splitting", "manual"] - ["javax.servlet.http", "HttpServletResponse", False, "sendError", "(int,String)", "", "Argument[1]", "information-leak", "manual"] - ["javax.servlet.http", "HttpServletResponse", False, "setHeader", "", "", "Argument[0..1]", "response-splitting", "manual"] + - ["javax.servlet.http", "HttpSession", True, "putValue", "", "", "Argument[0..1]", "trust-boundary-violation", "manual"] + - ["javax.servlet.http", "HttpSession", True, "setAttribute", "", "", "Argument[0..1]", "trust-boundary-violation", "manual"] - addsTo: pack: codeql/java-all extensible: summaryModel diff --git a/java/ql/lib/ext/org.apache.commons.lang.model.yml b/java/ql/lib/ext/org.apache.commons.lang.model.yml new file mode 100644 index 00000000000..8dd3fd003f9 --- /dev/null +++ b/java/ql/lib/ext/org.apache.commons.lang.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["org.apache.commons.lang", "StringEscapeUtils", true, "escapeHtml", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] + - ["org.apache.commons.lang", "StringEscapeUtils", true, "escapeHtml", "(Writer,String)", "", "Argument[1]", "Argument[0]", "taint", "manual"] diff --git a/java/ql/lib/ext/org.apache.struts2.dispatcher.model.yml b/java/ql/lib/ext/org.apache.struts2.dispatcher.model.yml new file mode 100644 index 00000000000..c15ad1cb315 --- /dev/null +++ b/java/ql/lib/ext/org.apache.struts2.dispatcher.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.apache.struts2.dispatcher", "SessionMap", False, "put", "", "", "Argument[0..1]", "trust-boundary-violation", "manual"] diff --git a/java/ql/lib/ext/org.apache.struts2.interceptor.model.yml b/java/ql/lib/ext/org.apache.struts2.interceptor.model.yml new file mode 100644 index 00000000000..4b9ccb2e093 --- /dev/null +++ b/java/ql/lib/ext/org.apache.struts2.interceptor.model.yml @@ -0,0 +1,7 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["org.apache.struts2.interceptor", "SessionAware", False, "setSession", "", "", "Argument[0]", "trust-boundary-violation", "manual"] + - ["org.apache.struts2.interceptor", "SessionAware", False, "withSession", "", "", "Argument[0]", "trust-boundary-violation", "manual"] \ No newline at end of file diff --git a/java/ql/lib/ext/org.owasp.esapi.model.yml b/java/ql/lib/ext/org.owasp.esapi.model.yml new file mode 100644 index 00000000000..30578debe58 --- /dev/null +++ b/java/ql/lib/ext/org.owasp.esapi.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/java-all + extensible: summaryModel + data: + - ["org.owasp.esapi", "Encoder", true, "encodeForHTML", "(String)", "", "Argument[0]", "ReturnValue", "taint", "manual"] \ No newline at end of file diff --git a/java/ql/lib/ext/play.mvc.model.yml b/java/ql/lib/ext/play.mvc.model.yml index ba9a11c3f78..3a11ddd649d 100644 --- a/java/ql/lib/ext/play.mvc.model.yml +++ b/java/ql/lib/ext/play.mvc.model.yml @@ -16,6 +16,11 @@ extensions: - ["play.mvc", "Http$RequestHeader", True, "queryString", "", "", "ReturnValue", "remote", "manual"] - ["play.mvc", "Http$RequestHeader", True, "remoteAddress", "", "", "ReturnValue", "remote", "manual"] - ["play.mvc", "Http$RequestHeader", True, "uri", "", "", "ReturnValue", "remote", "manual"] + - addsTo: + pack: codeql/java-all + extensible: sinkModel + data: + - ["play.mvc", "Result", False, "addingToSession", "", "", "Argument[1..2]", "trust-boundary-violation", "manual"] - addsTo: pack: codeql/java-all extensible: summaryModel diff --git a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll index f2de51b2aab..9c195ecea8d 100644 --- a/java/ql/lib/semmle/code/java/frameworks/Servlets.qll +++ b/java/ql/lib/semmle/code/java/frameworks/Servlets.qll @@ -397,3 +397,8 @@ class GetServletResourceAsStreamMethod extends Method { this.hasName("getResourceAsStream") } } + +/** The interface `javax.servlet.http.HttpSession` */ +class HttpServletSession extends RefType { + HttpServletSession() { this.hasQualifiedName("javax.servlet.http", "HttpSession") } +} diff --git a/java/ql/lib/semmle/code/java/frameworks/owasp/Esapi.qll b/java/ql/lib/semmle/code/java/frameworks/owasp/Esapi.qll new file mode 100644 index 00000000000..19cabda7073 --- /dev/null +++ b/java/ql/lib/semmle/code/java/frameworks/owasp/Esapi.qll @@ -0,0 +1,40 @@ +/** Classes and predicates for reasoning about the `owasp.easpi` package. */ + +import java + +/** + * The `org.owasp.esapi.Validator` interface. + */ +class EsapiValidator extends RefType { + EsapiValidator() { this.hasQualifiedName("org.owasp.esapi", "Validator") } +} + +/** + * The methods of `org.owasp.esapi.Validator` which validate data. + */ +class EsapiIsValidMethod extends Method { + EsapiIsValidMethod() { + this.getDeclaringType() instanceof EsapiValidator and + this.hasName([ + "isValidCreditCard", "isValidDate", "isValidDirectoryPath", "isValidDouble", + "isValidFileContent", "isValidFileName", "isValidInput", "isValidInteger", + "isValidListItem", "isValidNumber", "isValidPrintable", "isValidRedirectLocation", + "isValidSafeHTML", "isValidURI" + ]) + } +} + +/** + * The methods of `org.owasp.esapi.Validator` which return validated data. + */ +class EsapiGetValidMethod extends Method { + EsapiGetValidMethod() { + this.getDeclaringType() instanceof EsapiValidator and + this.hasName([ + "getValidCreditCard", "getValidDate", "getValidDirectoryPath", "getValidDouble", + "getValidFileContent", "getValidFileName", "getValidInput", "getValidInteger", + "getValidListItem", "getValidNumber", "getValidPrintable", "getValidRedirectLocation", + "getValidSafeHTML", "getValidURI" + ]) + } +} diff --git a/java/ql/lib/semmle/code/java/security/TrustBoundaryViolationQuery.qll b/java/ql/lib/semmle/code/java/security/TrustBoundaryViolationQuery.qll new file mode 100644 index 00000000000..a89f24e6f1f --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/TrustBoundaryViolationQuery.qll @@ -0,0 +1,70 @@ +/** Provides classes and predicates to reason about trust boundary violations */ + +import java +private import semmle.code.java.dataflow.DataFlow +private import semmle.code.java.controlflow.Guards +private import semmle.code.java.dataflow.ExternalFlow +private import semmle.code.java.dataflow.FlowSources +private import semmle.code.java.frameworks.owasp.Esapi + +/** + * A source of data that crosses a trust boundary. + */ +abstract class TrustBoundaryViolationSource extends DataFlow::Node { } + +private class RemoteSource extends TrustBoundaryViolationSource instanceof RemoteFlowSource { } + +/** + * A sink for data that crosses a trust boundary. + */ +class TrustBoundaryViolationSink extends DataFlow::Node { + TrustBoundaryViolationSink() { sinkNode(this, "trust-boundary-violation") } +} + +/** + * A sanitizer for data that crosses a trust boundary. + */ +abstract class TrustBoundaryValidationSanitizer extends DataFlow::Node { } + +/** + * A node validated by an OWASP ESAPI validation method. + */ +private class EsapiValidatedInputSanitizer extends TrustBoundaryValidationSanitizer { + EsapiValidatedInputSanitizer() { + this = DataFlow::BarrierGuard::getABarrierNode() or + this.asExpr().(MethodAccess).getMethod() instanceof EsapiGetValidMethod + } +} + +/** + * Holds if `g` is a guard that checks that `e` is valid data according to an OWASP ESAPI validation method. + */ +private predicate esapiIsValidData(Guard g, Expr e, boolean branch) { + branch = true and + exists(MethodAccess ma | ma.getMethod() instanceof EsapiIsValidMethod | + g = ma and + e = ma.getArgument(1) + ) +} + +/** + * Taint tracking for data that crosses a trust boundary. + */ +module TrustBoundaryConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof TrustBoundaryViolationSource } + + predicate isBarrier(DataFlow::Node node) { + node instanceof TrustBoundaryValidationSanitizer or + node.getType() instanceof HttpServletSession or + node.getType() instanceof NumberType or + node.getType() instanceof PrimitiveType or + node.getType() instanceof BoxedType + } + + predicate isSink(DataFlow::Node sink) { sink instanceof TrustBoundaryViolationSink } +} + +/** + * Taint-tracking flow for values which cross a trust boundary. + */ +module TrustBoundaryFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-501/TrustBoundaryFixed.java b/java/ql/src/Security/CWE/CWE-501/TrustBoundaryFixed.java new file mode 100644 index 00000000000..50f14c0bc4f --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-501/TrustBoundaryFixed.java @@ -0,0 +1,8 @@ +public void doGet(HttpServletRequest request, HttpServletResponse response) { + String username = request.getParameter("username"); + + if (validator.isValidInput("HTTP parameter", username, "username", 20, false)) { + // GOOD: The input is sanitized before being written to the session. + request.getSession().setAttribute("username", username); + } +} \ No newline at end of file diff --git a/java/ql/src/Security/CWE/CWE-501/TrustBoundaryViolation.qhelp b/java/ql/src/Security/CWE/CWE-501/TrustBoundaryViolation.qhelp new file mode 100644 index 00000000000..f0eb5de2f7f --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-501/TrustBoundaryViolation.qhelp @@ -0,0 +1,48 @@ + + + +

+ A trust boundary violation occurs when a value is passed from a less trusted context to a more trusted context. +

+ +

+ For example, a value that is generated by a less trusted source, such as a user, may be passed to a more trusted + source, such as a system process. If the less trusted source is malicious, then the value may be crafted to + exploit the more trusted source. +

+ +

+ Trust boundary violations are often caused by a failure to validate input. For example, if a web application + accepts a cookie from a user, then the application should validate the cookie before using it. If the cookie is + not validated, then the user may be able to craft a malicious cookie that exploits the application. +

+
+ + +

+ To maintain a trust boundary, validate data from less trusted sources before use. +

+
+ + +

+ In the first (bad) example, the server accepts a parameter from the user, then uses it to set the username without validation. +

+ + +

+ In the second (good) example, the server validates the parameter from the user, then uses it to set the username. +

+ + +
+ + +
  • + Wikipedia: Trust boundary. +
  • +
    + +
    diff --git a/java/ql/src/Security/CWE/CWE-501/TrustBoundaryViolation.ql b/java/ql/src/Security/CWE/CWE-501/TrustBoundaryViolation.ql new file mode 100644 index 00000000000..9bc90f49c1f --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-501/TrustBoundaryViolation.ql @@ -0,0 +1,20 @@ +/** + * @id java/trust-boundary-violation + * @name Trust boundary violation + * @description Modifying the HTTP session attributes based on data from an untrusted source may violate a trust boundary. + * @kind path-problem + * @problem.severity error + * @security-severity 8.8 + * @precision medium + * @tags security + * external/cwe/cwe-501 + */ + +import java +import semmle.code.java.security.TrustBoundaryViolationQuery +import TrustBoundaryFlow::PathGraph + +from TrustBoundaryFlow::PathNode source, TrustBoundaryFlow::PathNode sink +where TrustBoundaryFlow::flowPath(source, sink) +select sink.getNode(), sink, source, + "This servlet reads data from a remote source and writes it to a session variable." diff --git a/java/ql/src/Security/CWE/CWE-501/TrustBoundaryVulnerable.java b/java/ql/src/Security/CWE/CWE-501/TrustBoundaryVulnerable.java new file mode 100644 index 00000000000..c6174b7113e --- /dev/null +++ b/java/ql/src/Security/CWE/CWE-501/TrustBoundaryVulnerable.java @@ -0,0 +1,6 @@ +public void doGet(HttpServletRequest request, HttpServletResponse response) { + String username = request.getParameter("username"); + + // BAD: The input is written to the session without being sanitized. + request.getSession().setAttribute("username", username); +} \ No newline at end of file diff --git a/java/ql/src/change-notes/2023-07-25-trust-boundary-violation-query.md b/java/ql/src/change-notes/2023-07-25-trust-boundary-violation-query.md new file mode 100644 index 00000000000..802e367bf10 --- /dev/null +++ b/java/ql/src/change-notes/2023-07-25-trust-boundary-violation-query.md @@ -0,0 +1,5 @@ +--- +category: newQuery +--- +* Added the `java/trust-boundary-violation` query to detect trust boundary violations between HTTP requests and the HTTP session. Also added the `trust-boundary-violation` sink kind for sinks which may cross a trust boundary, such as calls to the `HttpSession#setAttribute` method. + diff --git a/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.expected b/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.expected new file mode 100644 index 00000000000..48de9172b36 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.expected @@ -0,0 +1,2 @@ +failures +testFailures diff --git a/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.java b/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.java new file mode 100644 index 00000000000..dc45f7e6604 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.java @@ -0,0 +1,35 @@ +import java.io.IOException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.owasp.esapi.Validator; + +public class TrustBoundaryViolations extends HttpServlet { + Validator validator; + + public void doGet(HttpServletRequest request, HttpServletResponse response) { + String input = request.getParameter("input"); + + // BAD: The input is written to the session without being sanitized. + request.getSession().setAttribute("input", input); // $ hasTaintFlow + + String input2 = request.getParameter("input2"); + + try { + String sanitized = validator.getValidInput("HTTP parameter", input2, "HTTPParameterValue", 100, false); + // GOOD: The input is sanitized before being written to the session. + request.getSession().setAttribute("input2", sanitized); + + } catch (Exception e) { + } + + try { + String input3 = request.getParameter("input3"); + if (validator.isValidInput("HTTP parameter", input3, "HTTPParameterValue", 100, false)) { + // GOOD: The input is sanitized before being written to the session. + request.getSession().setAttribute("input3", input3); + } + } catch (Exception e) { + } + } +} diff --git a/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.ql b/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.ql new file mode 100644 index 00000000000..26a9b4a7308 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-501/TrustBoundaryViolations.ql @@ -0,0 +1,4 @@ +import java +import semmle.code.java.security.TrustBoundaryViolationQuery +import TestUtilities.InlineFlowTest +import TaintFlowTest diff --git a/java/ql/test/query-tests/security/CWE-501/options b/java/ql/test/query-tests/security/CWE-501/options new file mode 100644 index 00000000000..37d627da7e8 --- /dev/null +++ b/java/ql/test/query-tests/security/CWE-501/options @@ -0,0 +1 @@ +//semmle-extractor-options: --javac-args -cp ${testdir}/../../../stubs/esapi-2.0.1:${testdir}/../../../stubs/javax-servlet-2.5 diff --git a/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/ValidationErrorList.java b/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/ValidationErrorList.java new file mode 100644 index 00000000000..ae56481a974 --- /dev/null +++ b/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/ValidationErrorList.java @@ -0,0 +1,5 @@ +package org.owasp.esapi; + +public class ValidationErrorList { + +} diff --git a/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/Validator.java b/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/Validator.java new file mode 100644 index 00000000000..8bee29c1c38 --- /dev/null +++ b/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/Validator.java @@ -0,0 +1,224 @@ +package org.owasp.esapi; + +import java.io.File; +import java.io.InputStream; +import java.net.URI; +import java.text.DateFormat; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import javax.servlet.http.HttpServletRequest; + +import org.owasp.esapi.errors.IntrusionException; +import org.owasp.esapi.errors.ValidationException; + +public interface Validator { + + boolean isValidInput(String context, String input, String type, int maxLength, boolean allowNull) + throws IntrusionException; + + boolean isValidInput(String context, String input, String type, int maxLength, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidInput(String context, String input, String type, int maxLength, boolean allowNull, + boolean canonicalize) throws IntrusionException; + + boolean isValidInput(String context, String input, String type, int maxLength, boolean allowNull, + boolean canonicalize, ValidationErrorList errorList) throws IntrusionException; + + String getValidInput(String context, String input, String type, int maxLength, boolean allowNull) + throws ValidationException, IntrusionException; + + String getValidInput(String context, String input, String type, int maxLength, boolean allowNull, + boolean canonicalize) throws ValidationException, IntrusionException; + + String getValidInput(String context, String input, String type, int maxLength, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + String getValidInput(String context, String input, String type, int maxLength, boolean allowNull, + boolean canonicalize, ValidationErrorList errorList) throws IntrusionException; + + boolean isValidDate(String context, String input, DateFormat format, boolean allowNull) throws IntrusionException; + + boolean isValidDate(String context, String input, DateFormat format, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + Date getValidDate(String context, String input, DateFormat format, boolean allowNull) + throws ValidationException, IntrusionException; + + Date getValidDate(String context, String input, DateFormat format, boolean allowNull, ValidationErrorList errorList) + throws IntrusionException; + + boolean isValidSafeHTML(String context, String input, int maxLength, boolean allowNull) throws IntrusionException; + + boolean isValidSafeHTML(String context, String input, int maxLength, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + String getValidSafeHTML(String context, String input, int maxLength, boolean allowNull) + throws ValidationException, IntrusionException; + + String getValidSafeHTML(String context, String input, int maxLength, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidCreditCard(String context, String input, boolean allowNull) throws IntrusionException; + + boolean isValidCreditCard(String context, String input, boolean allowNull, ValidationErrorList errorList) + throws IntrusionException; + + String getValidCreditCard(String context, String input, boolean allowNull) + throws ValidationException, IntrusionException; + + String getValidCreditCard(String context, String input, boolean allowNull, ValidationErrorList errorList) + throws IntrusionException; + + boolean isValidDirectoryPath(String context, String input, File parent, boolean allowNull) + throws IntrusionException; + + boolean isValidDirectoryPath(String context, String input, File parent, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + String getValidDirectoryPath(String context, String input, File parent, boolean allowNull) + throws ValidationException, IntrusionException; + + String getValidDirectoryPath(String context, String input, File parent, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidFileName(String context, String input, boolean allowNull) throws IntrusionException; + + boolean isValidFileName(String context, String input, boolean allowNull, ValidationErrorList errorList) + throws IntrusionException; + + boolean isValidFileName(String context, String input, List allowedExtensions, boolean allowNull) + throws IntrusionException; + + boolean isValidFileName(String context, String input, List allowedExtensions, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + String getValidFileName(String context, String input, List allowedExtensions, boolean allowNull) + throws ValidationException, IntrusionException; + + String getValidFileName(String context, String input, List allowedExtensions, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidNumber(String context, String input, long minValue, long maxValue, boolean allowNull) + throws IntrusionException; + + boolean isValidNumber(String context, String input, long minValue, long maxValue, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + Double getValidNumber(String context, String input, long minValue, long maxValue, boolean allowNull) + throws ValidationException, IntrusionException; + + Double getValidNumber(String context, String input, long minValue, long maxValue, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidInteger(String context, String input, int minValue, int maxValue, boolean allowNull) + throws IntrusionException; + + boolean isValidInteger(String context, String input, int minValue, int maxValue, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + Integer getValidInteger(String context, String input, int minValue, int maxValue, boolean allowNull) + throws ValidationException, IntrusionException; + + Integer getValidInteger(String context, String input, int minValue, int maxValue, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidDouble(String context, String input, double minValue, double maxValue, boolean allowNull) + throws IntrusionException; + + boolean isValidDouble(String context, String input, double minValue, double maxValue, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + Double getValidDouble(String context, String input, double minValue, double maxValue, boolean allowNull) + throws ValidationException, IntrusionException; + + Double getValidDouble(String context, String input, double minValue, double maxValue, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidFileContent(String context, byte[] input, int maxBytes, boolean allowNull) throws IntrusionException; + + boolean isValidFileContent(String context, byte[] input, int maxBytes, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + byte[] getValidFileContent(String context, byte[] input, int maxBytes, boolean allowNull) + throws ValidationException, IntrusionException; + + byte[] getValidFileContent(String context, byte[] input, int maxBytes, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidFileUpload(String context, String filepath, String filename, File parent, byte[] content, + int maxBytes, boolean allowNull) throws IntrusionException; + + boolean isValidFileUpload(String context, String filepath, String filename, File parent, byte[] content, + int maxBytes, boolean allowNull, ValidationErrorList errorList) throws IntrusionException; + + void assertValidFileUpload(String context, String filepath, String filename, File parent, byte[] content, + int maxBytes, List allowedExtensions, boolean allowNull) + throws ValidationException, IntrusionException; + + void assertValidFileUpload(String context, String filepath, String filename, File parent, byte[] content, + int maxBytes, List allowedExtensions, boolean allowNull, ValidationErrorList errorList) + throws IntrusionException; + + boolean isValidListItem(String context, String input, List list) throws IntrusionException; + + boolean isValidListItem(String context, String input, List list, ValidationErrorList errorList) + throws IntrusionException; + + String getValidListItem(String context, String input, List list) + throws ValidationException, IntrusionException; + + String getValidListItem(String context, String input, List list, ValidationErrorList errorList) + throws IntrusionException; + + boolean isValidHTTPRequestParameterSet(String context, HttpServletRequest request, Set required, + Set optional) throws IntrusionException; + + boolean isValidHTTPRequestParameterSet(String context, HttpServletRequest request, Set required, + Set optional, ValidationErrorList errorList) throws IntrusionException; + + void assertValidHTTPRequestParameterSet(String context, HttpServletRequest request, Set required, + Set optional) throws ValidationException, IntrusionException; + + void assertValidHTTPRequestParameterSet(String context, HttpServletRequest request, Set required, + Set optional, ValidationErrorList errorList) throws IntrusionException; + + boolean isValidPrintable(String context, char[] input, int maxLength, boolean allowNull) throws IntrusionException; + + boolean isValidPrintable(String context, char[] input, int maxLength, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + char[] getValidPrintable(String context, char[] input, int maxLength, boolean allowNull) throws ValidationException; + + char[] getValidPrintable(String context, char[] input, int maxLength, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidPrintable(String context, String input, int maxLength, boolean allowNull) throws IntrusionException; + + boolean isValidPrintable(String context, String input, int maxLength, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + String getValidPrintable(String context, String input, int maxLength, boolean allowNull) throws ValidationException; + + String getValidPrintable(String context, String input, int maxLength, boolean allowNull, + ValidationErrorList errorList) throws IntrusionException; + + boolean isValidRedirectLocation(String context, String input, boolean allowNull); + + boolean isValidRedirectLocation(String context, String input, boolean allowNull, ValidationErrorList errorList); + + String getValidRedirectLocation(String context, String input, boolean allowNull) + throws ValidationException, IntrusionException; + + String getValidRedirectLocation(String context, String input, boolean allowNull, ValidationErrorList errorList) + throws IntrusionException; + + String safeReadLine(InputStream inputStream, int maxLength) throws ValidationException; + + boolean isValidURI(String context, String input, boolean allowNull); + + URI getRfcCompliantURI(String input); + +} \ No newline at end of file diff --git a/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/errors/IntrusionException.java b/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/errors/IntrusionException.java new file mode 100644 index 00000000000..2ecbcd6c449 --- /dev/null +++ b/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/errors/IntrusionException.java @@ -0,0 +1,5 @@ +package org.owasp.esapi.errors; + +public class IntrusionException extends Exception { + +} diff --git a/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/errors/ValidationException.java b/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/errors/ValidationException.java new file mode 100644 index 00000000000..d8158b984f9 --- /dev/null +++ b/java/ql/test/stubs/esapi-2.0.1/org/owasp/esapi/errors/ValidationException.java @@ -0,0 +1,5 @@ +package org.owasp.esapi.errors; + +public class ValidationException extends Exception { + +} diff --git a/shared/mad/codeql/mad/ModelValidation.qll b/shared/mad/codeql/mad/ModelValidation.qll index d5108c2eeec..7225c2bc1ee 100644 --- a/shared/mad/codeql/mad/ModelValidation.qll +++ b/shared/mad/codeql/mad/ModelValidation.qll @@ -33,7 +33,7 @@ module KindValidation { "bean-validation", "fragment-injection", "groovy-injection", "hostname-verification", "information-leak", "intent-redirection", "jexl-injection", "jndi-injection", "mvel-injection", "ognl-injection", "pending-intents", "response-splitting", - "template-injection", "xpath-injection", "xslt-injection", + "trust-boundary-violation", "template-injection", "xpath-injection", "xslt-injection", // JavaScript-only currently, but may be shared in the future "mongodb.sink", "nosql-injection", "unsafe-deserialization", // Swift-only currently, but may be shared in the future