Merge branch 'main' into atorralba/promote-ognl-injection

This commit is contained in:
Tony Torralba
2021-07-20 17:17:17 +02:00
2457 changed files with 219307 additions and 31173 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
*/

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
/**

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 &amp; 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>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View 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"

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -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)
)
}

View File

@@ -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(),

View File

@@ -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
}
}

View File

@@ -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>

View File

@@ -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"

View File

@@ -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)
}
}

View File

@@ -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());
}
}
}

View File

@@ -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 Users Guide: <a href="https://docs.oracle.com/en/java/javase/11/jshell/introduction-jshell.html">Introduction to JShell</a>
</li>
</references>
</qhelp>

View File

@@ -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"

View File

@@ -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
}
}

View File

@@ -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`. */

View File

@@ -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();

View File

@@ -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>

View File

@@ -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"

View File

@@ -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());
}
}

View File

@@ -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