mirror of
https://github.com/github/codeql.git
synced 2025-12-21 11:16:30 +01:00
Merge branch 'main' into atorralba/promote-ognl-injection
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* Such operations could interfere with the EJB container's operation.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 4.9
|
||||
* @security-severity 5.8
|
||||
* @precision low
|
||||
* @id java/ejb/container-interference
|
||||
* @tags reliability
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* for enterprise components.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 4.9
|
||||
* @security-severity 5.8
|
||||
* @precision low
|
||||
* @id java/ejb/file-io
|
||||
* @tags reliability
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* Such use could compromise security and system stability.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 4.9
|
||||
* @security-severity 5.8
|
||||
* @precision low
|
||||
* @id java/ejb/native-code
|
||||
* @tags reliability
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* as this could compromise security.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 4.9
|
||||
* @security-severity 5.8
|
||||
* @precision low
|
||||
* @id java/ejb/reflection
|
||||
* @tags external/cwe/cwe-573
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* This functionality is reserved for the EJB container for security reasons.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 4.9
|
||||
* @security-severity 5.8
|
||||
* @precision low
|
||||
* @id java/ejb/security-configuration-access
|
||||
* @tags external/cwe/cwe-573
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* the Java serialization protocol, since their use could compromise security.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 4.9
|
||||
* @security-severity 5.8
|
||||
* @precision low
|
||||
* @id java/ejb/substitution-in-serialization
|
||||
* @tags external/cwe/cwe-573
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* compromise security or interfere with the EJB container's operation.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 4.9
|
||||
* @security-severity 5.8
|
||||
* @precision low
|
||||
* @id java/ejb/socket-or-stream-handler-factory
|
||||
* @tags reliability
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.Random
|
||||
import semmle.code.java.security.RandomQuery
|
||||
|
||||
from MethodAccess ma, Method abs, Method nextIntOrLong, RandomDataSource nma
|
||||
where
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* numeric errors such as overflows.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @security-severity 8.1
|
||||
* @precision very-high
|
||||
* @id java/implicit-cast-in-compound-assignment
|
||||
* @tags reliability
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* guarantee an evenly distributed sequence of random numbers.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision medium
|
||||
* @id java/random-used-once
|
||||
* @tags reliability
|
||||
@@ -13,7 +13,7 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.Random
|
||||
import semmle.code.java.security.RandomQuery
|
||||
|
||||
from RandomDataSource ma
|
||||
where ma.getQualifier() instanceof ClassInstanceExpr
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* may cause a deadlock.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.9
|
||||
* @security-severity 5.0
|
||||
* @precision medium
|
||||
* @id java/unreleased-lock
|
||||
* @tags reliability
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* @kind path-problem
|
||||
* @precision low
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 7.8
|
||||
* @tags security external/cwe/cwe-20
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id java/path-injection
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/path-injection-local
|
||||
* @tags security
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* @kind path-problem
|
||||
* @id java/zipslip
|
||||
* @problem.severity error
|
||||
* @security-severity 6.4
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @tags security
|
||||
* external/cwe/cwe-022
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* malicious changes in the PATH environment variable.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision medium
|
||||
* @id java/relative-path-command
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* changes in the strings.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id java/command-line-injection
|
||||
* @tags security
|
||||
@@ -15,7 +15,7 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.ExternalProcess
|
||||
import ExecCommon
|
||||
import semmle.code.java.security.CommandLineQuery
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* changes in the strings.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision medium
|
||||
* @id java/command-line-injection-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* insertion of special characters in the strings.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id java/concatenated-command-line
|
||||
* @tags security
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.ExternalProcess
|
||||
import ExecCommon
|
||||
import semmle.code.java.security.CommandLineQuery
|
||||
|
||||
/**
|
||||
* Strings that are known to be sane by some simple local analysis. Such strings
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* allows for a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 2.9
|
||||
* @security-severity 6.1
|
||||
* @precision high
|
||||
* @id java/xss
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* allows for a cross-site scripting vulnerability.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 2.9
|
||||
* @security-severity 6.1
|
||||
* @precision medium
|
||||
* @id java/xss-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.4
|
||||
* @security-severity 8.8
|
||||
* @precision high
|
||||
* @id java/sql-injection
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 6.4
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id java/sql-injection-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* characters is vulnerable to insertion of malicious code.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.4
|
||||
* @security-severity 8.8
|
||||
* @precision high
|
||||
* @id java/concatenated-sql-query
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* malicious LDAP code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id java/ldap-injection
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
* @id java/insecure-bean-validation
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* may lead to arbitrary code execution.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 10.0
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
* @id java/jexl-expression-injection
|
||||
* @tags security
|
||||
@@ -12,27 +12,9 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.JexlInjection
|
||||
import semmle.code.java.security.JexlInjectionQuery
|
||||
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"
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* an HTTP header.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 3.6
|
||||
* @security-severity 6.1
|
||||
* @precision high
|
||||
* @id java/netty-http-response-splitting
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* makes code vulnerable to attack by header splitting.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 3.6
|
||||
* @security-severity 6.1
|
||||
* @precision high
|
||||
* @id java/http-response-splitting
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* makes code vulnerable to attack by header splitting.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 3.6
|
||||
* @security-severity 6.1
|
||||
* @precision medium
|
||||
* @id java/http-response-splitting-local
|
||||
* @tags security
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.DefUse
|
||||
import semmle.code.java.security.Random
|
||||
import semmle.code.java.security.RandomDataSource
|
||||
private import BoundingChecks
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-construction
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +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
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-construction-code-specified
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +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
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-construction-local
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-index
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* proper validation, can lead to index out of bound exceptions.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-index-code-specified
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* proper validation, can lead to index out of bound exceptions.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @security-severity 8.8
|
||||
* @precision medium
|
||||
* @id java/improper-validation-of-array-index-local
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 9.3
|
||||
* @precision high
|
||||
* @id java/tainted-format-string
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 9.3
|
||||
* @precision medium
|
||||
* @id java/tainted-format-string-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* overflows.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @security-severity 8.6
|
||||
* @precision medium
|
||||
* @id java/tainted-arithmetic
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* overflows.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @security-severity 8.6
|
||||
* @precision medium
|
||||
* @id java/tainted-arithmetic-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* overflows.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @security-severity 8.6
|
||||
* @precision medium
|
||||
* @id java/uncontrolled-arithmetic
|
||||
* @tags security
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
import java
|
||||
import semmle.code.java.dataflow.TaintTracking
|
||||
import semmle.code.java.security.Random
|
||||
import semmle.code.java.security.RandomQuery
|
||||
import semmle.code.java.security.SecurityTests
|
||||
import ArithmeticCommon
|
||||
import DataFlow::PathGraph
|
||||
|
||||
@@ -4,7 +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
|
||||
* @security-severity 8.6
|
||||
* @precision medium
|
||||
* @id java/extreme-value-arithmetic
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* to behave unexpectedly.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @security-severity 8.1
|
||||
* @precision medium
|
||||
* @id java/comparison-with-wider-type
|
||||
* @tags reliability
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* that are useful to an attacker for developing a subsequent exploit.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 3.6
|
||||
* @security-severity 5.4
|
||||
* @precision high
|
||||
* @id java/stack-trace-exposure
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 5.9
|
||||
* @precision high
|
||||
* @id java/unsafe-hostname-verification
|
||||
* @tags security
|
||||
@@ -15,6 +15,7 @@ import semmle.code.java.controlflow.Guards
|
||||
import semmle.code.java.dataflow.DataFlow
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.Encryption
|
||||
import semmle.code.java.security.SecurityFlag
|
||||
import DataFlow::PathGraph
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
@@ -86,71 +87,30 @@ private class HostnameVerifierSink extends DataFlow::Node {
|
||||
HostnameVerifierSink() { sinkNode(this, "set-hostname-verifier") }
|
||||
}
|
||||
|
||||
bindingset[result]
|
||||
private string getAFlagName() {
|
||||
result
|
||||
.regexpMatch("(?i).*(secure|disable|selfCert|selfSign|validat|verif|trust|ignore|nocertificatecheck).*")
|
||||
}
|
||||
|
||||
/**
|
||||
* A flag has to either be of type `String`, `boolean` or `Boolean`.
|
||||
* Flags suggesting a deliberately unsafe `HostnameVerifier` usage.
|
||||
*/
|
||||
private class FlagType extends Type {
|
||||
FlagType() {
|
||||
this instanceof TypeString
|
||||
or
|
||||
this instanceof BooleanType
|
||||
private class UnsafeHostnameVerificationFlag extends FlagKind {
|
||||
UnsafeHostnameVerificationFlag() { this = "UnsafeHostnameVerificationFlag" }
|
||||
|
||||
bindingset[result]
|
||||
override string getAFlagName() {
|
||||
result
|
||||
.regexpMatch("(?i).*(secure|disable|selfCert|selfSign|validat|verif|trust|ignore|nocertificatecheck).*") and
|
||||
result != "equalsIgnoreCase"
|
||||
}
|
||||
}
|
||||
|
||||
private predicate isEqualsIgnoreCaseMethodAccess(MethodAccess ma) {
|
||||
ma.getMethod().hasName("equalsIgnoreCase") and
|
||||
ma.getMethod().getDeclaringType() instanceof TypeString
|
||||
/** Gets a guard that represents a (likely) flag controlling an unsafe `HostnameVerifier` use. */
|
||||
private Guard getAnUnsafeHostnameVerifierFlagGuard() {
|
||||
result = any(UnsafeHostnameVerificationFlag flag).getAFlag().asExpr()
|
||||
}
|
||||
|
||||
/** Holds if `source` should is considered a flag. */
|
||||
private predicate isFlag(DataFlow::Node source) {
|
||||
exists(VarAccess v | v.getVariable().getName() = getAFlagName() |
|
||||
source.asExpr() = v and v.getType() instanceof FlagType
|
||||
)
|
||||
or
|
||||
exists(StringLiteral s | s.getRepresentedString() = getAFlagName() | source.asExpr() = s)
|
||||
or
|
||||
exists(MethodAccess ma | ma.getMethod().getName() = getAFlagName() |
|
||||
source.asExpr() = ma and
|
||||
ma.getType() instanceof FlagType and
|
||||
not isEqualsIgnoreCaseMethodAccess(ma)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if there is flow from `node1` to `node2` either due to local flow or due to custom flow steps. */
|
||||
private predicate flagFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
DataFlow::localFlowStep(node1, node2)
|
||||
or
|
||||
exists(MethodAccess ma | ma.getMethod() = any(EnvReadMethod m) |
|
||||
ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr()
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod().hasName("parseBoolean") and
|
||||
ma.getMethod().getDeclaringType().hasQualifiedName("java.lang", "Boolean")
|
||||
|
|
||||
ma = node2.asExpr() and ma.getAnArgument() = node1.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a guard that depends on a flag. */
|
||||
private Guard getAGuard() {
|
||||
exists(DataFlow::Node source, DataFlow::Node sink |
|
||||
isFlag(source) and
|
||||
flagFlowStep*(source, sink) and
|
||||
sink.asExpr() = result
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` is guarded by a flag that suggests an intentionally insecure feature. */
|
||||
/** Holds if `node` is guarded by a flag that suggests an intentionally insecure use. */
|
||||
private predicate isNodeGuardedByFlag(DataFlow::Node node) {
|
||||
exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) | g = getAGuard())
|
||||
exists(Guard g | g.controls(node.asExpr().getBasicBlock(), _) |
|
||||
g = getASecurityFeatureFlagGuard() or g = getAnUnsafeHostnameVerifierFlagGuard()
|
||||
)
|
||||
}
|
||||
|
||||
from
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Storing sensitive information in cleartext can expose it to an attacker.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/cleartext-storage-in-class
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Storing sensitive information in cleartext can expose it to an attacker.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 2.9
|
||||
* @security-severity 5.0
|
||||
* @precision high
|
||||
* @id java/cleartext-storage-in-cookie
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Storing sensitive information in cleartext can expose it to an attacker.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 6.4
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/cleartext-storage-in-properties
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Non-HTTPS connections can be intercepted by third parties.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.2
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/non-https-url
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Non-SSL connections can be intercepted by third parties.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.2
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/non-ssl-connection
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* third parties.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.2
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/non-ssl-socket-factory
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 7.5
|
||||
* @precision high
|
||||
* @id java/weak-cryptographic-algorithm
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/potentially-weak-cryptographic-algorithm
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @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
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id java/predictable-seed
|
||||
* @tags security
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.Random
|
||||
import semmle.code.java.security.RandomQuery
|
||||
|
||||
from GetRandomData da, RValue use, PredictableSeedExpr source
|
||||
where
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 7.8
|
||||
* @precision very-high
|
||||
* @id java/jhipster-prng
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* a Cross-Site Request Forgery (CSRF) attack.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 6.4
|
||||
* @security-severity 8.8
|
||||
* @precision high
|
||||
* @id java/spring-disabled-csrf-protection
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* if the state may be changed between the check and use.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 5.9
|
||||
* @security-severity 7.7
|
||||
* @precision medium
|
||||
* @id java/toctou-race-condition
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 7.2
|
||||
* @precision medium
|
||||
* @id java/socket-auth-race-condition
|
||||
* @tags security
|
||||
|
||||
@@ -14,8 +14,8 @@ may have unforeseen effects, such as the execution of arbitrary code.
|
||||
</p>
|
||||
<p>
|
||||
There are many different serialization frameworks. This query currently
|
||||
supports Kryo, XmlDecoder, XStream, SnakeYaml, and Java IO serialization through
|
||||
<code>ObjectInputStream</code>/<code>ObjectOutputStream</code>.
|
||||
supports Kryo, XmlDecoder, XStream, SnakeYaml, JYaml, JsonIO, YAMLBeans, HessianBurlap, Castor, Burlap
|
||||
and Java IO serialization through <code>ObjectInputStream</code>/<code>ObjectOutputStream</code>.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
@@ -75,6 +75,22 @@ Alvaro Muñoz & Christian Schneider, RSAConference 2016:
|
||||
SnakeYaml documentation on deserialization:
|
||||
<a href="https://bitbucket.org/asomov/snakeyaml/wiki/Documentation#markdown-header-loading-yaml">SnakeYaml deserialization</a>.
|
||||
</li>
|
||||
<li>
|
||||
Hessian deserialization and related gadget chains:
|
||||
<a href="https://paper.seebug.org/1137/">Hessian deserialization</a>.
|
||||
</li>
|
||||
<li>
|
||||
Castor and Hessian java deserialization vulnerabilities:
|
||||
<a href="https://securitylab.github.com/research/hessian-java-deserialization-castor-vulnerabilities/">Castor and Hessian deserialization</a>.
|
||||
</li>
|
||||
<li>
|
||||
Remote code execution in JYaml library:
|
||||
<a href="https://www.cybersecurity-help.cz/vdb/SB2020022512">JYaml deserialization</a>.
|
||||
</li>
|
||||
<li>
|
||||
JsonIO deserialization vulnerabilities:
|
||||
<a href="https://klezvirus.github.io/Advanced-Web-Hacking/Serialisation/">JsonIO deserialization</a>.
|
||||
</li>
|
||||
</references>
|
||||
|
||||
</qhelp>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* execute arbitrary code.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id java/unsafe-deserialization
|
||||
* @tags security
|
||||
@@ -22,6 +22,39 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration {
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(ClassInstanceExpr cie |
|
||||
cie.getArgument(0) = pred.asExpr() and
|
||||
cie = succ.asExpr() and
|
||||
(
|
||||
cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader or
|
||||
cie.getConstructor().getDeclaringType() instanceof YamlBeansReader or
|
||||
cie.getConstructor().getDeclaringType().getASupertype*() instanceof UnsafeHessianInput or
|
||||
cie.getConstructor().getDeclaringType() instanceof BurlapInput
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof BurlapInputInitMethod and
|
||||
ma.getArgument(0) = pred.asExpr() and
|
||||
ma.getQualifier() = succ.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
exists(ClassInstanceExpr cie |
|
||||
cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and
|
||||
cie = node.asExpr() and
|
||||
exists(SafeJsonIoConfig sji | sji.hasFlowToExpr(cie.getArgument(1)))
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof JsonIoJsonToJavaMethod and
|
||||
ma.getArgument(0) = node.asExpr() and
|
||||
exists(SafeJsonIoConfig sji | sji.hasFlowToExpr(ma.getArgument(1)))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeDeserializationConfig conf
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* may cause redirection to malicious web sites.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 2.7
|
||||
* @security-severity 6.1
|
||||
* @precision high
|
||||
* @id java/unvalidated-url-redirection
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* may cause redirection to malicious web sites.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 2.7
|
||||
* @security-severity 6.1
|
||||
* @precision medium
|
||||
* @id java/unvalidated-url-redirection-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* references may lead to disclosure of confidential data or denial of service.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.1
|
||||
* @precision high
|
||||
* @id java/xxe
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* interception.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 2.9
|
||||
* @security-severity 5.0
|
||||
* @precision high
|
||||
* @id java/insecure-cookie
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* malicious code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision high
|
||||
* @id java/xml/xpath-injection
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* can cause unexpected truncation.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.0
|
||||
* @precision high
|
||||
* @id java/tainted-numeric-cast
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* can cause unexpected truncation.
|
||||
* @kind path-problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.0
|
||||
* @precision medium
|
||||
* @id java/tainted-numeric-cast-local
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* the file may be modified or removed by external actors.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 7.8
|
||||
* @precision high
|
||||
* @id java/world-writable-file-read
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 9.8
|
||||
* @precision medium
|
||||
* @id java/hardcoded-credential-api-call
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Comparing a parameter to a hard-coded credential may compromise security.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision low
|
||||
* @id java/hardcoded-credential-comparison
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +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
|
||||
* @security-severity 9.8
|
||||
* @precision low
|
||||
* @id java/hardcoded-credential-sensitive-call
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Hard-coding a password string may compromise security.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 9.8
|
||||
* @precision low
|
||||
* @id java/hardcoded-password-field
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* passing through authentication systems.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 7.8
|
||||
* @precision medium
|
||||
* @id java/user-controlled-bypass
|
||||
* @tags security
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* permissions being granted.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 7.8
|
||||
* @precision high
|
||||
* @id java/tainted-permissions-check
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Non-HTTPS connections can be intercepted by third parties.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @security-severity 5.9
|
||||
* @security-severity 8.1
|
||||
* @precision very-high
|
||||
* @id java/maven/non-https-url
|
||||
* @tags security
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @description Acquiring multiple locks in a different order may cause deadlock.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @security-severity 6.9
|
||||
* @security-severity 5.0
|
||||
* @precision medium
|
||||
* @id java/lock-order-inconsistency
|
||||
* @tags security
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* looping.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 3.6
|
||||
* @security-severity 7.5
|
||||
* @precision medium
|
||||
* @id java/unreachable-exit-in-loop
|
||||
* @tags security
|
||||
|
||||
@@ -5,22 +5,24 @@
|
||||
|
||||
|
||||
<overview>
|
||||
<p>Directly incorporating user input into a HTTP request without validating the input
|
||||
can facilitate Server Side Request Forgery (SSRF) attacks. In these attacks, the server
|
||||
may be tricked into making a request and interacting with an attacker-controlled server.
|
||||
<p>Directly incorporating user input into an HTTP request without validating the input
|
||||
can facilitate server-side request forgery (SSRF) attacks. In these attacks, the server
|
||||
may be tricked into making a request and interacting with an attacker-controlled server.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>To guard against SSRF attacks, it is advisable to avoid putting user input
|
||||
directly into the request URL. Instead, maintain a list of authorized
|
||||
URLs on the server; then choose from that list based on the user input provided.</p>
|
||||
<p>To guard against SSRF attacks, you should avoid putting user-provided input
|
||||
directly into a request URL. Instead, maintain a list of authorized
|
||||
URLs on the server; then choose from that list based on the input provided.
|
||||
Alternatively, ensure requests constructed from user input are limited to
|
||||
a particular host or more restrictive URL prefix.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
|
||||
<p>The following example shows an HTTP request parameter being used directly in a forming a
|
||||
<p>The following example shows an HTTP request parameter being used directly to form a
|
||||
new request without validating the input, which facilitates SSRF attacks.
|
||||
It also shows how to remedy the problem by validating the user input against a known fixed string.
|
||||
</p>
|
||||
20
java/ql/src/Security/CWE/CWE-918/RequestForgery.ql
Normal file
20
java/ql/src/Security/CWE/CWE-918/RequestForgery.ql
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* @name Server-side request forgery
|
||||
* @description Making web requests based on unvalidated user-input
|
||||
* may cause the server to communicate with malicious servers.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id java/ssrf
|
||||
* @tags security
|
||||
* external/cwe/cwe-918
|
||||
*/
|
||||
|
||||
import java
|
||||
import semmle.code.java.security.RequestForgeryConfig
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, RequestForgeryConfiguration conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "Potential server-side request forgery due to $@.",
|
||||
source.getNode(), "a user-provided value"
|
||||
@@ -479,6 +479,11 @@ implInterface(
|
||||
int id2: @interface ref
|
||||
);
|
||||
|
||||
permits(
|
||||
int id1: @classorinterface ref,
|
||||
int id2: @classorinterface ref
|
||||
);
|
||||
|
||||
hasModifier(
|
||||
int id1: @modifiable ref,
|
||||
int id2: @modifier ref
|
||||
|
||||
@@ -17639,6 +17639,64 @@
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>permits</name>
|
||||
<cardinality>16</cardinality>
|
||||
<columnsizes>
|
||||
<e>
|
||||
<k>id1</k>
|
||||
<v>6</v>
|
||||
</e>
|
||||
<e>
|
||||
<k>id2</k>
|
||||
<v>16</v>
|
||||
</e>
|
||||
</columnsizes>
|
||||
<dependencies>
|
||||
<dep>
|
||||
<src>id1</src>
|
||||
<trg>id2</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>3</a>
|
||||
<b>4</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
<b>
|
||||
<a>4</a>
|
||||
<b>5</b>
|
||||
<v>2</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
<dep>
|
||||
<src>id2</src>
|
||||
<trg>id1</trg>
|
||||
<val>
|
||||
<hist>
|
||||
<budget>12</budget>
|
||||
<bs>
|
||||
<b>
|
||||
<a>1</a>
|
||||
<b>2</b>
|
||||
<v>16</v>
|
||||
</b>
|
||||
</bs>
|
||||
</hist>
|
||||
</val>
|
||||
</dep>
|
||||
</dependencies>
|
||||
</relation>
|
||||
<relation>
|
||||
<name>hasModifier</name>
|
||||
<cardinality>5667539</cardinality>
|
||||
<columnsizes>
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
* @description Exposed Spring Boot Actuator through configuration files without declarative or procedural
|
||||
* security enforcement leads to information leak or even remote code execution.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id java/insecure-spring-actuator-config
|
||||
* @tags security
|
||||
* external/cwe-016
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.ExternalProcess
|
||||
import semmle.code.java.security.CommandArguments
|
||||
|
||||
private class RemoteUserInputToArgumentToExecFlowConfig extends TaintTracking::Configuration {
|
||||
RemoteUserInputToArgumentToExecFlowConfig() {
|
||||
this = "ExecCommon::RemoteUserInputToArgumentToExecFlowConfig"
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof ArgumentToExec }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
node.getType() instanceof PrimitiveType
|
||||
or
|
||||
node.getType() instanceof BoxedType
|
||||
or
|
||||
isSafeCommandArgument(node.asExpr())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of `ExecTainted.ql`. It is extracted to a QLL
|
||||
* so that it can be excluded from `ExecUnescaped.ql` to avoid
|
||||
* reporting overlapping results.
|
||||
*/
|
||||
predicate execTainted(DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg) {
|
||||
exists(RemoteUserInputToArgumentToExecFlowConfig conf |
|
||||
conf.hasFlowPath(source, sink) and sink.getNode() = DataFlow::exprNode(execArg)
|
||||
)
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* @name Uncontrolled command line
|
||||
* @name Uncontrolled command line (experimental sinks)
|
||||
* @description Using externally controlled strings in a command line is vulnerable to malicious
|
||||
* changes in the strings.
|
||||
* changes in the strings (includes experimental sinks).
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id java/command-line-injection
|
||||
* @id java/command-line-injection-experimental
|
||||
* @tags security
|
||||
* external/cwe/cwe-078
|
||||
* external/cwe/cwe-088
|
||||
@@ -14,10 +14,11 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import semmle.code.java.security.ExternalProcess
|
||||
import ExecCommon
|
||||
import semmle.code.java.security.CommandLineQuery
|
||||
import JSchOSInjection
|
||||
import DataFlow::PathGraph
|
||||
|
||||
// This is a clone of query `java/command-line-injection` that also includes experimental sinks.
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, ArgumentToExec execArg
|
||||
where execTainted(source, sink, execArg)
|
||||
select execArg, source, sink, "$@ flows to here and is used in a command.", source.getNode(),
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import bsh.Interpreter;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.springframework.scripting.bsh.BshScriptEvaluator;
|
||||
import org.springframework.scripting.support.StaticScriptSource;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class BeanShellInjection {
|
||||
|
||||
@GetMapping(value = "bad1")
|
||||
public void bad1(HttpServletRequest request) {
|
||||
String code = request.getParameter("code");
|
||||
BshScriptEvaluator evaluator = new BshScriptEvaluator();
|
||||
evaluator.evaluate(new StaticScriptSource(code)); //bad
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad2")
|
||||
public void bad2(HttpServletRequest request) throws Exception {
|
||||
String code = request.getParameter("code");
|
||||
Interpreter interpreter = new Interpreter();
|
||||
interpreter.eval(code); //bad
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad3")
|
||||
public void bad3(HttpServletRequest request) {
|
||||
String code = request.getParameter("code");
|
||||
StaticScriptSource staticScriptSource = new StaticScriptSource("test");
|
||||
staticScriptSource.setScript(code);
|
||||
BshScriptEvaluator evaluator = new BshScriptEvaluator();
|
||||
evaluator.evaluate(staticScriptSource); //bad
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
BeanShell is a small, free, embeddable Java source interpreter with object scripting language
|
||||
features, written in Java. BeanShell dynamically executes standard Java syntax and extends it
|
||||
with common scripting conveniences such as loose types, commands, and method closures like
|
||||
those in Perl and JavaScript. If a BeanShell 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 BeanShell expression.
|
||||
If it is not possible, BeanShell 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 BeanShell expression.
|
||||
</p>
|
||||
<sample src="BeanShellInjection.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
CVE-2016-2510:<a href="https://nvd.nist.gov/vuln/detail/CVE-2016-2510">BeanShell Injection</a>.
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* @name BeanShell injection
|
||||
* @description Evaluation of a user-controlled BeanShell expression
|
||||
* may lead to arbitrary code execution.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id java/beanshell-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-094
|
||||
*/
|
||||
|
||||
import java
|
||||
import BeanShellInjection
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
|
||||
class BeanShellInjectionConfig extends TaintTracking::Configuration {
|
||||
BeanShellInjectionConfig() { this = "BeanShellInjectionConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof BeanShellInjectionSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node prod, DataFlow::Node succ) {
|
||||
exists(ClassInstanceExpr cie |
|
||||
cie.getConstructedType()
|
||||
.hasQualifiedName("org.springframework.scripting.support", "StaticScriptSource") and
|
||||
cie.getArgument(0) = prod.asExpr() and
|
||||
cie = succ.asExpr()
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod().hasName("setScript") and
|
||||
ma.getMethod()
|
||||
.getDeclaringType()
|
||||
.hasQualifiedName("org.springframework.scripting.support", "StaticScriptSource") and
|
||||
ma.getArgument(0) = prod.asExpr() and
|
||||
ma.getQualifier() = succ.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, BeanShellInjectionConfig conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "BeanShell injection from $@.", source.getNode(),
|
||||
"this user input"
|
||||
@@ -0,0 +1,28 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
/** A call to `Interpreter.eval`. */
|
||||
class InterpreterEvalCall extends MethodAccess {
|
||||
InterpreterEvalCall() {
|
||||
this.getMethod().hasName("eval") and
|
||||
this.getMethod().getDeclaringType().hasQualifiedName("bsh", "Interpreter")
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `BshScriptEvaluator.evaluate`. */
|
||||
class BshScriptEvaluatorEvaluateCall extends MethodAccess {
|
||||
BshScriptEvaluatorEvaluateCall() {
|
||||
this.getMethod().hasName("evaluate") and
|
||||
this.getMethod()
|
||||
.getDeclaringType()
|
||||
.hasQualifiedName("org.springframework.scripting.bsh", "BshScriptEvaluator")
|
||||
}
|
||||
}
|
||||
|
||||
/** A sink for BeanShell expression injection vulnerabilities. */
|
||||
class BeanShellInjectionSink extends DataFlow::Node {
|
||||
BeanShellInjectionSink() {
|
||||
this.asExpr() = any(InterpreterEvalCall iec).getArgument(0) or
|
||||
this.asExpr() = any(BshScriptEvaluatorEvaluateCall bseec).getArgument(0)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jdk.jshell.JShell;
|
||||
import jdk.jshell.SourceCodeAnalysis;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class JShellInjection {
|
||||
|
||||
@GetMapping(value = "bad1")
|
||||
public void bad1(HttpServletRequest request) {
|
||||
String input = request.getParameter("code");
|
||||
JShell jShell = JShell.builder().build();
|
||||
// BAD: allow execution of arbitrary Java code
|
||||
jShell.eval(input);
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad2")
|
||||
public void bad2(HttpServletRequest request) {
|
||||
String input = request.getParameter("code");
|
||||
JShell jShell = JShell.builder().build();
|
||||
SourceCodeAnalysis sourceCodeAnalysis = jShell.sourceCodeAnalysis();
|
||||
// BAD: allow execution of arbitrary Java code
|
||||
sourceCodeAnalysis.wrappers(input);
|
||||
}
|
||||
|
||||
@GetMapping(value = "bad3")
|
||||
public void bad3(HttpServletRequest request) {
|
||||
String input = request.getParameter("code");
|
||||
JShell jShell = JShell.builder().build();
|
||||
SourceCodeAnalysis.CompletionInfo info;
|
||||
SourceCodeAnalysis sca = jShell.sourceCodeAnalysis();
|
||||
for (info = sca.analyzeCompletion(input);
|
||||
info.completeness().isComplete();
|
||||
info = sca.analyzeCompletion(info.remaining())) {
|
||||
// BAD: allow execution of arbitrary Java code
|
||||
jShell.eval(info.source());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>The Java Shell tool (JShell) is an interactive tool for learning the Java programming
|
||||
language and prototyping Java code. JShell is a Read-Evaluate-Print Loop (REPL), which
|
||||
evaluates declarations, statements, and expressions as they are entered and immediately
|
||||
shows the results. If an expression is built using attacker-controlled data and then evaluated,
|
||||
it may allow the attacker to run arbitrary code.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>It is generally recommended to avoid using untrusted input in a JShell expression.
|
||||
If it is not possible, JShell expressions should be run in a sandbox that allows accessing only
|
||||
explicitly allowed classes.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>The following example calls <code>JShell.eval(...)</code> or <code>SourceCodeAnalysis.wrappers(...)</code>
|
||||
to execute untrusted data.</p>
|
||||
<sample src="JShellInjection.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Java Shell User’s Guide: <a href="https://docs.oracle.com/en/java/javase/11/jshell/introduction-jshell.html">Introduction to JShell</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @name JShell injection
|
||||
* @description Evaluation of a user-controlled JShell expression
|
||||
* may lead to arbitrary code execution.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id java/jshell-injection
|
||||
* @tags security
|
||||
* external/cwe-094
|
||||
*/
|
||||
|
||||
import java
|
||||
import JShellInjection
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
|
||||
class JShellInjectionConfiguration extends TaintTracking::Configuration {
|
||||
JShellInjectionConfiguration() { this = "JShellInjectionConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof JShellInjectionSink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
exists(SourceCodeAnalysisAnalyzeCompletionCall scaacc |
|
||||
scaacc.getArgument(0) = pred.asExpr() and scaacc = succ.asExpr()
|
||||
)
|
||||
or
|
||||
exists(CompletionInfoSourceOrRemainingCall cisorc |
|
||||
cisorc.getQualifier() = pred.asExpr() and cisorc = succ.asExpr()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from DataFlow::PathNode source, DataFlow::PathNode sink, JShellInjectionConfiguration conf
|
||||
where conf.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "JShell injection from $@.", source.getNode(),
|
||||
"this user input"
|
||||
@@ -0,0 +1,53 @@
|
||||
import java
|
||||
import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
/** A sink for JShell expression injection vulnerabilities. */
|
||||
class JShellInjectionSink extends DataFlow::Node {
|
||||
JShellInjectionSink() {
|
||||
this.asExpr() = any(JShellEvalCall jsec).getArgument(0)
|
||||
or
|
||||
this.asExpr() = any(SourceCodeAnalysisWrappersCall scawc).getArgument(0)
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `JShell.eval`. */
|
||||
private class JShellEvalCall extends MethodAccess {
|
||||
JShellEvalCall() {
|
||||
this.getMethod().hasName("eval") and
|
||||
this.getMethod().getDeclaringType().hasQualifiedName("jdk.jshell", "JShell") and
|
||||
this.getMethod().getNumberOfParameters() = 1
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `SourceCodeAnalysis.wrappers`. */
|
||||
private class SourceCodeAnalysisWrappersCall extends MethodAccess {
|
||||
SourceCodeAnalysisWrappersCall() {
|
||||
this.getMethod().hasName("wrappers") and
|
||||
this.getMethod().getDeclaringType().hasQualifiedName("jdk.jshell", "SourceCodeAnalysis") and
|
||||
this.getMethod().getNumberOfParameters() = 1
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `SourceCodeAnalysis.analyzeCompletion`. */
|
||||
class SourceCodeAnalysisAnalyzeCompletionCall extends MethodAccess {
|
||||
SourceCodeAnalysisAnalyzeCompletionCall() {
|
||||
this.getMethod().hasName("analyzeCompletion") and
|
||||
this.getMethod()
|
||||
.getDeclaringType()
|
||||
.getASupertype*()
|
||||
.hasQualifiedName("jdk.jshell", "SourceCodeAnalysis") and
|
||||
this.getMethod().getNumberOfParameters() = 1
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `CompletionInfo.source` or `CompletionInfo.remaining`. */
|
||||
class CompletionInfoSourceOrRemainingCall extends MethodAccess {
|
||||
CompletionInfoSourceOrRemainingCall() {
|
||||
this.getMethod().getName() in ["source", "remaining"] and
|
||||
this.getMethod()
|
||||
.getDeclaringType()
|
||||
.getASupertype*()
|
||||
.hasQualifiedName("jdk.jshell", "SourceCodeAnalysis$CompletionInfo") and
|
||||
this.getMethod().getNumberOfParameters() = 0
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
* @description Sensitive cookies without the 'HttpOnly' flag set leaves session cookies vulnerable to
|
||||
* an XSS attack.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @id java/sensitive-cookie-not-httponly
|
||||
* @tags security
|
||||
* external/cwe/cwe-1004
|
||||
@@ -74,12 +76,9 @@ class MatchesHttpOnlyConfiguration extends TaintTracking2::Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** A class descended from `javax.servlet.http.Cookie` or `javax/jakarta.ws.rs.core.Cookie`. */
|
||||
/** A class descended from `javax.servlet.http.Cookie`. */
|
||||
class CookieClass extends RefType {
|
||||
CookieClass() {
|
||||
this.getASupertype*()
|
||||
.hasQualifiedName(["javax.servlet.http", "javax.ws.rs.core", "jakarta.ws.rs.core"], "Cookie")
|
||||
}
|
||||
CookieClass() { this.getASupertype*().hasQualifiedName("javax.servlet.http", "Cookie") }
|
||||
}
|
||||
|
||||
/** Holds if `expr` is any boolean-typed expression other than literal `false`. */
|
||||
|
||||
@@ -1,45 +1,5 @@
|
||||
public static void main(String[] args) {
|
||||
|
||||
{
|
||||
X509TrustManager trustAllCertManager = new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(final X509Certificate[] chain, final String authType)
|
||||
throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(final X509Certificate[] chain, final String authType)
|
||||
throws CertificateException {
|
||||
// BAD: trust any server cert
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null; //BAD: doesn't check cert issuer
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
X509TrustManager trustCertManager = new X509TrustManager() {
|
||||
@Override
|
||||
public void checkClientTrusted(final X509Certificate[] chain, final String authType)
|
||||
throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(final X509Certificate[] chain, final String authType)
|
||||
throws CertificateException {
|
||||
pkixTrustManager.checkServerTrusted(chain, authType); //GOOD: validate the server cert
|
||||
}
|
||||
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[0]; //GOOD: Validate the cert issuer
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
SSLEngine sslEngine = sslContext.createSSLEngine();
|
||||
|
||||
@@ -4,10 +4,9 @@
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>Java offers two mechanisms for SSL authentication - trust manager and hostname verifier (checked by the <code>java/insecure-hostname-verifier</code> query). Trust manager validates the peer's certificate chain while hostname verification establishes that the hostname in the URL matches the hostname in the server's identification.</p>
|
||||
<p>And when SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.</p>
|
||||
<p>When SSLSocket or SSLEngine is created without a valid parameter of setEndpointIdentificationAlgorithm, hostname verification is disabled by default.</p>
|
||||
<p>Unsafe implementation of the interface X509TrustManager and SSLSocket/SSLEngine ignores all SSL certificate validation errors when establishing an HTTPS connection, thereby making the app vulnerable to man-in-the-middle attacks.</p>
|
||||
<p>This query checks whether trust manager is set to trust all certificates or setEndpointIdentificationAlgorithm is missing. The query also covers a special implementation com.rabbitmq.client.ConnectionFactory.</p>
|
||||
<p>This query checks whether setEndpointIdentificationAlgorithm is missing. The query also covers a special implementation com.rabbitmq.client.ConnectionFactory.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
@@ -15,8 +14,8 @@
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>The following two examples show two ways of configuring X509 trust cert manager. In the 'BAD' case,
|
||||
no validation is performed thus any certificate is trusted. In the 'GOOD' case, the proper validation is performed.</p>
|
||||
<p>The following two examples show two ways of configuring SSLSocket/SSLEngine. In the 'BAD' case,
|
||||
setEndpointIdentificationAlgorithm is not called, thus no hostname verification takes place. In the 'GOOD' case, setEndpointIdentificationAlgorithm is called.</p>
|
||||
<sample src="UnsafeCertTrust.java" />
|
||||
</example>
|
||||
|
||||
@@ -25,9 +24,6 @@ no validation is performed thus any certificate is trusted. In the 'GOOD' case,
|
||||
<a href="https://cwe.mitre.org/data/definitions/273.html">CWE-273</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://support.google.com/faqs/answer/6346016?hl=en">How to fix apps containing an unsafe implementation of TrustManager</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://github.com/OWASP/owasp-mstg/blob/master/Document/0x05g-Testing-Network-Communication.md">Testing Endpoint Identify Verification (MSTG-NETWORK-3)</a>
|
||||
</li>
|
||||
<li>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
/**
|
||||
* @name Unsafe certificate trust
|
||||
* @description Unsafe implementation of the interface X509TrustManager and
|
||||
* SSLSocket/SSLEngine ignores all SSL certificate validation
|
||||
* @description SSLSocket/SSLEngine ignores all SSL certificate validation
|
||||
* errors when establishing an HTTPS connection, thereby making
|
||||
* the app vulnerable to man-in-the-middle attacks.
|
||||
* @kind problem
|
||||
@@ -15,49 +14,6 @@
|
||||
import java
|
||||
import semmle.code.java.security.Encryption
|
||||
|
||||
/**
|
||||
* X509TrustManager class that blindly trusts all certificates in server SSL authentication
|
||||
*/
|
||||
class X509TrustAllManager extends RefType {
|
||||
X509TrustAllManager() {
|
||||
this.getASupertype*() instanceof X509TrustManager and
|
||||
exists(Method m1 |
|
||||
m1.getDeclaringType() = this and
|
||||
m1.hasName("checkServerTrusted") and
|
||||
m1.getBody().getNumStmt() = 0
|
||||
) and
|
||||
exists(Method m2, ReturnStmt rt2 |
|
||||
m2.getDeclaringType() = this and
|
||||
m2.hasName("getAcceptedIssuers") and
|
||||
rt2.getEnclosingCallable() = m2 and
|
||||
rt2.getResult() instanceof NullLiteral
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The init method of SSLContext with the trust all manager, which is sslContext.init(..., serverTMs, ...)
|
||||
*/
|
||||
class X509TrustAllManagerInit extends MethodAccess {
|
||||
X509TrustAllManagerInit() {
|
||||
this.getMethod().hasName("init") and
|
||||
this.getMethod().getDeclaringType() instanceof SSLContext and //init method of SSLContext
|
||||
(
|
||||
exists(ArrayInit ai |
|
||||
this.getArgument(1).(ArrayCreationExpr).getInit() = ai and
|
||||
ai.getInit(0).(VarAccess).getVariable().getInitializer().getType().(Class).getASupertype*()
|
||||
instanceof X509TrustAllManager //Scenario of context.init(null, new TrustManager[] { TRUST_ALL_CERTIFICATES }, null);
|
||||
)
|
||||
or
|
||||
exists(Variable v, ArrayInit ai |
|
||||
this.getArgument(1).(VarAccess).getVariable() = v and
|
||||
ai.getParent() = v.getAnAssignedValue() and
|
||||
ai.getInit(0).getType().(Class).getASupertype*() instanceof X509TrustAllManager //Scenario of context.init(null, serverTMs, null);
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class SSLEngine extends RefType {
|
||||
SSLEngine() { this.hasQualifiedName("javax.net.ssl", "SSLEngine") }
|
||||
}
|
||||
@@ -208,7 +164,6 @@ class RabbitMQEnableHostnameVerificationNotSet extends MethodAccess {
|
||||
|
||||
from MethodAccess aa
|
||||
where
|
||||
aa instanceof X509TrustAllManagerInit or
|
||||
aa instanceof SSLEndpointIdentificationNotSet or
|
||||
aa instanceof RabbitMQEnableHostnameVerificationNotSet
|
||||
select aa, "Unsafe configuration of trusted certificates"
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
public static void main(String[] args) throws Exception {
|
||||
{
|
||||
class InsecureTrustManager implements X509TrustManager {
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
// BAD: Does not verify the certificate chain, allowing any certificate.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
|
||||
}
|
||||
}
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
TrustManager[] trustManager = new TrustManager[] { new InsecureTrustManager() };
|
||||
context.init(null, trustManager, null);
|
||||
}
|
||||
{
|
||||
SSLContext context = SSLContext.getInstance("TLS");
|
||||
File certificateFile = new File("path/to/self-signed-certificate");
|
||||
// Create a `KeyStore` with default type
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
// `keyStore` is initially empty
|
||||
keyStore.load(null, null);
|
||||
X509Certificate generatedCertificate;
|
||||
try (InputStream cert = new FileInputStream(certificateFile)) {
|
||||
generatedCertificate = (X509Certificate) CertificateFactory.getInstance("X509")
|
||||
.generateCertificate(cert);
|
||||
}
|
||||
// Add the self-signed certificate to the key store
|
||||
keyStore.setCertificateEntry(certificateFile.getName(), generatedCertificate);
|
||||
// Get default `TrustManagerFactory`
|
||||
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
// Use it with our key store that trusts our self-signed certificate
|
||||
tmf.init(keyStore);
|
||||
TrustManager[] trustManagers = tmf.getTrustManagers();
|
||||
context.init(null, trustManagers, null);
|
||||
// GOOD, we are not using a custom `TrustManager` but instead have
|
||||
// added the self-signed certificate we want to trust to the key
|
||||
// store. Note, the `trustManagers` will **only** trust this one
|
||||
// certificate.
|
||||
|
||||
URL url = new URL("https://self-signed.badssl.com/");
|
||||
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
|
||||
conn.setSSLSocketFactory(context.getSocketFactory());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>
|
||||
If the <code>checkServerTrusted</code> method of a <code>TrustManager</code> never throws a <code>CertificateException</code> it trusts every certificate.
|
||||
This allows an attacker to perform a machine-in-the-middle attack against the application therefore breaking any security Transport Layer Security (TLS) gives.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
An attack might look like this:
|
||||
</p>
|
||||
|
||||
<ol>
|
||||
<li>The vulnerable program connects to <code>https://example.com</code>.</li>
|
||||
<li>The attacker intercepts this connection and presents a valid, self-signed certificate for <code>https://example.com</code>.</li>
|
||||
<li>The vulnerable program calls the <code>checkServerTrusted</code> method to check whether it should trust the certificate.</li>
|
||||
<li>The <code>checkServerTrusted</code> method of your <code>TrustManager</code> does not throw a <code>CertificateException</code>.</li>
|
||||
<li>The vulnerable program accepts the certificate and proceeds with the connection since your <code>TrustManager</code> implicitly trusted it by not throwing an exception.</li>
|
||||
<li>The attacker can now read the data your program sends to <code>https://example.com</code> and/or alter its replies while the program thinks the connection is secure.</li>
|
||||
</ol>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Do not use a custom <code>TrustManager</code> that trusts any certificate.
|
||||
If you have to use a self-signed certificate, don't trust every certificate, but instead only trust this specific certificate.
|
||||
See below for an example of how to do this.
|
||||
</p>
|
||||
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the first (bad) example, the <code>TrustManager</code> never throws a <code>CertificateException</code> and therefore implicitly trusts any certificate.
|
||||
This allows an attacker to perform a machine-in-the-middle attack.
|
||||
In the second (good) example, the self-signed certificate that should be trusted
|
||||
is loaded into a <code>KeyStore</code>. This explicitly defines the certificate as trusted and there is no need to create a custom <code>TrustManager</code>.
|
||||
</p>
|
||||
<sample src="InsecureTrustManager.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Android Develoers:<a href="https://developer.android.com/training/articles/security-ssl">Security with HTTPS and SSL</a>.</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user