Merge branch 'main' into java/UnsafeDeserialization

This commit is contained in:
haby0
2021-06-16 16:37:03 +08:00
committed by GitHub
2034 changed files with 74612 additions and 21269 deletions

View File

@@ -5,6 +5,7 @@
* @kind path-problem
* @precision low
* @problem.severity error
* @security-severity 5.9
* @tags security external/cwe/cwe-20
*/

View File

@@ -3,6 +3,7 @@
* @description Accessing paths influenced by users can allow an attacker to access unexpected resources.
* @kind path-problem
* @problem.severity error
* @security-severity 6.4
* @precision high
* @id java/path-injection
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Accessing paths influenced by users can allow an attacker to access unexpected resources.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 6.4
* @precision medium
* @id java/path-injection-local
* @tags security

View File

@@ -6,6 +6,7 @@
* @kind path-problem
* @id java/zipslip
* @problem.severity error
* @security-severity 6.4
* @precision high
* @tags security
* external/cwe/cwe-022
@@ -17,6 +18,7 @@ import semmle.code.java.dataflow.SSA
import semmle.code.java.dataflow.TaintTracking
import DataFlow
import PathGraph
private import semmle.code.java.dataflow.ExternalFlow
/**
* A method that returns the name of an archive entry.
@@ -33,34 +35,6 @@ class ArchiveEntryNameMethod extends Method {
}
}
/**
* An expression that will be treated as the destination of a write.
*/
class WrittenFileName extends Expr {
WrittenFileName() {
// Constructors that write to their first argument.
exists(ConstructorCall ctr | this = ctr.getArgument(0) |
exists(Class c | ctr.getConstructor() = c.getAConstructor() |
c.hasQualifiedName("java.io", "FileOutputStream") or
c.hasQualifiedName("java.io", "RandomAccessFile") or
c.hasQualifiedName("java.io", "FileWriter")
)
)
or
// Methods that write to their n'th argument
exists(MethodAccess call, int n | this = call.getArgument(n) |
call.getMethod().getDeclaringType().hasQualifiedName("java.nio.file", "Files") and
(
call.getMethod().getName().regexpMatch("new.*Reader|newOutputStream|create.*") and n = 0
or
call.getMethod().hasName("copy") and n = 1
or
call.getMethod().hasName("move") and n = 1
)
)
}
}
/**
* Holds if `n1` to `n2` is a dataflow step that converts between `String`,
* `File`, and `Path`.
@@ -151,7 +125,7 @@ class ZipSlipConfiguration extends TaintTracking::Configuration {
source.asExpr().(MethodAccess).getMethod() instanceof ArchiveEntryNameMethod
}
override predicate isSink(Node sink) { sink.asExpr() instanceof WrittenFileName }
override predicate isSink(Node sink) { sink instanceof FileCreationSink }
override predicate isAdditionalTaintStep(Node n1, Node n2) {
filePathStep(n1, n2) or fileTaintStep(n1, n2)
@@ -173,6 +147,13 @@ class ZipSlipConfiguration extends TaintTracking::Configuration {
}
}
/**
* A sink that represents a file creation, such as a file write, copy or move operation.
*/
private class FileCreationSink extends DataFlow::Node {
FileCreationSink() { sinkNode(this, "create-file") }
}
from PathNode source, PathNode sink
where any(ZipSlipConfiguration c).hasFlowPath(source, sink)
select source.getNode(), source, sink,

View File

@@ -4,6 +4,7 @@
* malicious changes in the PATH environment variable.
* @kind problem
* @problem.severity warning
* @security-severity 5.9
* @precision medium
* @id java/relative-path-command
* @tags security

View File

@@ -4,6 +4,7 @@
* changes in the strings.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/command-line-injection
* @tags security

View File

@@ -4,6 +4,7 @@
* changes in the strings.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 5.9
* @precision medium
* @id java/command-line-injection-local
* @tags security

View File

@@ -4,6 +4,7 @@
* insertion of special characters in the strings.
* @kind problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/concatenated-command-line
* @tags security

View File

@@ -4,6 +4,7 @@
* allows for a cross-site scripting vulnerability.
* @kind path-problem
* @problem.severity error
* @security-severity 2.9
* @precision high
* @id java/xss
* @tags security

View File

@@ -4,6 +4,7 @@
* allows for a cross-site scripting vulnerability.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 2.9
* @precision medium
* @id java/xss-local
* @tags security

View File

@@ -4,6 +4,7 @@
* malicious code by the user.
* @kind path-problem
* @problem.severity error
* @security-severity 6.4
* @precision high
* @id java/sql-injection
* @tags security

View File

@@ -4,6 +4,7 @@
* malicious code by the user.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 6.4
* @precision medium
* @id java/sql-injection-local
* @tags security

View File

@@ -4,6 +4,7 @@
* characters is vulnerable to insertion of malicious code.
* @kind problem
* @problem.severity error
* @security-severity 6.4
* @precision high
* @id java/concatenated-sql-query
* @tags security

View File

@@ -4,6 +4,7 @@
* malicious LDAP code by the user.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/ldap-injection
* @tags security

View File

@@ -3,6 +3,7 @@
* @description User-controlled data may be evaluated as a Java EL expression, leading to arbitrary code execution.
* @kind path-problem
* @problem.severity error
* @security-severity 10.0
* @precision high
* @id java/insecure-bean-validation
* @tags security
@@ -13,6 +14,7 @@ import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.dataflow.FlowSources
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
/**
* A message interpolator Type that perform Expression Language (EL) evaluations
@@ -50,19 +52,6 @@ class SetMessageInterpolatorCall extends MethodAccess {
predicate isSafe() { not this.getAnArgument().getType() instanceof ELMessageInterpolatorType }
}
/**
* A method named `buildConstraintViolationWithTemplate` declared on a subtype
* of `javax.validation.ConstraintValidatorContext`.
*/
class BuildConstraintViolationWithTemplateMethod extends Method {
BuildConstraintViolationWithTemplateMethod() {
this.getDeclaringType()
.getASupertype*()
.hasQualifiedName("javax.validation", "ConstraintValidatorContext") and
this.hasName("buildConstraintViolationWithTemplate")
}
}
/**
* Taint tracking BeanValidationConfiguration describing the flow of data from user input
* to the argument of a method that builds constraint error messages.
@@ -72,12 +61,15 @@ class BeanValidationConfig extends TaintTracking::Configuration {
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod() instanceof BuildConstraintViolationWithTemplateMethod and
sink.asExpr() = ma.getArgument(0)
)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof BeanValidationSink }
}
/**
* A bean validation sink, such as method `buildConstraintViolationWithTemplate`
* declared on a subtype of `javax.validation.ConstraintValidatorContext`.
*/
private class BeanValidationSink extends DataFlow::Node {
BeanValidationSink() { sinkNode(this, "bean-validation") }
}
from BeanValidationConfig cfg, DataFlow::PathNode source, DataFlow::PathNode sink

View File

@@ -0,0 +1,63 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>
Java EXpression Language (JEXL) is a simple expression language
provided by the Apache Commons JEXL library.
The syntax is close to a mix of ECMAScript and shell-script.
The language allows invocation of methods available in the JVM.
If a JEXL expression is built using attacker-controlled data,
and then evaluated, then it may allow the attacker to run arbitrary code.
</p>
</overview>
<recommendation>
<p>
It is generally recommended to avoid using untrusted input in a JEXL expression.
If it is not possible, JEXL expressions should be run in a sandbox that allows accessing only
explicitly allowed classes.
</p>
</recommendation>
<example>
<p>
The following example uses untrusted data to build and run a JEXL expression.
</p>
<sample src="UnsafeJexlExpressionEvaluation.java" />
<p>
The next example shows how an untrusted JEXL expression can be run
in a sandbox that allows accessing only methods in the <code>java.lang.Math</code> class.
The sandbox is implemented using <code>JexlSandbox</code> class that is provided by
Apache Commons JEXL 3.
</p>
<sample src="SaferJexlExpressionEvaluationWithSandbox.java" />
<p>
The next example shows another way how a sandbox can be implemented.
It uses a custom implementation of <code>JexlUberspect</code>
that checks if callees are instances of allowed classes.
</p>
<sample src="SaferJexlExpressionEvaluationWithUberspectSandbox.java" />
</example>
<references>
<li>
Apache Commons JEXL:
<a href="https://commons.apache.org/proper/commons-jexl/">Project page</a>.
</li>
<li>
Apache Commons JEXL documentation:
<a href="https://commons.apache.org/proper/commons-jexl/javadocs/apidocs-2.1.1/">JEXL 2.1.1 API</a>.
</li>
<li>
Apache Commons JEXL documentation:
<a href="https://commons.apache.org/proper/commons-jexl/apidocs/index.html">JEXL 3.1 API</a>.
</li>
<li>
OWASP:
<a href="https://owasp.org/www-community/vulnerabilities/Expression_Language_Injection">Expression Language Injection</a>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,38 @@
/**
* @name Expression language injection (JEXL)
* @description Evaluation of a user-controlled JEXL expression
* may lead to arbitrary code execution.
* @kind path-problem
* @problem.severity error
* @security-severity 10.0
* @precision high
* @id java/jexl-expression-injection
* @tags security
* external/cwe/cwe-094
*/
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.JexlInjection
import DataFlow::PathGraph
/**
* A taint-tracking configuration for unsafe user input
* that is used to construct and evaluate a JEXL expression.
* It supports both JEXL 2 and 3.
*/
class JexlInjectionConfig extends TaintTracking::Configuration {
JexlInjectionConfig() { this = "JexlInjectionConfig" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof JexlEvaluationSink }
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
any(JexlInjectionAdditionalTaintStep c).step(node1, node2)
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, JexlInjectionConfig conf
where conf.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "JEXL injection from $@.", source.getNode(), "this user input"

View File

@@ -0,0 +1,14 @@
public void evaluate(Socket socket) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
JexlSandbox onlyMath = new JexlSandbox(false);
onlyMath.white("java.lang.Math");
JexlEngine jexl = new JexlBuilder().sandbox(onlyMath).create();
String input = reader.readLine();
JexlExpression expression = jexl.createExpression(input);
JexlContext context = new MapContext();
expression.evaluate(context);
}
}

View File

@@ -0,0 +1,90 @@
public void evaluate(Socket socket) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
JexlUberspect sandbox = new JexlUberspectSandbox();
JexlEngine jexl = new JexlBuilder().uberspect(sandbox).create();
String input = reader.readLine();
JexlExpression expression = jexl.createExpression(input);
JexlContext context = new MapContext();
expression.evaluate(context);
}
private static class JexlUberspectSandbox implements JexlUberspect {
private static final List<String> ALLOWED_CLASSES =
Arrays.asList("java.lang.Math", "java.util.Random");
private final JexlUberspect uberspect = new JexlBuilder().create().getUberspect();
private void checkAccess(Object obj) {
if (!ALLOWED_CLASSES.contains(obj.getClass().getCanonicalName())) {
throw new AccessControlException("Not allowed");
}
}
@Override
public JexlMethod getMethod(Object obj, String method, Object... args) {
checkAccess(obj);
return uberspect.getMethod(obj, method, args);
}
@Override
public List<PropertyResolver> getResolvers(JexlOperator op, Object obj) {
checkAccess(obj);
return uberspect.getResolvers(op, obj);
}
@Override
public void setClassLoader(ClassLoader loader) {
uberspect.setClassLoader(loader);
}
@Override
public int getVersion() {
return uberspect.getVersion();
}
@Override
public JexlMethod getConstructor(Object obj, Object... args) {
checkAccess(obj);
return uberspect.getConstructor(obj, args);
}
@Override
public JexlPropertyGet getPropertyGet(Object obj, Object identifier) {
checkAccess(obj);
return uberspect.getPropertyGet(obj, identifier);
}
@Override
public JexlPropertyGet getPropertyGet(List<PropertyResolver> resolvers, Object obj, Object identifier) {
checkAccess(obj);
return uberspect.getPropertyGet(resolvers, obj, identifier);
}
@Override
public JexlPropertySet getPropertySet(Object obj, Object identifier, Object arg) {
checkAccess(obj);
return uberspect.getPropertySet(obj, identifier, arg);
}
@Override
public JexlPropertySet getPropertySet(List<PropertyResolver> resolvers, Object obj, Object identifier, Object arg) {
checkAccess(obj);
return uberspect.getPropertySet(resolvers, obj, identifier, arg);
}
@Override
public Iterator<?> getIterator(Object obj) {
checkAccess(obj);
return uberspect.getIterator(obj);
}
@Override
public JexlArithmetic.Uberspect getArithmetic(JexlArithmetic arithmetic) {
return uberspect.getArithmetic(arithmetic);
}
}
}

View File

@@ -0,0 +1,11 @@
public void evaluate(Socket socket) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
String input = reader.readLine();
JexlEngine jexl = new JexlBuilder().create();
JexlExpression expression = jexl.createExpression(input);
JexlContext context = new MapContext();
expression.evaluate(context);
}
}

View File

@@ -3,6 +3,7 @@
* @description Using a deprecated artifact repository may eventually give attackers access for a supply chain attack.
* @kind problem
* @problem.severity error
* @security-severity 6.5
* @precision very-high
* @id java/maven/dependency-upon-bintray
* @tags security

View File

@@ -5,6 +5,7 @@
* an HTTP header.
* @kind problem
* @problem.severity error
* @security-severity 3.6
* @precision high
* @id java/netty-http-response-splitting
* @tags security

View File

@@ -4,6 +4,7 @@
* makes code vulnerable to attack by header splitting.
* @kind path-problem
* @problem.severity error
* @security-severity 3.6
* @precision high
* @id java/http-response-splitting
* @tags security

View File

@@ -4,6 +4,7 @@
* makes code vulnerable to attack by header splitting.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 3.6
* @precision medium
* @id java/http-response-splitting-local
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Using unvalidated external input as the argument to a construction of an array can lead to index out of bound exceptions.
* @kind path-problem
* @problem.severity warning
* @security-severity 5.9
* @precision medium
* @id java/improper-validation-of-array-construction
* @tags security

View File

@@ -4,6 +4,7 @@
* a construction of an array can lead to index out of bound exceptions.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 5.9
* @precision medium
* @id java/improper-validation-of-array-construction-code-specified
* @tags security

View File

@@ -4,6 +4,7 @@
* a construction of an array can lead to index out of bound exceptions.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 5.9
* @precision medium
* @id java/improper-validation-of-array-construction-local
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Using external input as an index to an array, without proper validation, can lead to index out of bound exceptions.
* @kind path-problem
* @problem.severity warning
* @security-severity 5.9
* @precision medium
* @id java/improper-validation-of-array-index
* @tags security

View File

@@ -4,6 +4,7 @@
* proper validation, can lead to index out of bound exceptions.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 5.9
* @precision medium
* @id java/improper-validation-of-array-index-code-specified
* @tags security

View File

@@ -4,6 +4,7 @@
* proper validation, can lead to index out of bound exceptions.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 5.9
* @precision medium
* @id java/improper-validation-of-array-index-local
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Using external input in format strings can lead to exceptions or information leaks.
* @kind path-problem
* @problem.severity error
* @security-severity 6.9
* @precision high
* @id java/tainted-format-string
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Using external input in format strings can lead to exceptions or information leaks.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 6.9
* @precision medium
* @id java/tainted-format-string-local
* @tags security

View File

@@ -4,6 +4,7 @@
* overflows.
* @kind path-problem
* @problem.severity warning
* @security-severity 5.9
* @precision medium
* @id java/tainted-arithmetic
* @tags security

View File

@@ -4,6 +4,7 @@
* overflows.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 5.9
* @precision medium
* @id java/tainted-arithmetic-local
* @tags security

View File

@@ -4,6 +4,7 @@
* overflows.
* @kind path-problem
* @problem.severity warning
* @security-severity 5.9
* @precision medium
* @id java/uncontrolled-arithmetic
* @tags security

View File

@@ -4,6 +4,7 @@
* is then used in an arithmetic expression, this may result in an overflow.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 5.9
* @precision medium
* @id java/extreme-value-arithmetic
* @tags security

View File

@@ -4,6 +4,7 @@
* to behave unexpectedly.
* @kind problem
* @problem.severity warning
* @security-severity 5.9
* @precision medium
* @id java/comparison-with-wider-type
* @tags reliability

View File

@@ -5,6 +5,7 @@
* that are useful to an attacker for developing a subsequent exploit.
* @kind problem
* @problem.severity error
* @security-severity 3.6
* @precision high
* @id java/stack-trace-exposure
* @tags security
@@ -15,7 +16,7 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.XSS
import semmle.code.java.security.InformationLeak
/**
* One of the `printStackTrace()` overloads on `Throwable`.
@@ -79,19 +80,18 @@ predicate stackTraceExpr(Expr exception, MethodAccess stackTraceString) {
printStackCall.getAnArgument() = printWriter and
printStackCall.getQualifier() = exception and
stackTraceString.getQualifier() = stringWriterVar.getAnAccess() and
stackTraceString.getMethod().getName() = "toString" and
stackTraceString.getMethod().getNumberOfParameters() = 0
stackTraceString.getMethod() instanceof ToStringMethod
)
}
class StackTraceStringToXssSinkFlowConfig extends TaintTracking::Configuration {
StackTraceStringToXssSinkFlowConfig() {
this = "StackTraceExposure::StackTraceStringToXssSinkFlowConfig"
class StackTraceStringToHttpResponseSinkFlowConfig extends TaintTracking::Configuration {
StackTraceStringToHttpResponseSinkFlowConfig() {
this = "StackTraceExposure::StackTraceStringToHttpResponseSinkFlowConfig"
}
override predicate isSource(DataFlow::Node src) { stackTraceExpr(_, src.asExpr()) }
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
}
/**
@@ -106,8 +106,8 @@ predicate printsStackExternally(MethodAccess call, Expr stackTrace) {
/**
* A stringified stack trace flows to an external sink.
*/
predicate stringifiedStackFlowsExternally(XssSink externalExpr, Expr stackTrace) {
exists(MethodAccess stackTraceString, StackTraceStringToXssSinkFlowConfig conf |
predicate stringifiedStackFlowsExternally(DataFlow::Node externalExpr, Expr stackTrace) {
exists(MethodAccess stackTraceString, StackTraceStringToHttpResponseSinkFlowConfig conf |
stackTraceExpr(stackTrace, stackTraceString) and
conf.hasFlow(DataFlow::exprNode(stackTraceString), externalExpr)
)
@@ -124,21 +124,21 @@ class GetMessageFlowSource extends MethodAccess {
}
}
class GetMessageFlowSourceToXssSinkFlowConfig extends TaintTracking::Configuration {
GetMessageFlowSourceToXssSinkFlowConfig() {
this = "StackTraceExposure::GetMessageFlowSourceToXssSinkFlowConfig"
class GetMessageFlowSourceToHttpResponseSinkFlowConfig extends TaintTracking::Configuration {
GetMessageFlowSourceToHttpResponseSinkFlowConfig() {
this = "StackTraceExposure::GetMessageFlowSourceToHttpResponseSinkFlowConfig"
}
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof GetMessageFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof XssSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof InformationLeakSink }
}
/**
* A call to `getMessage()` that then flows to a servlet response.
*/
predicate getMessageFlowsExternally(XssSink externalExpr, GetMessageFlowSource getMessage) {
any(GetMessageFlowSourceToXssSinkFlowConfig conf)
predicate getMessageFlowsExternally(DataFlow::Node externalExpr, GetMessageFlowSource getMessage) {
any(GetMessageFlowSourceToHttpResponseSinkFlowConfig conf)
.hasFlow(DataFlow::exprNode(getMessage), externalExpr)
}

View File

@@ -3,6 +3,7 @@
* @description Marking a certificate as valid for a host without checking the certificate hostname allows an attacker to perform a machine-in-the-middle attack.
* @kind path-problem
* @problem.severity error
* @security-severity 4.9
* @precision high
* @id java/unsafe-hostname-verification
* @tags security
@@ -15,6 +16,7 @@ import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.Encryption
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
/**
* Holds if `m` always returns `true` ignoring any exceptional flow.
@@ -49,14 +51,7 @@ class TrustAllHostnameVerifierConfiguration extends DataFlow::Configuration {
source.asExpr().(ClassInstanceExpr).getConstructedType() instanceof TrustAllHostnameVerifier
}
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma, Method m |
(m instanceof SetDefaultHostnameVerifierMethod or m instanceof SetHostnameVerifierMethod) and
ma.getMethod() = m
|
ma.getArgument(0) = sink.asExpr()
)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof HostnameVerifierSink }
override predicate isBarrier(DataFlow::Node barrier) {
// ignore nodes that are in functions that intentionally disable hostname verification
@@ -84,6 +79,13 @@ class TrustAllHostnameVerifierConfiguration extends DataFlow::Configuration {
}
}
/**
* A sink that sets the `HostnameVerifier` on `HttpsURLConnection`.
*/
private class HostnameVerifierSink extends DataFlow::Node {
HostnameVerifierSink() { sinkNode(this, "set-hostname-verifier") }
}
bindingset[result]
private string getAFlagName() {
result

View File

@@ -3,6 +3,7 @@
* @description Storing sensitive information in cleartext can expose it to an attacker.
* @kind problem
* @problem.severity recommendation
* @security-severity 5.9
* @precision medium
* @id java/cleartext-storage-in-class
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Storing sensitive information in cleartext can expose it to an attacker.
* @kind problem
* @problem.severity error
* @security-severity 2.9
* @precision high
* @id java/cleartext-storage-in-cookie
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Storing sensitive information in cleartext can expose it to an attacker.
* @kind problem
* @problem.severity warning
* @security-severity 6.4
* @precision medium
* @id java/cleartext-storage-in-properties
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Non-HTTPS connections can be intercepted by third parties.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 5.2
* @precision medium
* @id java/non-https-url
* @tags security
@@ -13,9 +14,10 @@ import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.Networking
import DataFlow::PathGraph
private import semmle.code.java.dataflow.ExternalFlow
class HTTPString extends StringLiteral {
HTTPString() {
class HttpString extends StringLiteral {
HttpString() {
// Avoid matching "https" here.
exists(string s | this.getRepresentedString() = s |
(
@@ -30,26 +32,12 @@ class HTTPString extends StringLiteral {
}
}
class URLOpenMethod extends Method {
URLOpenMethod() {
this.getDeclaringType().getQualifiedName() = "java.net.URL" and
(
this.getName() = "openConnection" or
this.getName() = "openStream"
)
}
}
class HttpStringToUrlOpenMethodFlowConfig extends TaintTracking::Configuration {
HttpStringToUrlOpenMethodFlowConfig() { this = "HttpsUrls::HttpStringToUrlOpenMethodFlowConfig" }
class HTTPStringToURLOpenMethodFlowConfig extends TaintTracking::Configuration {
HTTPStringToURLOpenMethodFlowConfig() { this = "HttpsUrls::HTTPStringToURLOpenMethodFlowConfig" }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof HttpString }
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof HTTPString }
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess m |
sink.asExpr() = m.getQualifier() and m.getMethod() instanceof URLOpenMethod
)
}
override predicate isSink(DataFlow::Node sink) { sink instanceof UrlOpenSink }
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(UrlConstructorCall u |
@@ -63,10 +51,17 @@ class HTTPStringToURLOpenMethodFlowConfig extends TaintTracking::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess m, HTTPString s
/**
* A sink that represents a URL opening method call, such as a call to `java.net.URL.openConnection()`.
*/
private class UrlOpenSink extends DataFlow::Node {
UrlOpenSink() { sinkNode(this, "open-url") }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess m, HttpString s
where
source.getNode().asExpr() = s and
sink.getNode().asExpr() = m.getQualifier() and
any(HTTPStringToURLOpenMethodFlowConfig c).hasFlowPath(source, sink)
any(HttpStringToUrlOpenMethodFlowConfig c).hasFlowPath(source, sink)
select m, source, sink, "URL may have been constructed with HTTP protocol, using $@.", s,
"this source"

View File

@@ -3,6 +3,7 @@
* @description Non-SSL connections can be intercepted by third parties.
* @kind problem
* @problem.severity recommendation
* @security-severity 5.2
* @precision medium
* @id java/non-ssl-connection
* @tags security

View File

@@ -4,6 +4,7 @@
* third parties.
* @kind problem
* @problem.severity recommendation
* @security-severity 5.2
* @precision medium
* @id java/non-ssl-socket-factory
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Using broken or weak cryptographic algorithms can allow an attacker to compromise security.
* @kind path-problem
* @problem.severity warning
* @security-severity 5.2
* @precision high
* @id java/weak-cryptographic-algorithm
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Using broken or weak cryptographic algorithms can allow an attacker to compromise security.
* @kind path-problem
* @problem.severity warning
* @security-severity 5.2
* @precision medium
* @id java/potentially-weak-cryptographic-algorithm
* @tags security
@@ -33,9 +34,8 @@ class InsecureAlgoLiteral extends ShortStringLiteral {
}
predicate objectToString(MethodAccess ma) {
exists(Method m |
exists(ToStringMethod m |
m = ma.getMethod() and
m.hasName("toString") and
m.getDeclaringType() instanceof TypeObject and
variableTrack(ma.getQualifier()).getType().getErasure() instanceof TypeObject
)

View File

@@ -3,9 +3,11 @@
* @description Using a predictable seed in a pseudo-random number generator can lead to predictability of the numbers generated by it.
* @kind problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/predictable-seed
* @tags security
* external/cwe/cwe-335
*/
import java

View File

@@ -3,6 +3,7 @@
* @description Using a vulnerable version of JHipster to generate random numbers makes it easier for attackers to take over accounts.
* @kind problem
* @problem.severity error
* @security-severity 5.9
* @precision very-high
* @id java/jhipster-prng
* @tags security

View File

@@ -4,6 +4,7 @@
* a Cross-Site Request Forgery (CSRF) attack.
* @kind problem
* @problem.severity error
* @security-severity 6.4
* @precision high
* @id java/spring-disabled-csrf-protection
* @tags security

View File

@@ -4,6 +4,7 @@
* if the state may be changed between the check and use.
* @kind problem
* @problem.severity warning
* @security-severity 5.9
* @precision medium
* @id java/toctou-race-condition
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Opening a socket after authenticating via a different channel may allow an attacker to connect to the port first.
* @kind problem
* @problem.severity warning
* @security-severity 10.0
* @precision medium
* @id java/socket-auth-race-condition
* @tags security

View File

@@ -69,7 +69,7 @@ Or How I Learned to Start Worrying and Hate Java Object Deserialization</a>.
</li>
<li>
Alvaro Muñoz &amp; Christian Schneider, RSAConference 2016:
<a href="https://www.rsaconference.com/writable/presentations/file_upload/asd-f03-serial-killer-silently-pwning-your-java-endpoints.pdf">Serial Killer: Silently Pwning Your Java Endpoints</a>.
<a href="https://speakerdeck.com/pwntester/serial-killer-silently-pwning-your-java-endpoints">Serial Killer: Silently Pwning Your Java Endpoints</a>.
</li>
<li>
SnakeYaml documentation on deserialization:

View File

@@ -4,6 +4,7 @@
* execute arbitrary code.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/unsafe-deserialization
* @tags security

View File

@@ -4,6 +4,7 @@
* may cause redirection to malicious web sites.
* @kind path-problem
* @problem.severity error
* @security-severity 2.7
* @precision high
* @id java/unvalidated-url-redirection
* @tags security

View File

@@ -4,6 +4,7 @@
* may cause redirection to malicious web sites.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 2.7
* @precision medium
* @id java/unvalidated-url-redirection-local
* @tags security

View File

@@ -56,11 +56,11 @@ OWASP guidance on parsing xml files:
</li>
<li>
Paper by Timothy Morgen:
<a href="https://www.vsecurity.com//download/publications/XMLDTDEntityAttacks.pdf">XML Schema, DTD, and Entity Attacks</a>
<a href="https://research.nccgroup.com/2014/05/19/xml-schema-dtd-and-entity-attacks-a-compendium-of-known-techniques/">XML Schema, DTD, and Entity Attacks</a>
</li>
<li>
Out-of-band data retrieval: Timur Yunusov &amp; Alexey Osipov, Black hat EU 2013:
<a href="https://media.blackhat.com/eu-13/briefings/Osipov/bh-eu-13-XML-data-osipov-slides.pdf">XML Out-Of-Band Data Retrieval</a>.
<a href="https://www.slideshare.net/qqlan/bh-ready-v4">XML Out-Of-Band Data Retrieval</a>.
</li>
<li>
Denial of service attack (Billion laughs):

View File

@@ -4,6 +4,7 @@
* references may lead to disclosure of confidential data or denial of service.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/xxe
* @tags security

View File

@@ -4,6 +4,7 @@
* interception.
* @kind problem
* @problem.severity error
* @security-severity 2.9
* @precision high
* @id java/insecure-cookie
* @tags security

View File

@@ -0,0 +1,83 @@
final String xmlStr = "<users>" +
" <user name=\"aaa\" pass=\"pass1\"></user>" +
" <user name=\"bbb\" pass=\"pass2\"></user>" +
"</users>";
try {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
//Document doc = builder.parse("user.xml");
Document doc = builder.parse(new InputSource(new StringReader(xmlStr)));
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
// Injectable data
String user = request.getParameter("user");
String pass = request.getParameter("pass");
if (user != null && pass != null) {
boolean isExist = false;
// Bad expression
String expression1 = "/users/user[@name='" + user + "' and @pass='" + pass + "']";
isExist = (boolean)xpath.evaluate(expression1, doc, XPathConstants.BOOLEAN);
System.out.println(isExist);
// Bad expression
XPathExpression expression2 = xpath.compile("/users/user[@name='" + user + "' and @pass='" + pass + "']");
isExist = (boolean)expression2.evaluate(doc, XPathConstants.BOOLEAN);
System.out.println(isExist);
// Bad expression
StringBuffer sb = new StringBuffer("/users/user[@name=");
sb.append(user);
sb.append("' and @pass='");
sb.append(pass);
sb.append("']");
String query = sb.toString();
XPathExpression expression3 = xpath.compile(query);
isExist = (boolean)expression3.evaluate(doc, XPathConstants.BOOLEAN);
System.out.println(isExist);
// Good expression
String expression4 = "/users/user[@name=$user and @pass=$pass]";
xpath.setXPathVariableResolver(v -> {
switch (v.getLocalPart()) {
case "user":
return user;
case "pass":
return pass;
default:
throw new IllegalArgumentException();
}
});
isExist = (boolean)xpath.evaluate(expression4, doc, XPathConstants.BOOLEAN);
System.out.println(isExist);
// Bad Dom4j
org.dom4j.io.SAXReader reader = new org.dom4j.io.SAXReader();
org.dom4j.Document document = reader.read(new InputSource(new StringReader(xmlStr)));
isExist = document.selectSingleNode("/users/user[@name='" + user + "' and @pass='" + pass + "']") != null;
// or document.selectNodes
System.out.println(isExist);
// Good Dom4j
org.jaxen.SimpleVariableContext svc = new org.jaxen.SimpleVariableContext();
svc.setVariableValue("user", user);
svc.setVariableValue("pass", pass);
String xpathString = "/users/user[@name=$user and @pass=$pass]";
org.dom4j.XPath safeXPath = document.createXPath(xpathString);
safeXPath.setVariableContext(svc);
isExist = safeXPath.selectSingleNode(document) != null;
System.out.println(isExist);
}
} catch (ParserConfigurationException e) {
} catch (SAXException e) {
} catch (XPathExpressionException e) {
} catch (org.dom4j.DocumentException e) {
}

View File

@@ -0,0 +1,44 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>
If an XPath expression is built using string concatenation, and the components of the concatenation
include user input, it makes it very easy for a user to create a malicious XPath expression.
</p>
</overview>
<recommendation>
<p>
If user input must be included in an XPath expression, either sanitize the data or pre-compile the query
and use variable references to include the user input.
</p>
<p>
XPath injection can also be prevented by using XQuery.
</p>
</recommendation>
<example>
<p>
In the first three examples, the code accepts a name and password specified by the user, and uses this
unvalidated and unsanitized value in an XPath expression. This is vulnerable to the user providing
special characters or string sequences that change the meaning of the XPath expression to search
for different values.
</p>
<p>
In the fourth example, the code uses <code>setXPathVariableResolver</code> which prevents XPath injection.
</p>
<p>
The final two examples are for dom4j. They show an example of XPath injection and one method of preventing it.
</p>
<sample src="XPathInjection.java" />
</example>
<references>
<li>OWASP: <a href="https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/09-Testing_for_XPath_Injection">Testing for XPath Injection</a>.</li>
<li>OWASP: <a href="https://owasp.org/www-community/attacks/XPATH_Injection">XPath Injection</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,31 @@
/**
* @name XPath injection
* @description Building an XPath expression from user-controlled sources is vulnerable to insertion of
* malicious code by the user.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/xml/xpath-injection
* @tags security
* external/cwe/cwe-643
*/
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.XPath
import DataFlow::PathGraph
class XPathInjectionConfiguration extends TaintTracking::Configuration {
XPathInjectionConfiguration() { this = "XPathInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof XPathInjectionSink }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, XPathInjectionConfiguration c
where c.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ flows to here and is used in an XPath expression.",
source.getNode(), "User-provided value"

View File

@@ -3,6 +3,7 @@
* @description Certain standard library routines are dangerous to call.
* @kind problem
* @problem.severity warning
* @security-severity 10.0
* @precision medium
* @id java/potentially-dangerous-function
* @tags reliability

View File

@@ -4,6 +4,7 @@
* can cause unexpected truncation.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/tainted-numeric-cast
* @tags security

View File

@@ -4,6 +4,7 @@
* can cause unexpected truncation.
* @kind path-problem
* @problem.severity recommendation
* @security-severity 5.9
* @precision medium
* @id java/tainted-numeric-cast-local
* @tags security

View File

@@ -4,6 +4,7 @@
* the file may be modified or removed by external actors.
* @kind problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/world-writable-file-read
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Using a hard-coded credential in a call to a sensitive Java API may compromise security.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision medium
* @id java/hardcoded-credential-api-call
* @tags security
@@ -19,14 +20,14 @@ class HardcodedCredentialApiCallConfiguration extends DataFlow::Configuration {
override predicate isSource(DataFlow::Node n) {
n.asExpr() instanceof HardcodedExpr and
not n.asExpr().getEnclosingCallable().getName() = "toString"
not n.asExpr().getEnclosingCallable() instanceof ToStringMethod
}
override predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsApiSink }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
node1.asExpr().getType() instanceof TypeString and
exists(MethodAccess ma | ma.getMethod().getName().regexpMatch("getBytes|toCharArray") |
exists(MethodAccess ma | ma.getMethod().hasName(["getBytes", "toCharArray"]) |
node2.asExpr() = ma and
ma.getQualifier() = node1.asExpr()
)

View File

@@ -3,6 +3,7 @@
* @description Comparing a parameter to a hard-coded credential may compromise security.
* @kind problem
* @problem.severity error
* @security-severity 5.9
* @precision low
* @id java/hardcoded-credential-comparison
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Using a hard-coded credential in a sensitive call may compromise security.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision low
* @id java/hardcoded-credential-sensitive-call
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Hard-coding a password string may compromise security.
* @kind problem
* @problem.severity error
* @security-severity 5.9
* @precision low
* @id java/hardcoded-password-field
* @tags security

View File

@@ -4,6 +4,7 @@
* passing through authentication systems.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision medium
* @id java/user-controlled-bypass
* @tags security

View File

@@ -4,6 +4,7 @@
* permissions being granted.
* @kind path-problem
* @problem.severity error
* @security-severity 5.9
* @precision high
* @id java/tainted-permissions-check
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Non-HTTPS connections can be intercepted by third parties.
* @kind problem
* @problem.severity error
* @security-severity 5.9
* @precision very-high
* @id java/maven/non-https-url
* @tags security

View File

@@ -3,6 +3,7 @@
* @description Acquiring multiple locks in a different order may cause deadlock.
* @kind problem
* @problem.severity recommendation
* @security-severity 6.9
* @precision medium
* @id java/lock-order-inconsistency
* @tags security

View File

@@ -5,6 +5,7 @@
* looping.
* @kind problem
* @problem.severity warning
* @security-severity 3.6
* @precision medium
* @id java/unreachable-exit-in-loop
* @tags security