mirror of
https://github.com/github/codeql.git
synced 2026-06-18 19:31:11 +02:00
Merge branch 'main' into java/UnsafeDeserialization
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
* @kind path-problem
|
||||
* @precision low
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @tags security external/cwe/cwe-20
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Accessing paths influenced by users can allow an attacker to access unexpected resources.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.4
|
||||
* @precision high
|
||||
* @id java/path-injection
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Accessing paths influenced by users can allow an attacker to access unexpected resources.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 6.4
|
||||
* @precision medium
|
||||
* @id java/path-injection-local
|
||||
* @tags security
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* @kind path-problem
|
||||
* @id java/zipslip
|
||||
* @problem.severity error
|
||||
* @security-severity 6.4
|
||||
* @precision high
|
||||
* @tags security
|
||||
* external/cwe/cwe-022
|
||||
@@ -17,6 +18,7 @@ import semmle.code.java.dataflow.SSA
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import DataFlow
|
||||
import PathGraph
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* A method that returns the name of an archive entry.
|
||||
@@ -33,34 +35,6 @@ class ArchiveEntryNameMethod extends Method {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that will be treated as the destination of a write.
|
||||
*/
|
||||
class WrittenFileName extends Expr {
|
||||
WrittenFileName() {
|
||||
// Constructors that write to their first argument.
|
||||
exists(ConstructorCall ctr | this = ctr.getArgument(0) |
|
||||
exists(Class c | ctr.getConstructor() = c.getAConstructor() |
|
||||
c.hasQualifiedName("java.io", "FileOutputStream") or
|
||||
c.hasQualifiedName("java.io", "RandomAccessFile") or
|
||||
c.hasQualifiedName("java.io", "FileWriter")
|
||||
)
|
||||
)
|
||||
or
|
||||
// Methods that write to their n'th argument
|
||||
exists(MethodAccess call, int n | this = call.getArgument(n) |
|
||||
call.getMethod().getDeclaringType().hasQualifiedName("java.nio.file", "Files") and
|
||||
(
|
||||
call.getMethod().getName().regexpMatch("new.*Reader|newOutputStream|create.*") and n = 0
|
||||
or
|
||||
call.getMethod().hasName("copy") and n = 1
|
||||
or
|
||||
call.getMethod().hasName("move") and n = 1
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `n1` to `n2` is a dataflow step that converts between `String`,
|
||||
* `File`, and `Path`.
|
||||
@@ -151,7 +125,7 @@ class ZipSlipConfiguration extends TaintTracking::Configuration {
|
||||
source.asExpr().(MethodAccess).getMethod() instanceof ArchiveEntryNameMethod
|
||||
}
|
||||
|
||||
override predicate isSink(Node sink) { sink.asExpr() instanceof WrittenFileName }
|
||||
override predicate isSink(Node sink) { sink instanceof FileCreationSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(Node n1, Node n2) {
|
||||
filePathStep(n1, n2) or fileTaintStep(n1, n2)
|
||||
@@ -173,6 +147,13 @@ class ZipSlipConfiguration extends TaintTracking::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink that represents a file creation, such as a file write, copy or move operation.
|
||||
*/
|
||||
private class FileCreationSink extends DataFlow::Node {
|
||||
FileCreationSink() { sinkNode(this, "create-file") }
|
||||
}
|
||||
|
||||
from PathNode source, PathNode sink
|
||||
where any(ZipSlipConfiguration c).hasFlowPath(source, sink)
|
||||
select source.getNode(), source, sink,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* malicious changes in the PATH environment variable.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/relative-path-command
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* changes in the strings.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/command-line-injection
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* changes in the strings.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/command-line-injection-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* insertion of special characters in the strings.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/concatenated-command-line
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* allows for a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 2.9
|
||||
* @precision high
|
||||
* @id java/xss
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* allows for a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 2.9
|
||||
* @precision medium
|
||||
* @id java/xss-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.4
|
||||
* @precision high
|
||||
* @id java/sql-injection
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 6.4
|
||||
* @precision medium
|
||||
* @id java/sql-injection-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* characters is vulnerable to insertion of malicious code.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.4
|
||||
* @precision high
|
||||
* @id java/concatenated-sql-query
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* malicious LDAP code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/ldap-injection
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description User-controlled data may be evaluated as a Java EL expression, leading to arbitrary code execution.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 10.0
|
||||
* @precision high
|
||||
* @id java/insecure-bean-validation
|
||||
* @tags security
|
||||
@@ -13,6 +14,7 @@ import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* A message interpolator Type that perform Expression Language (EL) evaluations
|
||||
@@ -50,19 +52,6 @@ class SetMessageInterpolatorCall extends MethodAccess {
|
||||
predicate isSafe() { not this.getAnArgument().getType() instanceof ELMessageInterpolatorType }
|
||||
}
|
||||
|
||||
/**
|
||||
* A method named `buildConstraintViolationWithTemplate` declared on a subtype
|
||||
* of `javax.validation.ConstraintValidatorContext`.
|
||||
*/
|
||||
class BuildConstraintViolationWithTemplateMethod extends Method {
|
||||
BuildConstraintViolationWithTemplateMethod() {
|
||||
this.getDeclaringType()
|
||||
.getASupertype*()
|
||||
.hasQualifiedName("javax.validation", "ConstraintValidatorContext") and
|
||||
this.hasName("buildConstraintViolationWithTemplate")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Taint tracking BeanValidationConfiguration describing the flow of data from user input
|
||||
* to the argument of a method that builds constraint error messages.
|
||||
@@ -72,12 +61,15 @@ class BeanValidationConfig extends TaintTracking::Configuration {
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof BuildConstraintViolationWithTemplateMethod and
|
||||
sink.asExpr() = ma.getArgument(0)
|
||||
)
|
||||
}
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof BeanValidationSink }
|
||||
}
|
||||
|
||||
/**
|
||||
* A bean validation sink, such as method `buildConstraintViolationWithTemplate`
|
||||
* declared on a subtype of `javax.validation.ConstraintValidatorContext`.
|
||||
*/
|
||||
private class BeanValidationSink extends DataFlow::Node {
|
||||
BeanValidationSink() { sinkNode(this, "bean-validation") }
|
||||
}
|
||||
|
||||
from BeanValidationConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
|
||||
63
java/ql/src/Security/CWE/CWE-094/JexlInjection.qhelp
Normal file
63
java/ql/src/Security/CWE/CWE-094/JexlInjection.qhelp
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Java EXpression Language (JEXL) is a simple expression language
|
||||
provided by the Apache Commons JEXL library.
|
||||
The syntax is close to a mix of ECMAScript and shell-script.
|
||||
The language allows invocation of methods available in the JVM.
|
||||
If a JEXL expression is built using attacker-controlled data,
|
||||
and then evaluated, then it may allow the attacker to run arbitrary code.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
It is generally recommended to avoid using untrusted input in a JEXL expression.
|
||||
If it is not possible, JEXL expressions should be run in a sandbox that allows accessing only
|
||||
explicitly allowed classes.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
The following example uses untrusted data to build and run a JEXL expression.
|
||||
</p>
|
||||
<sample src="UnsafeJexlExpressionEvaluation.java" />
|
||||
|
||||
<p>
|
||||
The next example shows how an untrusted JEXL expression can be run
|
||||
in a sandbox that allows accessing only methods in the <code>java.lang.Math</code> class.
|
||||
The sandbox is implemented using <code>JexlSandbox</code> class that is provided by
|
||||
Apache Commons JEXL 3.
|
||||
</p>
|
||||
<sample src="SaferJexlExpressionEvaluationWithSandbox.java" />
|
||||
|
||||
<p>
|
||||
The next example shows another way how a sandbox can be implemented.
|
||||
It uses a custom implementation of <code>JexlUberspect</code>
|
||||
that checks if callees are instances of allowed classes.
|
||||
</p>
|
||||
<sample src="SaferJexlExpressionEvaluationWithUberspectSandbox.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Apache Commons JEXL:
|
||||
<a href="https://commons.apache.org/proper/commons-jexl/">Project page</a>.
|
||||
</li>
|
||||
<li>
|
||||
Apache Commons JEXL documentation:
|
||||
<a href="https://commons.apache.org/proper/commons-jexl/javadocs/apidocs-2.1.1/">JEXL 2.1.1 API</a>.
|
||||
</li>
|
||||
<li>
|
||||
Apache Commons JEXL documentation:
|
||||
<a href="https://commons.apache.org/proper/commons-jexl/apidocs/index.html">JEXL 3.1 API</a>.
|
||||
</li>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://owasp.org/www-community/vulnerabilities/Expression_Language_Injection">Expression Language Injection</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
38
java/ql/src/Security/CWE/CWE-094/JexlInjection.ql
Normal file
38
java/ql/src/Security/CWE/CWE-094/JexlInjection.ql
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* @name Expression language injection (JEXL)
|
||||
* @description Evaluation of a user-controlled JEXL expression
|
||||
* may lead to arbitrary code execution.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 10.0
|
||||
* @precision high
|
||||
* @id java/jexl-expression-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-094
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.JexlInjection
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for unsafe user input
|
||||
* that is used to construct and evaluate a JEXL expression.
|
||||
* It supports both JEXL 2 and 3.
|
||||
*/
|
||||
class JexlInjectionConfig extends TaintTracking::Configuration {
|
||||
JexlInjectionConfig() { this = "JexlInjectionConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof JexlEvaluationSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
any(JexlInjectionAdditionalTaintStep c).step(node1, node2)
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, JexlInjectionConfig conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "JEXL injection from $@.", source.getNode(), "this user input"
|
||||
@@ -0,0 +1,14 @@
|
||||
public void evaluate(Socket socket) throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(socket.getInputStream()))) {
|
||||
|
||||
JexlSandbox onlyMath = new JexlSandbox(false);
|
||||
onlyMath.white("java.lang.Math");
|
||||
JexlEngine jexl = new JexlBuilder().sandbox(onlyMath).create();
|
||||
|
||||
String input = reader.readLine();
|
||||
JexlExpression expression = jexl.createExpression(input);
|
||||
JexlContext context = new MapContext();
|
||||
expression.evaluate(context);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
public void evaluate(Socket socket) throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(socket.getInputStream()))) {
|
||||
|
||||
JexlUberspect sandbox = new JexlUberspectSandbox();
|
||||
JexlEngine jexl = new JexlBuilder().uberspect(sandbox).create();
|
||||
|
||||
String input = reader.readLine();
|
||||
JexlExpression expression = jexl.createExpression(input);
|
||||
JexlContext context = new MapContext();
|
||||
expression.evaluate(context);
|
||||
}
|
||||
|
||||
private static class JexlUberspectSandbox implements JexlUberspect {
|
||||
|
||||
private static final List<String> ALLOWED_CLASSES =
|
||||
Arrays.asList("java.lang.Math", "java.util.Random");
|
||||
|
||||
private final JexlUberspect uberspect = new JexlBuilder().create().getUberspect();
|
||||
|
||||
private void checkAccess(Object obj) {
|
||||
if (!ALLOWED_CLASSES.contains(obj.getClass().getCanonicalName())) {
|
||||
throw new AccessControlException("Not allowed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JexlMethod getMethod(Object obj, String method, Object... args) {
|
||||
checkAccess(obj);
|
||||
return uberspect.getMethod(obj, method, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PropertyResolver> getResolvers(JexlOperator op, Object obj) {
|
||||
checkAccess(obj);
|
||||
return uberspect.getResolvers(op, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setClassLoader(ClassLoader loader) {
|
||||
uberspect.setClassLoader(loader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVersion() {
|
||||
return uberspect.getVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JexlMethod getConstructor(Object obj, Object... args) {
|
||||
checkAccess(obj);
|
||||
return uberspect.getConstructor(obj, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JexlPropertyGet getPropertyGet(Object obj, Object identifier) {
|
||||
checkAccess(obj);
|
||||
return uberspect.getPropertyGet(obj, identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JexlPropertyGet getPropertyGet(List<PropertyResolver> resolvers, Object obj, Object identifier) {
|
||||
checkAccess(obj);
|
||||
return uberspect.getPropertyGet(resolvers, obj, identifier);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JexlPropertySet getPropertySet(Object obj, Object identifier, Object arg) {
|
||||
checkAccess(obj);
|
||||
return uberspect.getPropertySet(obj, identifier, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JexlPropertySet getPropertySet(List<PropertyResolver> resolvers, Object obj, Object identifier, Object arg) {
|
||||
checkAccess(obj);
|
||||
return uberspect.getPropertySet(resolvers, obj, identifier, arg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<?> getIterator(Object obj) {
|
||||
checkAccess(obj);
|
||||
return uberspect.getIterator(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JexlArithmetic.Uberspect getArithmetic(JexlArithmetic arithmetic) {
|
||||
return uberspect.getArithmetic(arithmetic);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
public void evaluate(Socket socket) throws IOException {
|
||||
try (BufferedReader reader = new BufferedReader(
|
||||
new InputStreamReader(socket.getInputStream()))) {
|
||||
|
||||
String input = reader.readLine();
|
||||
JexlEngine jexl = new JexlBuilder().create();
|
||||
JexlExpression expression = jexl.createExpression(input);
|
||||
JexlContext context = new MapContext();
|
||||
expression.evaluate(context);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using a deprecated artifact repository may eventually give attackers access for a supply chain attack.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.5
|
||||
* @precision very-high
|
||||
* @id java/maven/dependency-upon-bintray
|
||||
* @tags security
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* an HTTP header.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 3.6
|
||||
* @precision high
|
||||
* @id java/netty-http-response-splitting
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* makes code vulnerable to attack by header splitting.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 3.6
|
||||
* @precision high
|
||||
* @id java/http-response-splitting
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* makes code vulnerable to attack by header splitting.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 3.6
|
||||
* @precision medium
|
||||
* @id java/http-response-splitting-local
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using unvalidated external input as the argument to a construction of an array can lead to index out of bound exceptions.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-construction
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* a construction of an array can lead to index out of bound exceptions.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-construction-code-specified
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* a construction of an array can lead to index out of bound exceptions.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-construction-local
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using external input as an index to an array, without proper validation, can lead to index out of bound exceptions.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-index
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* proper validation, can lead to index out of bound exceptions.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-index-code-specified
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* proper validation, can lead to index out of bound exceptions.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-index-local
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using external input in format strings can lead to exceptions or information leaks.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.9
|
||||
* @precision high
|
||||
* @id java/tainted-format-string
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using external input in format strings can lead to exceptions or information leaks.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 6.9
|
||||
* @precision medium
|
||||
* @id java/tainted-format-string-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* overflows.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/tainted-arithmetic
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* overflows.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/tainted-arithmetic-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* overflows.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/uncontrolled-arithmetic
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* is then used in an arithmetic expression, this may result in an overflow.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/extreme-value-arithmetic
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* to behave unexpectedly.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/comparison-with-wider-type
|
||||
* @tags reliability
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* that are useful to an attacker for developing a subsequent exploit.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 3.6
|
||||
* @precision high
|
||||
* @id java/stack-trace-exposure
|
||||
* @tags security
|
||||
@@ -15,7 +16,7 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.security.XSS
|
||||
import semmle.code.java.security.InformationLeak
|
||||
|
||||
/**
|
||||
* One of the `printStackTrace()` overloads on `Throwable`.
|
||||
@@ -79,19 +80,18 @@ predicate stackTraceExpr(Expr exception, MethodAccess stackTraceString) {
|
||||
printStackCall.getAnArgument() = printWriter and
|
||||
printStackCall.getQualifier() = exception and
|
||||
stackTraceString.getQualifier() = stringWriterVar.getAnAccess() and
|
||||
stackTraceString.getMethod().getName() = "toString" and
|
||||
stackTraceString.getMethod().getNumberOfParameters() = 0
|
||||
stackTraceString.getMethod() instanceof ToStringMethod
|
||||
)
|
||||
}
|
||||
|
||||
class StackTraceStringToXssSinkFlowConfig extends TaintTracking::Configuration {
|
||||
StackTraceStringToXssSinkFlowConfig() {
|
||||
this = "StackTraceExposure::StackTraceStringToXssSinkFlowConfig"
|
||||
class StackTraceStringToHttpResponseSinkFlowConfig extends TaintTracking::Configuration {
|
||||
StackTraceStringToHttpResponseSinkFlowConfig() {
|
||||
this = "StackTraceExposure::StackTraceStringToHttpResponseSinkFlowConfig"
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { stackTraceExpr(_, src.asExpr()) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,8 +106,8 @@ predicate printsStackExternally(MethodAccess call, Expr stackTrace) {
|
||||
/**
|
||||
* A stringified stack trace flows to an external sink.
|
||||
*/
|
||||
predicate stringifiedStackFlowsExternally(XssSink externalExpr, Expr stackTrace) {
|
||||
exists(MethodAccess stackTraceString, StackTraceStringToXssSinkFlowConfig conf |
|
||||
predicate stringifiedStackFlowsExternally(DataFlow::Node externalExpr, Expr stackTrace) {
|
||||
exists(MethodAccess stackTraceString, StackTraceStringToHttpResponseSinkFlowConfig conf |
|
||||
stackTraceExpr(stackTrace, stackTraceString) and
|
||||
conf.hasFlow(DataFlow::exprNode(stackTraceString), externalExpr)
|
||||
)
|
||||
@@ -124,21 +124,21 @@ class GetMessageFlowSource extends MethodAccess {
|
||||
}
|
||||
}
|
||||
|
||||
class GetMessageFlowSourceToXssSinkFlowConfig extends TaintTracking::Configuration {
|
||||
GetMessageFlowSourceToXssSinkFlowConfig() {
|
||||
this = "StackTraceExposure::GetMessageFlowSourceToXssSinkFlowConfig"
|
||||
class GetMessageFlowSourceToHttpResponseSinkFlowConfig extends TaintTracking::Configuration {
|
||||
GetMessageFlowSourceToHttpResponseSinkFlowConfig() {
|
||||
this = "StackTraceExposure::GetMessageFlowSourceToHttpResponseSinkFlowConfig"
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof GetMessageFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to `getMessage()` that then flows to a servlet response.
|
||||
*/
|
||||
predicate getMessageFlowsExternally(XssSink externalExpr, GetMessageFlowSource getMessage) {
|
||||
any(GetMessageFlowSourceToXssSinkFlowConfig conf)
|
||||
predicate getMessageFlowsExternally(DataFlow::Node externalExpr, GetMessageFlowSource getMessage) {
|
||||
any(GetMessageFlowSourceToHttpResponseSinkFlowConfig conf)
|
||||
.hasFlow(DataFlow::exprNode(getMessage), externalExpr)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Marking a certificate as valid for a host without checking the certificate hostname allows an attacker to perform a machine-in-the-middle attack.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 4.9
|
||||
* @precision high
|
||||
* @id java/unsafe-hostname-verification
|
||||
* @tags security
|
||||
@@ -15,6 +16,7 @@ import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.Encryption
|
||||
import DataFlow::PathGraph
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
/**
|
||||
* Holds if `m` always returns `true` ignoring any exceptional flow.
|
||||
@@ -49,14 +51,7 @@ class TrustAllHostnameVerifierConfiguration extends DataFlow::Configuration {
|
||||
source.asExpr().(ClassInstanceExpr).getConstructedType() instanceof TrustAllHostnameVerifier
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma, Method m |
|
||||
(m instanceof SetDefaultHostnameVerifierMethod or m instanceof SetHostnameVerifierMethod) and
|
||||
ma.getMethod() = m
|
||||
|
|
||||
ma.getArgument(0) = sink.asExpr()
|
||||
)
|
||||
}
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof HostnameVerifierSink }
|
||||
|
||||
override predicate isBarrier(DataFlow::Node barrier) {
|
||||
// ignore nodes that are in functions that intentionally disable hostname verification
|
||||
@@ -84,6 +79,13 @@ class TrustAllHostnameVerifierConfiguration extends DataFlow::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink that sets the `HostnameVerifier` on `HttpsURLConnection`.
|
||||
*/
|
||||
private class HostnameVerifierSink extends DataFlow::Node {
|
||||
HostnameVerifierSink() { sinkNode(this, "set-hostname-verifier") }
|
||||
}
|
||||
|
||||
bindingset[result]
|
||||
private string getAFlagName() {
|
||||
result
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Storing sensitive information in cleartext can expose it to an attacker.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/cleartext-storage-in-class
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Storing sensitive information in cleartext can expose it to an attacker.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 2.9
|
||||
* @precision high
|
||||
* @id java/cleartext-storage-in-cookie
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Storing sensitive information in cleartext can expose it to an attacker.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 6.4
|
||||
* @precision medium
|
||||
* @id java/cleartext-storage-in-properties
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Non-HTTPS connections can be intercepted by third parties.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.2
|
||||
* @precision medium
|
||||
* @id java/non-https-url
|
||||
* @tags security
|
||||
@@ -13,9 +14,10 @@ import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.frameworks.Networking
|
||||
import DataFlow::PathGraph
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
class HTTPString extends StringLiteral {
|
||||
HTTPString() {
|
||||
class HttpString extends StringLiteral {
|
||||
HttpString() {
|
||||
// Avoid matching "https" here.
|
||||
exists(string s | this.getRepresentedString() = s |
|
||||
(
|
||||
@@ -30,26 +32,12 @@ class HTTPString extends StringLiteral {
|
||||
}
|
||||
}
|
||||
|
||||
class URLOpenMethod extends Method {
|
||||
URLOpenMethod() {
|
||||
this.getDeclaringType().getQualifiedName() = "java.net.URL" and
|
||||
(
|
||||
this.getName() = "openConnection" or
|
||||
this.getName() = "openStream"
|
||||
)
|
||||
}
|
||||
}
|
||||
class HttpStringToUrlOpenMethodFlowConfig extends TaintTracking::Configuration {
|
||||
HttpStringToUrlOpenMethodFlowConfig() { this = "HttpsUrls::HttpStringToUrlOpenMethodFlowConfig" }
|
||||
|
||||
class HTTPStringToURLOpenMethodFlowConfig extends TaintTracking::Configuration {
|
||||
HTTPStringToURLOpenMethodFlowConfig() { this = "HttpsUrls::HTTPStringToURLOpenMethodFlowConfig" }
|
||||
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof HttpString }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof HTTPString }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess m |
|
||||
sink.asExpr() = m.getQualifier() and m.getMethod() instanceof URLOpenMethod
|
||||
)
|
||||
}
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof UrlOpenSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(UrlConstructorCall u |
|
||||
@@ -63,10 +51,17 @@ class HTTPStringToURLOpenMethodFlowConfig extends TaintTracking::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess m, HTTPString s
|
||||
/**
|
||||
* A sink that represents a URL opening method call, such as a call to `java.net.URL.openConnection()`.
|
||||
*/
|
||||
private class UrlOpenSink extends DataFlow::Node {
|
||||
UrlOpenSink() { sinkNode(this, "open-url") }
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess m, HttpString s
|
||||
where
|
||||
source.getNode().asExpr() = s and
|
||||
sink.getNode().asExpr() = m.getQualifier() and
|
||||
any(HTTPStringToURLOpenMethodFlowConfig c).hasFlowPath(source, sink)
|
||||
any(HttpStringToUrlOpenMethodFlowConfig c).hasFlowPath(source, sink)
|
||||
select m, source, sink, "URL may have been constructed with HTTP protocol, using $@.", s,
|
||||
"this source"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Non-SSL connections can be intercepted by third parties.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.2
|
||||
* @precision medium
|
||||
* @id java/non-ssl-connection
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* third parties.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.2
|
||||
* @precision medium
|
||||
* @id java/non-ssl-socket-factory
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using broken or weak cryptographic algorithms can allow an attacker to compromise security.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.2
|
||||
* @precision high
|
||||
* @id java/weak-cryptographic-algorithm
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using broken or weak cryptographic algorithms can allow an attacker to compromise security.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.2
|
||||
* @precision medium
|
||||
* @id java/potentially-weak-cryptographic-algorithm
|
||||
* @tags security
|
||||
@@ -33,9 +34,8 @@ class InsecureAlgoLiteral extends ShortStringLiteral {
|
||||
}
|
||||
|
||||
predicate objectToString(MethodAccess ma) {
|
||||
exists(Method m |
|
||||
exists(ToStringMethod m |
|
||||
m = ma.getMethod() and
|
||||
m.hasName("toString") and
|
||||
m.getDeclaringType() instanceof TypeObject and
|
||||
variableTrack(ma.getQualifier()).getType().getErasure() instanceof TypeObject
|
||||
)
|
||||
|
||||
@@ -3,9 +3,11 @@
|
||||
* @description Using a predictable seed in a pseudo-random number generator can lead to predictability of the numbers generated by it.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/predictable-seed
|
||||
* @tags security
|
||||
* external/cwe/cwe-335
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using a vulnerable version of JHipster to generate random numbers makes it easier for attackers to take over accounts.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision very-high
|
||||
* @id java/jhipster-prng
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* a Cross-Site Request Forgery (CSRF) attack.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.4
|
||||
* @precision high
|
||||
* @id java/spring-disabled-csrf-protection
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* if the state may be changed between the check and use.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/toctou-race-condition
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Opening a socket after authenticating via a different channel may allow an attacker to connect to the port first.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 10.0
|
||||
* @precision medium
|
||||
* @id java/socket-auth-race-condition
|
||||
* @tags security
|
||||
|
||||
@@ -69,7 +69,7 @@ Or How I Learned to Start Worrying and Hate Java Object Deserialization</a>.
|
||||
</li>
|
||||
<li>
|
||||
Alvaro Muñoz & Christian Schneider, RSAConference 2016:
|
||||
<a href="https://www.rsaconference.com/writable/presentations/file_upload/asd-f03-serial-killer-silently-pwning-your-java-endpoints.pdf">Serial Killer: Silently Pwning Your Java Endpoints</a>.
|
||||
<a href="https://speakerdeck.com/pwntester/serial-killer-silently-pwning-your-java-endpoints">Serial Killer: Silently Pwning Your Java Endpoints</a>.
|
||||
</li>
|
||||
<li>
|
||||
SnakeYaml documentation on deserialization:
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* execute arbitrary code.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/unsafe-deserialization
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* may cause redirection to malicious web sites.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 2.7
|
||||
* @precision high
|
||||
* @id java/unvalidated-url-redirection
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* may cause redirection to malicious web sites.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 2.7
|
||||
* @precision medium
|
||||
* @id java/unvalidated-url-redirection-local
|
||||
* @tags security
|
||||
|
||||
@@ -56,11 +56,11 @@ OWASP guidance on parsing xml files:
|
||||
</li>
|
||||
<li>
|
||||
Paper by Timothy Morgen:
|
||||
<a href="https://www.vsecurity.com//download/publications/XMLDTDEntityAttacks.pdf">XML Schema, DTD, and Entity Attacks</a>
|
||||
<a href="https://research.nccgroup.com/2014/05/19/xml-schema-dtd-and-entity-attacks-a-compendium-of-known-techniques/">XML Schema, DTD, and Entity Attacks</a>
|
||||
</li>
|
||||
<li>
|
||||
Out-of-band data retrieval: Timur Yunusov & Alexey Osipov, Black hat EU 2013:
|
||||
<a href="https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf">XML Out-Of-Band Data Retrieval</a>.
|
||||
<a href="https://www.slideshare.net/qqlan/bh-ready-v4">XML Out-Of-Band Data Retrieval</a>.
|
||||
</li>
|
||||
<li>
|
||||
Denial of service attack (Billion laughs):
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* references may lead to disclosure of confidential data or denial of service.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/xxe
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* interception.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 2.9
|
||||
* @precision high
|
||||
* @id java/insecure-cookie
|
||||
* @tags security
|
||||
|
||||
83
java/ql/src/Security/CWE/CWE-643/XPathInjection.java
Normal file
83
java/ql/src/Security/CWE/CWE-643/XPathInjection.java
Normal file
@@ -0,0 +1,83 @@
|
||||
final String xmlStr = "<users>" +
|
||||
" <user name=\"aaa\" pass=\"pass1\"></user>" +
|
||||
" <user name=\"bbb\" pass=\"pass2\"></user>" +
|
||||
"</users>";
|
||||
try {
|
||||
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
|
||||
domFactory.setNamespaceAware(true);
|
||||
DocumentBuilder builder = domFactory.newDocumentBuilder();
|
||||
//Document doc = builder.parse("user.xml");
|
||||
Document doc = builder.parse(new InputSource(new StringReader(xmlStr)));
|
||||
|
||||
XPathFactory factory = XPathFactory.newInstance();
|
||||
XPath xpath = factory.newXPath();
|
||||
|
||||
// Injectable data
|
||||
String user = request.getParameter("user");
|
||||
String pass = request.getParameter("pass");
|
||||
if (user != null && pass != null) {
|
||||
boolean isExist = false;
|
||||
|
||||
// Bad expression
|
||||
String expression1 = "/users/user[@name='" + user + "' and @pass='" + pass + "']";
|
||||
isExist = (boolean)xpath.evaluate(expression1, doc, XPathConstants.BOOLEAN);
|
||||
System.out.println(isExist);
|
||||
|
||||
// Bad expression
|
||||
XPathExpression expression2 = xpath.compile("/users/user[@name='" + user + "' and @pass='" + pass + "']");
|
||||
isExist = (boolean)expression2.evaluate(doc, XPathConstants.BOOLEAN);
|
||||
System.out.println(isExist);
|
||||
|
||||
// Bad expression
|
||||
StringBuffer sb = new StringBuffer("/users/user[@name=");
|
||||
sb.append(user);
|
||||
sb.append("' and @pass='");
|
||||
sb.append(pass);
|
||||
sb.append("']");
|
||||
String query = sb.toString();
|
||||
XPathExpression expression3 = xpath.compile(query);
|
||||
isExist = (boolean)expression3.evaluate(doc, XPathConstants.BOOLEAN);
|
||||
System.out.println(isExist);
|
||||
|
||||
// Good expression
|
||||
String expression4 = "/users/user[@name=$user and @pass=$pass]";
|
||||
xpath.setXPathVariableResolver(v -> {
|
||||
switch (v.getLocalPart()) {
|
||||
case "user":
|
||||
return user;
|
||||
case "pass":
|
||||
return pass;
|
||||
default:
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
});
|
||||
isExist = (boolean)xpath.evaluate(expression4, doc, XPathConstants.BOOLEAN);
|
||||
System.out.println(isExist);
|
||||
|
||||
|
||||
// Bad Dom4j
|
||||
org.dom4j.io.SAXReader reader = new org.dom4j.io.SAXReader();
|
||||
org.dom4j.Document document = reader.read(new InputSource(new StringReader(xmlStr)));
|
||||
isExist = document.selectSingleNode("/users/user[@name='" + user + "' and @pass='" + pass + "']") != null;
|
||||
// or document.selectNodes
|
||||
System.out.println(isExist);
|
||||
|
||||
// Good Dom4j
|
||||
org.jaxen.SimpleVariableContext svc = new org.jaxen.SimpleVariableContext();
|
||||
svc.setVariableValue("user", user);
|
||||
svc.setVariableValue("pass", pass);
|
||||
String xpathString = "/users/user[@name=$user and @pass=$pass]";
|
||||
org.dom4j.XPath safeXPath = document.createXPath(xpathString);
|
||||
safeXPath.setVariableContext(svc);
|
||||
isExist = safeXPath.selectSingleNode(document) != null;
|
||||
System.out.println(isExist);
|
||||
}
|
||||
} catch (ParserConfigurationException e) {
|
||||
|
||||
} catch (SAXException e) {
|
||||
|
||||
} catch (XPathExpressionException e) {
|
||||
|
||||
} catch (org.dom4j.DocumentException e) {
|
||||
|
||||
}
|
||||
44
java/ql/src/Security/CWE/CWE-643/XPathInjection.qhelp
Normal file
44
java/ql/src/Security/CWE/CWE-643/XPathInjection.qhelp
Normal file
@@ -0,0 +1,44 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
If an XPath expression is built using string concatenation, and the components of the concatenation
|
||||
include user input, it makes it very easy for a user to create a malicious XPath expression.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
If user input must be included in an XPath expression, either sanitize the data or pre-compile the query
|
||||
and use variable references to include the user input.
|
||||
</p>
|
||||
<p>
|
||||
XPath injection can also be prevented by using XQuery.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the first three examples, the code accepts a name and password specified by the user, and uses this
|
||||
unvalidated and unsanitized value in an XPath expression. This is vulnerable to the user providing
|
||||
special characters or string sequences that change the meaning of the XPath expression to search
|
||||
for different values.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In the fourth example, the code uses <code>setXPathVariableResolver</code> which prevents XPath injection.
|
||||
</p>
|
||||
<p>
|
||||
The final two examples are for dom4j. They show an example of XPath injection and one method of preventing it.
|
||||
</p>
|
||||
<sample src="XPathInjection.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>OWASP: <a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/09-Testing_for_XPath_Injection">Testing for XPath Injection</a>.</li>
|
||||
<li>OWASP: <a href="https://owasp.org/www-community/attacks/XPATH_Injection">XPath Injection</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
31
java/ql/src/Security/CWE/CWE-643/XPathInjection.ql
Normal file
31
java/ql/src/Security/CWE/CWE-643/XPathInjection.ql
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* @name XPath injection
|
||||
* @description Building an XPath expression from user-controlled sources is vulnerable to insertion of
|
||||
* malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/xml/xpath-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-643
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.security.XPath
|
||||
import DataFlow::PathGraph
|
||||
|
||||
class XPathInjectionConfiguration extends TaintTracking::Configuration {
|
||||
XPathInjectionConfiguration() { this = "XPathInjection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof XPathInjectionSink }
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, XPathInjectionConfiguration c
|
||||
where c.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "$@ flows to here and is used in an XPath expression.",
|
||||
source.getNode(), "User-provided value"
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Certain standard library routines are dangerous to call.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 10.0
|
||||
* @precision medium
|
||||
* @id java/potentially-dangerous-function
|
||||
* @tags reliability
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* can cause unexpected truncation.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/tainted-numeric-cast
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* can cause unexpected truncation.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/tainted-numeric-cast-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* the file may be modified or removed by external actors.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/world-writable-file-read
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using a hard-coded credential in a call to a sensitive Java API may compromise security.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/hardcoded-credential-api-call
|
||||
* @tags security
|
||||
@@ -19,14 +20,14 @@ class HardcodedCredentialApiCallConfiguration extends DataFlow::Configuration {
|
||||
|
||||
override predicate isSource(DataFlow::Node n) {
|
||||
n.asExpr() instanceof HardcodedExpr and
|
||||
not n.asExpr().getEnclosingCallable().getName() = "toString"
|
||||
not n.asExpr().getEnclosingCallable() instanceof ToStringMethod
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsApiSink }
|
||||
|
||||
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
node1.asExpr().getType() instanceof TypeString and
|
||||
exists(MethodAccess ma | ma.getMethod().getName().regexpMatch("getBytes|toCharArray") |
|
||||
exists(MethodAccess ma | ma.getMethod().hasName(["getBytes", "toCharArray"]) |
|
||||
node2.asExpr() = ma and
|
||||
ma.getQualifier() = node1.asExpr()
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Comparing a parameter to a hard-coded credential may compromise security.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision low
|
||||
* @id java/hardcoded-credential-comparison
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Using a hard-coded credential in a sensitive call may compromise security.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision low
|
||||
* @id java/hardcoded-credential-sensitive-call
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Hard-coding a password string may compromise security.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision low
|
||||
* @id java/hardcoded-password-field
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* passing through authentication systems.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision medium
|
||||
* @id java/user-controlled-bypass
|
||||
* @tags security
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* permissions being granted.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/tainted-permissions-check
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Non-HTTPS connections can be intercepted by third parties.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @precision very-high
|
||||
* @id java/maven/non-https-url
|
||||
* @tags security
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @description Acquiring multiple locks in a different order may cause deadlock.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 6.9
|
||||
* @precision medium
|
||||
* @id java/lock-order-inconsistency
|
||||
* @tags security
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
* looping.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 3.6
|
||||
* @precision medium
|
||||
* @id java/unreachable-exit-in-loop
|
||||
* @tags security
|
||||
|
||||
Reference in New Issue
Block a user