Merge remote-tracking branch 'upstream/main' into main

This commit is contained in:
haby0
2021-02-16 17:54:01 +08:00
928 changed files with 92594 additions and 12306 deletions

View File

@@ -0,0 +1,23 @@
public static void main(String[] args) {
{
Browser browser = new Browser();
browser.loadURL("https://example.com");
// no further calls
// BAD: The browser ignores any certificate error by default!
}
{
Browser browser = new Browser();
browser.setLoadHandler(new LoadHandler() {
public boolean onLoad(LoadParams params) {
return true;
}
public boolean onCertificateError(CertificateErrorParams params){
return true; // GOOD: This means that loading will be cancelled on certificate errors
}
}); // GOOD: A secure `LoadHandler` is used.
browser.loadURL("https://example.com");
}
}

View File

@@ -0,0 +1,32 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<p>JxBrowser is a Java library that allows to embed the Chromium browser inside Java applications.
Versions smaller than 6.24 by default ignore any HTTPS certificate errors thereby allowing man-in-the-middle attacks.
</p>
</overview>
<recommendation>
<p>Do either of these:</p>
<ul>
<li>Update to version 6.24 or 7.x.x as these correctly reject certificate errors by default.</li>
<li>Add a custom implementation of the <code>LoadHandler</code> interface whose <code>onCertificateError</code> method always returns <b>true</b> indicating that loading should be cancelled.
Then use the <code>setLoadHandler</code> method with your custom <code>LoadHandler</code> on every <code>Browser</code> you use.</li>
</ul>
</recommendation>
<example>
<p>The following two examples show two ways of using a <code>Browser</code>. In the 'BAD' case,
all certificate errors are ignored. In the 'GOOD' case, certificate errors are rejected.</p>
<sample src="JxBrowserWithoutCertValidation.java" />
</example>
<references>
<li>Teamdev:
<a href="https://jxbrowser.support.teamdev.com/support/discussions/topics/9000051708">
Changelog of JxBrowser 6.24</a>.</li>
</references>
</qhelp>

View File

@@ -0,0 +1,86 @@
/**
* @name JxBrowser with disabled certificate validation
* @description Insecure configuration of JxBrowser disables certificate validation making the app vulnerable to man-in-the-middle attacks.
* @kind problem
* @id java/jxbrowser/disabled-certificate-validation
* @tags security
* external/cwe/cwe-295
*/
import java
import semmle.code.java.security.Encryption
import semmle.code.java.dataflow.DataFlow
/*
* This query is version specific to JxBrowser < 6.24. The version is indirectly detected.
* In version 6.x.x the `Browser` class is in a different package compared to version 7.x.x.
*/
/**
* Holds if a safe JxBrowser 6.x.x version is used, such as version 6.24.
* This is detected by the the presence of the `addBoundsListener` in the `Browser` class.
*/
private predicate isSafeJxBrowserVersion() {
exists(Method m | m.getDeclaringType() instanceof JxBrowser | m.hasName("addBoundsListener"))
}
/** The `com.teamdev.jxbrowser.chromium.Browser` class. */
private class JxBrowser extends RefType {
JxBrowser() { this.hasQualifiedName("com.teamdev.jxbrowser.chromium", "Browser") }
}
/** The `setLoadHandler` method on the `com.teamdev.jxbrowser.chromium.Browser` class. */
private class JxBrowserSetLoadHandler extends Method {
JxBrowserSetLoadHandler() {
this.hasName("setLoadHandler") and this.getDeclaringType() instanceof JxBrowser
}
}
/** The `com.teamdev.jxbrowser.chromium.LoadHandler` interface. */
private class JxBrowserLoadHandler extends RefType {
JxBrowserLoadHandler() { this.hasQualifiedName("com.teamdev.jxbrowser.chromium", "LoadHandler") }
}
private predicate isOnCertificateErrorMethodSafe(Method m) {
forex(ReturnStmt rs | rs.getEnclosingCallable() = m |
rs.getResult().(CompileTimeConstantExpr).getBooleanValue() = true
)
}
/** A class that securely implements the `com.teamdev.jxbrowser.chromium.LoadHandler` interface. */
private class JxBrowserSafeLoadHandler extends RefType {
JxBrowserSafeLoadHandler() {
this.getASupertype() instanceof JxBrowserLoadHandler and
exists(Method m | m.hasName("onCertificateError") and m.getDeclaringType() = this |
isOnCertificateErrorMethodSafe(m)
)
}
}
/**
* Models flow from the source `new Browser()` to a sink `browser.setLoadHandler(loadHandler)` where `loadHandler`
* has been determined to be safe.
*/
private class JxBrowserFlowConfiguration extends DataFlow::Configuration {
JxBrowserFlowConfiguration() { this = "JxBrowserFlowConfiguration" }
override predicate isSource(DataFlow::Node src) {
exists(ClassInstanceExpr newJxBrowser | newJxBrowser.getConstructedType() instanceof JxBrowser |
newJxBrowser = src.asExpr()
)
}
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma | ma.getMethod() instanceof JxBrowserSetLoadHandler |
ma.getArgument(0).getType() instanceof JxBrowserSafeLoadHandler and
ma.getQualifier() = sink.asExpr()
)
}
}
from JxBrowserFlowConfiguration cfg, DataFlow::Node src
where
cfg.isSource(src) and
not cfg.hasFlow(src, _) and
not isSafeJxBrowserVersion()
select src, "This JxBrowser instance may not check HTTPS certificates."

View File

@@ -0,0 +1,37 @@
public class InsufficientKeySize {
public void CryptoMethod() {
KeyGenerator keyGen1 = KeyGenerator.getInstance("AES");
// BAD: Key size is less than 128
keyGen1.init(64);
KeyGenerator keyGen2 = KeyGenerator.getInstance("AES");
// GOOD: Key size is no less than 128
keyGen2.init(128);
KeyPairGenerator keyPairGen1 = KeyPairGenerator.getInstance("RSA");
// BAD: Key size is less than 2048
keyPairGen1.initialize(1024);
KeyPairGenerator keyPairGen2 = KeyPairGenerator.getInstance("RSA");
// GOOD: Key size is no less than 2048
keyPairGen2.initialize(2048);
KeyPairGenerator keyPairGen3 = KeyPairGenerator.getInstance("DSA");
// BAD: Key size is less than 2048
keyPairGen3.initialize(1024);
KeyPairGenerator keyPairGen4 = KeyPairGenerator.getInstance("DSA");
// GOOD: Key size is no less than 2048
keyPairGen4.initialize(2048);
KeyPairGenerator keyPairGen5 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 256
ECGenParameterSpec ecSpec1 = new ECGenParameterSpec("secp112r1");
keyPairGen5.initialize(ecSpec1);
KeyPairGenerator keyPairGen6 = KeyPairGenerator.getInstance("EC");
// GOOD: Key size is no less than 256
ECGenParameterSpec ecSpec2 = new ECGenParameterSpec("secp256r1");
keyPairGen6.initialize(ecSpec2);
}
}

View File

@@ -0,0 +1,29 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>This rule finds uses of encryption algorithms with too small a key size. Encryption algorithms
are vulnerable to brute force attack when too small a key size is used.</p>
</overview>
<recommendation>
<p>The key should be at least 2048 bits long when using RSA and DSA encryption, 256 bits long when using EC encryption, and 128 bits long when using
symmetric encryption.</p>
</recommendation>
<references>
<li>
Wikipedia.
<a href="http://en.wikipedia.org/wiki/Key_size">Key size</a>
</li>
<li>
SonarSource.
<a href="https://rules.sonarsource.com/java/type/Vulnerability/RSPEC-4426">Cryptographic keys should be robust</a>
</li>
<li>
CWE.
<a href="https://cwe.mitre.org/data/definitions/326.html">CWE-326: Inadequate Encryption Strength</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,151 @@
/**
* @name Weak encryption: Insufficient key size
* @description Finds uses of encryption algorithms with too small a key size
* @kind problem
* @id java/insufficient-key-size
* @tags security
* external/cwe/cwe-326
*/
import java
import semmle.code.java.security.Encryption
import semmle.code.java.dataflow.TaintTracking
/** The Java class `java.security.spec.ECGenParameterSpec`. */
class ECGenParameterSpec extends RefType {
ECGenParameterSpec() { this.hasQualifiedName("java.security.spec", "ECGenParameterSpec") }
}
/** The `init` method declared in `javax.crypto.KeyGenerator`. */
class KeyGeneratorInitMethod extends Method {
KeyGeneratorInitMethod() {
getDeclaringType() instanceof KeyGenerator and
hasName("init")
}
}
/** The `initialize` method declared in `java.security.KeyPairGenerator`. */
class KeyPairGeneratorInitMethod extends Method {
KeyPairGeneratorInitMethod() {
getDeclaringType() instanceof KeyPairGenerator and
hasName("initialize")
}
}
/** Returns the key size in the EC algorithm string */
bindingset[algorithm]
int getECKeySize(string algorithm) {
algorithm.matches("sec%") and // specification such as "secp256r1"
result = algorithm.regexpCapture("sec[p|t](\\d+)[a-zA-Z].*", 1).toInt()
or
algorithm.matches("X9.62%") and //specification such as "X9.62 prime192v2"
result = algorithm.regexpCapture("X9\\.62 .*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt()
or
(algorithm.matches("prime%") or algorithm.matches("c2tnb%")) and //specification such as "prime192v2"
result = algorithm.regexpCapture(".*[a-zA-Z](\\d+)[a-zA-Z].*", 1).toInt()
}
/** Taint configuration tracking flow from a key generator to a `init` method call. */
class KeyGeneratorInitConfiguration extends TaintTracking::Configuration {
KeyGeneratorInitConfiguration() { this = "KeyGeneratorInitConfiguration" }
override predicate isSource(DataFlow::Node source) {
exists(JavaxCryptoKeyGenerator jcg | jcg = source.asExpr())
}
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod() instanceof KeyGeneratorInitMethod and
sink.asExpr() = ma.getQualifier()
)
}
}
/** Taint configuration tracking flow from a keypair generator to a `initialize` method call. */
class KeyPairGeneratorInitConfiguration extends TaintTracking::Configuration {
KeyPairGeneratorInitConfiguration() { this = "KeyPairGeneratorInitConfiguration" }
override predicate isSource(DataFlow::Node source) {
exists(JavaSecurityKeyPairGenerator jkg | jkg = source.asExpr())
}
override predicate isSink(DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
sink.asExpr() = ma.getQualifier()
)
}
}
/** Holds if a symmetric `KeyGenerator` implementing encryption algorithm `type` and initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */
bindingset[type]
predicate hasShortSymmetricKey(MethodAccess ma, string msg, string type) {
ma.getMethod() instanceof KeyGeneratorInitMethod and
exists(
JavaxCryptoKeyGenerator jcg, KeyGeneratorInitConfiguration cc, DataFlow::PathNode source,
DataFlow::PathNode dest
|
jcg.getAlgoSpec().(StringLiteral).getValue() = type and
source.getNode().asExpr() = jcg and
dest.getNode().asExpr() = ma.getQualifier() and
cc.hasFlowPath(source, dest)
) and
ma.getArgument(0).(IntegerLiteral).getIntValue() < 128 and
msg = "Key size should be at least 128 bits for " + type + " encryption."
}
/** Holds if an AES `KeyGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */
predicate hasShortAESKey(MethodAccess ma, string msg) { hasShortSymmetricKey(ma, msg, "AES") }
/** Holds if an asymmetric `KeyPairGenerator` implementing encryption algorithm `type` and initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */
bindingset[type]
predicate hasShortAsymmetricKeyPair(MethodAccess ma, string msg, string type) {
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
exists(
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc,
DataFlow::PathNode source, DataFlow::PathNode dest
|
jpg.getAlgoSpec().(StringLiteral).getValue().toUpperCase() = type and
source.getNode().asExpr() = jpg and
dest.getNode().asExpr() = ma.getQualifier() and
kc.hasFlowPath(source, dest)
) and
ma.getArgument(0).(IntegerLiteral).getIntValue() < 2048 and
msg = "Key size should be at least 2048 bits for " + type + " encryption."
}
/** Holds if a DSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */
predicate hasShortDSAKeyPair(MethodAccess ma, string msg) {
hasShortAsymmetricKeyPair(ma, msg, "DSA") or hasShortAsymmetricKeyPair(ma, msg, "DH")
}
/** Holds if a RSA `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */
predicate hasShortRSAKeyPair(MethodAccess ma, string msg) {
hasShortAsymmetricKeyPair(ma, msg, "RSA")
}
/** Holds if an EC `KeyPairGenerator` initialized by `ma` uses an insufficient key size. `msg` provides a human-readable description of the problem. */
predicate hasShortECKeyPair(MethodAccess ma, string msg) {
ma.getMethod() instanceof KeyPairGeneratorInitMethod and
exists(
JavaSecurityKeyPairGenerator jpg, KeyPairGeneratorInitConfiguration kc,
DataFlow::PathNode source, DataFlow::PathNode dest, ClassInstanceExpr cie
|
jpg.getAlgoSpec().(StringLiteral).getValue().matches("EC%") and // ECC variants such as ECDH and ECDSA
source.getNode().asExpr() = jpg and
dest.getNode().asExpr() = ma.getQualifier() and
kc.hasFlowPath(source, dest) and
DataFlow::localExprFlow(cie, ma.getArgument(0)) and
ma.getArgument(0).getType() instanceof ECGenParameterSpec and
getECKeySize(cie.getArgument(0).(StringLiteral).getRepresentedString()) < 256
) and
msg = "Key size should be at least 256 bits for EC encryption."
}
from Expr e, string msg
where
hasShortAESKey(e, msg) or
hasShortDSAKeyPair(e, msg) or
hasShortRSAKeyPair(e, msg) or
hasShortECKeyPair(e, msg)
select e, msg

View File

@@ -14,14 +14,6 @@ import semmle.code.java.frameworks.ApacheHttp
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
/**
* Gets a regular expression for matching private hosts, which only matches the host portion therefore checking for port is not necessary.
*/
private string getPrivateHostRegex() {
result =
"(?i)localhost(?:[:/?#].*)?|127\\.0\\.0\\.1(?:[:/?#].*)?|10(?:\\.[0-9]+){3}(?:[:/?#].*)?|172\\.16(?:\\.[0-9]+){2}(?:[:/?#].*)?|192.168(?:\\.[0-9]+){2}(?:[:/?#].*)?|\\[?0:0:0:0:0:0:0:1\\]?(?:[:/?#].*)?|\\[?::1\\]?(?:[:/?#].*)?"
}
/**
* Class of Java URL constructor.
*/
@@ -76,7 +68,7 @@ class HttpStringLiteral extends StringLiteral {
// Match URLs with the HTTP protocol and without private IP addresses to reduce false positives.
exists(string s | this.getRepresentedString() = s |
s.regexpMatch("(?i)http://[\\[a-zA-Z0-9].*") and
not s.substring(7, s.length()).regexpMatch(getPrivateHostRegex())
not s.substring(7, s.length()) instanceof PrivateHostName
)
}
}
@@ -101,7 +93,7 @@ predicate concatHttpString(Expr protocol, Expr host) {
host.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue()
|
hostString.length() = 0 or // Empty host is loopback address
hostString.regexpMatch(getPrivateHostRegex())
hostString instanceof PrivateHostName
)
}

View File

@@ -0,0 +1,24 @@
public class InsecureLdapAuth {
/** LDAP authentication */
public DirContext ldapAuth(String ldapUserName, String password) {
{
// BAD: LDAP authentication in cleartext
String ldapUrl = "ldap://ad.your-server.com:389";
}
{
// GOOD: LDAPS authentication over SSL
String ldapUrl = "ldaps://ad.your-server.com:636";
}
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);
return dirContext;
}
}

View File

@@ -0,0 +1,27 @@
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
<qhelp>
<overview>
<p>When using the Java LDAP API to perform LDAPv3-style extended operations and controls, a context with connection properties including user credentials is started. Transmission of LDAP credentials in cleartext allows remote attackers to obtain sensitive information by sniffing the network.</p>
</overview>
<recommendation>
<p>Use LDAPS to send credentials through SSL or use SASL authentication.</p>
</recommendation>
<example>
<p>The following example shows two ways of using LDAP authentication. In the 'BAD' case, the credentials are transmitted in cleartext. In the 'GOOD' case, the credentials are transmitted over SSL.</p>
<sample src="InsecureLdapAuth.java" />
</example>
<references>
<li>
Oracle:
<a href="https://docs.oracle.com/javase/jndi/tutorial/ldap/misc/url.html">LDAP and LDAPS URLs</a>
</li>
<li>
Oracle:
<a href="https://docs.oracle.com/javase/tutorial/jndi/ldap/simple.html">Simple authentication</a>
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,213 @@
/**
* @name Insecure LDAP authentication
* @description LDAP authentication with credentials sent in cleartext.
* @kind path-problem
* @id java/insecure-ldap-auth
* @tags security
* external/cwe-522
* external/cwe-319
*/
import java
import DataFlow
import semmle.code.java.frameworks.Jndi
import semmle.code.java.frameworks.Networking
import semmle.code.java.dataflow.TaintTracking
import DataFlow::PathGraph
/**
* Insecure (non-SSL, non-private) LDAP URL string literal.
*/
class InsecureLdapUrlLiteral extends StringLiteral {
InsecureLdapUrlLiteral() {
// Match connection strings with the LDAP protocol and without private IP addresses to reduce false positives.
exists(string s | this.getRepresentedString() = s |
s.regexpMatch("(?i)ldap://[\\[a-zA-Z0-9].*") and
not s.substring(7, s.length()) instanceof PrivateHostName
)
}
}
/** The interface `javax.naming.Context`. */
class TypeNamingContext extends Interface {
TypeNamingContext() { this.hasQualifiedName("javax.naming", "Context") }
}
/** The class `java.util.Hashtable`. */
class TypeHashtable extends Class {
TypeHashtable() { this.getSourceDeclaration().hasQualifiedName("java.util", "Hashtable") }
}
/**
* Holds if a non-private LDAP string is concatenated from both protocol and host.
*/
predicate concatInsecureLdapString(Expr protocol, Expr host) {
protocol.(CompileTimeConstantExpr).getStringValue() = "ldap://" and
not exists(string hostString |
hostString = host.(CompileTimeConstantExpr).getStringValue() or
hostString =
host.(VarAccess).getVariable().getAnAssignedValue().(CompileTimeConstantExpr).getStringValue()
|
hostString.length() = 0 or // Empty host is loopback address
hostString instanceof PrivateHostName
)
}
/** Gets the leftmost operand in a concatenated string */
Expr getLeftmostConcatOperand(Expr expr) {
if expr instanceof AddExpr
then result = getLeftmostConcatOperand(expr.(AddExpr).getLeftOperand())
else result = expr
}
/**
* String concatenated with `InsecureLdapUrlLiteral`.
*/
class InsecureLdapUrl extends Expr {
InsecureLdapUrl() {
this instanceof InsecureLdapUrlLiteral
or
concatInsecureLdapString(this.(AddExpr).getLeftOperand(),
getLeftmostConcatOperand(this.(AddExpr).getRightOperand()))
}
}
/**
* Holds if `ma` writes the `java.naming.provider.url` (also known as `Context.PROVIDER_URL`) key of a `Hashtable`.
*/
predicate isProviderUrlSetter(MethodAccess ma) {
ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and
ma.getMethod().hasName(["put", "setProperty"]) and
(
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = "java.naming.provider.url"
or
exists(Field f |
ma.getArgument(0) = f.getAnAccess() and
f.hasName("PROVIDER_URL") and
f.getDeclaringType() instanceof TypeNamingContext
)
)
}
/**
* Holds if `ma` sets `fieldValue` to `envValue` in some `Hashtable`.
*/
bindingset[fieldValue, envValue]
predicate hasFieldValueEnv(MethodAccess ma, string fieldValue, string envValue) {
// environment.put("java.naming.security.authentication", "simple")
ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and
ma.getMethod().hasName(["put", "setProperty"]) and
ma.getArgument(0).(CompileTimeConstantExpr).getStringValue() = fieldValue and
ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue
}
/**
* Holds if `ma` sets attribute name `fieldName` to `envValue` in some `Hashtable`.
*/
bindingset[fieldName, envValue]
predicate hasFieldNameEnv(MethodAccess ma, string fieldName, string envValue) {
// environment.put(Context.SECURITY_AUTHENTICATION, "simple")
ma.getMethod().getDeclaringType().getAnAncestor() instanceof TypeHashtable and
ma.getMethod().hasName(["put", "setProperty"]) and
exists(Field f |
ma.getArgument(0) = f.getAnAccess() and
f.hasName(fieldName) and
f.getDeclaringType() instanceof TypeNamingContext
) and
ma.getArgument(1).(CompileTimeConstantExpr).getStringValue() = envValue
}
/**
* Holds if `ma` sets `java.naming.security.authentication` (also known as `Context.SECURITY_AUTHENTICATION`) to `simple` in some `Hashtable`.
*/
predicate isBasicAuthEnv(MethodAccess ma) {
hasFieldValueEnv(ma, "java.naming.security.authentication", "simple") or
hasFieldNameEnv(ma, "SECURITY_AUTHENTICATION", "simple")
}
/**
* Holds if `ma` sets `java.naming.security.protocol` (also known as `Context.SECURITY_PROTOCOL`) to `ssl` in some `Hashtable`.
*/
predicate isSSLEnv(MethodAccess ma) {
hasFieldValueEnv(ma, "java.naming.security.protocol", "ssl") or
hasFieldNameEnv(ma, "SECURITY_PROTOCOL", "ssl")
}
/**
* A taint-tracking configuration for `ldap://` URL in LDAP authentication.
*/
class InsecureUrlFlowConfig extends TaintTracking::Configuration {
InsecureUrlFlowConfig() { this = "InsecureLdapAuth:InsecureUrlFlowConfig" }
/** Source of `ldap://` connection string. */
override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof InsecureLdapUrl }
/** Sink of directory context creation. */
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc |
cc.getConstructedType().getASupertype*() instanceof TypeDirContext and
sink.asExpr() = cc.getArgument(0)
)
}
/** Method call of `env.put()`. */
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
exists(MethodAccess ma |
pred.asExpr() = ma.getArgument(1) and
isProviderUrlSetter(ma) and
succ.asExpr() = ma.getQualifier()
)
}
}
/**
* A taint-tracking configuration for `simple` basic-authentication in LDAP configuration.
*/
class BasicAuthFlowConfig extends DataFlow::Configuration {
BasicAuthFlowConfig() { this = "InsecureLdapAuth:BasicAuthFlowConfig" }
/** Source of `simple` configuration. */
override predicate isSource(DataFlow::Node src) {
exists(MethodAccess ma |
isBasicAuthEnv(ma) and ma.getQualifier() = src.(PostUpdateNode).getPreUpdateNode().asExpr()
)
}
/** Sink of directory context creation. */
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc |
cc.getConstructedType().getASupertype*() instanceof TypeDirContext and
sink.asExpr() = cc.getArgument(0)
)
}
}
/**
* A taint-tracking configuration for `ssl` configuration in LDAP authentication.
*/
class SSLFlowConfig extends DataFlow::Configuration {
SSLFlowConfig() { this = "InsecureLdapAuth:SSLFlowConfig" }
/** Source of `ssl` configuration. */
override predicate isSource(DataFlow::Node src) {
exists(MethodAccess ma |
isSSLEnv(ma) and ma.getQualifier() = src.(PostUpdateNode).getPreUpdateNode().asExpr()
)
}
/** Sink of directory context creation. */
override predicate isSink(DataFlow::Node sink) {
exists(ConstructorCall cc |
cc.getConstructedType().getASupertype*() instanceof TypeDirContext and
sink.asExpr() = cc.getArgument(0)
)
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, InsecureUrlFlowConfig config
where
config.hasFlowPath(source, sink) and
exists(BasicAuthFlowConfig bc | bc.hasFlowTo(sink.getNode())) and
not exists(SSLFlowConfig sc | sc.hasFlowTo(sink.getNode()))
select sink.getNode(), source, sink, "Insecure LDAP authentication from $@.", source.getNode(),
"LDAP connection string"

View File

@@ -23,6 +23,14 @@ class Member extends Element, Annotatable, Modifiable, @member {
/** Gets the qualified name of this member. */
string getQualifiedName() { result = getDeclaringType().getName() + "." + getName() }
/**
* Holds if this member has the specified name and is declared in the
* specified package and type.
*/
predicate hasQualifiedName(string package, string type, string name) {
this.getDeclaringType().hasQualifiedName(package, type) and this.hasName(name)
}
/** Holds if this member is package protected, that is, neither public nor private nor protected. */
predicate isPackageProtected() {
not isPrivate() and

View File

@@ -16,6 +16,7 @@ module Frameworks {
private import semmle.code.java.frameworks.Guice
private import semmle.code.java.frameworks.Protobuf
private import semmle.code.java.frameworks.guava.Guava
private import semmle.code.java.frameworks.apache.Lang
}
/**

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
else any()

View File

@@ -3598,6 +3598,7 @@ private module FlowExploration {
or
exists(PartialPathNodeRev mid |
revPartialPathStep(mid, node, sc1, sc2, ap, config) and
not clearsContent(node, ap.getHead()) and
not fullBarrier(node, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
@@ -3611,6 +3612,7 @@ private module FlowExploration {
exists(PartialPathNodeFwd mid |
partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
not fullBarrier(node, config) and
not clearsContent(node, ap.getHead().getContent()) and
if node instanceof CastingNode
then compatibleTypes(getNodeType(node), ap.getType())
else any()

View File

@@ -345,7 +345,9 @@ private predicate taintPreservingQualifierToMethod(Method m) {
m.getDeclaringType() instanceof TypeUri and
m.hasName("toURL")
or
m instanceof GetterMethod and m.getDeclaringType() instanceof SpringUntrustedDataType
m instanceof GetterMethod and
m.getDeclaringType().getASubtype*() instanceof SpringUntrustedDataType and
not m.getDeclaringType() instanceof TypeObject
or
m.getDeclaringType() instanceof SpringHttpEntity and
m.getName().regexpMatch("getBody|getHeaders")

View File

@@ -129,3 +129,14 @@ class UrlOpenConnectionMethod extends Method {
this.getName() = "openConnection"
}
}
/**
* A string matching private host names of IPv4 and IPv6, which only matches the host portion therefore checking for port is not necessary.
* Several examples are localhost, reserved IPv4 IP addresses including 127.0.0.1, 10.x.x.x, 172.16.x,x, 192.168.x,x, and reserved IPv6 addresses including [0:0:0:0:0:0:0:1] and [::1]
*/
class PrivateHostName extends string {
bindingset[this]
PrivateHostName() {
this.regexpMatch("(?i)localhost(?:[:/?#].*)?|127\\.0\\.0\\.1(?:[:/?#].*)?|10(?:\\.[0-9]+){3}(?:[:/?#].*)?|172\\.16(?:\\.[0-9]+){2}(?:[:/?#].*)?|192.168(?:\\.[0-9]+){2}(?:[:/?#].*)?|\\[?0:0:0:0:0:0:0:1\\]?(?:[:/?#].*)?|\\[?::1\\]?(?:[:/?#].*)?")
}
}

View File

@@ -1,27 +1,65 @@
/** Definitions related to the Apache Commons Lang library. */
import java
private import semmle.code.java.dataflow.FlowSteps
/*--- Types ---*/
/** The class `org.apache.commons.lang.RandomStringUtils` or `org.apache.commons.lang3.RandomStringUtils`. */
/**
* The class `org.apache.commons.lang.RandomStringUtils` or `org.apache.commons.lang3.RandomStringUtils`.
*/
class TypeApacheRandomStringUtils extends Class {
TypeApacheRandomStringUtils() {
hasQualifiedName("org.apache.commons.lang", "RandomStringUtils") or
hasQualifiedName("org.apache.commons.lang3", "RandomStringUtils")
this.hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"],
"RandomStringUtils")
}
}
/**
* The class `org.apache.commons.lang.ArrayUtils` or `org.apache.commons.lang3.ArrayUtils`.
*/
class TypeApacheArrayUtils extends Class {
TypeApacheArrayUtils() {
hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"], "ArrayUtils")
}
}
/*--- Methods ---*/
/**
* The method `deserialize` in either `org.apache.commons.lang.SerializationUtils`
* or `org.apache.commons.lang3.SerializationUtils`.
*/
class MethodApacheSerializationUtilsDeserialize extends Method {
MethodApacheSerializationUtilsDeserialize() {
(
this.getDeclaringType().hasQualifiedName("org.apache.commons.lang", "SerializationUtils") or
this.getDeclaringType().hasQualifiedName("org.apache.commons.lang3", "SerializationUtils")
) and
this.getDeclaringType()
.hasQualifiedName(["org.apache.commons.lang", "org.apache.commons.lang3"],
"SerializationUtils") and
this.hasName("deserialize")
}
}
/**
* A taint preserving method on `org.apache.commons.lang.ArrayUtils` or `org.apache.commons.lang3.ArrayUtils`
*/
private class ApacheLangArrayUtilsTaintPreservingMethod extends TaintPreservingCallable {
ApacheLangArrayUtilsTaintPreservingMethod() {
this.getDeclaringType() instanceof TypeApacheArrayUtils
}
override predicate returnsTaintFrom(int src) {
this.hasName(["addAll", "addFirst"]) and
src = [0 .. getNumberOfParameters() - 1]
or
this.hasName([
"clone", "nullToEmpty", "remove", "removeAll", "removeElement", "removeElements", "reverse",
"shift", "shuffle", "subarray", "swap", "toArray", "toMap", "toObject", "toPrimitive",
"toString", "toStringArray"
]) and
src = 0
or
this.hasName("add") and
this.getNumberOfParameters() = 2 and
src = [0, 1]
or
this.hasName("add") and
this.getNumberOfParameters() = 3 and
src = [0, 2]
}
}

View File

@@ -0,0 +1,360 @@
/** Definitions of flow steps through the collection types in the Guava framework */
import java
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.FlowSteps
private import semmle.code.java.Collections
private string guavaCollectPackage() { result = "com.google.common.collect" }
/** A reference type that extends a parameterization of one of the various immutable container types. */
private class ImmutableContainerType extends RefType {
string kind;
ImmutableContainerType() {
this.getSourceDeclaration().getASourceSupertype*().hasQualifiedName(guavaCollectPackage(), kind) and
kind = ["ImmutableCollection", "ImmutableMap", "ImmutableMultimap", "ImmutableTable"]
}
/**
* Gets the name of the most general superclass of this type
* from among `ImmutableCollection`, `ImmutableMap`, `ImmutableMultimap`, and `ImmutableTable`.
*/
string getKind() { result = kind }
}
/** A nested `Builder` class of one of the various immutable container classes */
private class ContainerBuilder extends NestedType {
ContainerBuilder() {
this.hasName("Builder") and
this.getEnclosingType() instanceof ImmutableContainerType
}
}
private class BuilderBuildMethod extends TaintPreservingCallable {
BuilderBuildMethod() {
this.getDeclaringType().getASourceSupertype*() instanceof ContainerBuilder and
// abstract ImmutableCollection<E> build()
// similar for other builder types
this.hasName("build")
}
override predicate returnsTaintFrom(int arg) { arg = -1 }
}
/** A method on a `Builder` class that adds elements to the container being built */
private class BuilderAddMethod extends TaintPreservingCallable {
int argument;
BuilderAddMethod() {
this.getDeclaringType().getASourceSupertype*() instanceof ContainerBuilder and
(
// abstract ImmutableCollection.Builder<E> add(E element)
// ImmutableCollection.Builder<E> add(E... elements)
// ImmutableCollection.Builder<E> addAll(Iterable<? extends E> elements)
// ImmutableCollection.Builder<E> addAll(Iterator<? extends E> elements)
// ImmutableMultiset.Builder<E> addCopies(E element, int occurrences)
// ImmutableMultiset.Builder<E> setCount(E element, int count)
this.hasName(["add", "addAll", "addCopies", "setCount"]) and
argument = 0
or
// ImmutableMap.Builder<K,V> put(K key, V value)
// ImmutableMap.Builder<K,V> put(Map.Entry<? extends K,? extends V> entry)
// ImmutableMap.Builder<K,V> putAll(Map<? extends K,? extends V> map)
// ImmutableMap.Builder<K,V> putAll(Iterable<? extends Map.Entry<? extends K,? extends V>> entries)
// ImmutableMultimap.Builder<K,V> put(K key, V value)
// ImmutableMultimap.Builder<K,V> put(Map.Entry<? extends K,? extends V> entry)
// ImmutableMultimap.Builder<K,V> putAll(Iterable<? extends Map.Entry<? extends K,? extends V>> entries)
// ImmutableMultimap.Builder<K,V> putAll(K key, Iterable<? extends V> values)
// ImmutableMultimap.Builder<K,V> putAll(K key, V... values)
// ImmutableMultimap.Builder<K,V> putAll(Multimap<? extends K,? extends V> multimap)
// ImmutableTable.Builder<R,C,V> put(R rowKey, C columnKey, V value)
// ImmutableTable.Builder<R,C,V> put(Table.Cell<? extends R,? extends C,? extends V> cell)
// ImmutableTable.Builder<R,C,V> putAll(Table<? extends R,? extends C,? extends V> table)
this.hasName(["put", "putAll"]) and
argument = getNumberOfParameters() - 1
)
}
override predicate returnsTaintFrom(int arg) { arg = [-1, argument] }
override predicate transfersTaint(int src, int sink) { src = argument and sink = -1 }
}
/**
* In a chained call `b.add(x).add(y).add(z)`, represents a flow step from the return value of
* this expression to the post update node of `b` (valid because the builder add methods return their qualifier).
* This is sufficient to express flow from `y` and `z` to `b`.
*/
private class ChainedBuilderAddStep extends AdditionalTaintStep {
override predicate step(DataFlow::Node src, DataFlow::Node sink) {
exists(MethodAccess ma |
ma.getMethod() instanceof BuilderAddMethod and
src.asExpr() = ma and
chainedBuilderMethod+(sink.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr()) = ma
)
}
}
private MethodAccess chainedBuilderMethod(Expr e) {
result.getQualifier() = e and
result.getMethod() instanceof BuilderAddMethod
}
/**
* A reference type that extends a parameterization of `com.google.common.collect.Multimap`.
*/
class MultimapType extends RefType {
MultimapType() {
this.getSourceDeclaration()
.getASourceSupertype*()
.hasQualifiedName(guavaCollectPackage(), "Multimap")
}
/** Gets the type of keys stored in this map. */
RefType getKeyType() {
exists(GenericInterface map | map.hasQualifiedName(guavaCollectPackage(), "Multimap") |
indirectlyInstantiates(this, map, 0, result)
)
}
/** Gets the type of values stored in this map. */
RefType getValueType() {
exists(GenericInterface map | map.hasQualifiedName(guavaCollectPackage(), "Multimap") |
indirectlyInstantiates(this, map, 1, result)
)
}
}
private class MultimapWriteMethod extends TaintPreservingCallable {
MultimapWriteMethod() {
this.getDeclaringType() instanceof MultimapType and
// boolean put(K key, V value)
// boolean putAll(K key, Iterable<? extends V> values)
// boolean putAll(Multimap<? extends K,? extends V> multimap)
// Collection<V> replaceValues(K key, Iterable<? extends V> values)
this.hasName(["put", "putAll", "replaceValues"])
}
override predicate transfersTaint(int src, int sink) {
src = getNumberOfParameters() - 1 and
sink = -1
}
}
private class MultimapReadMethod extends TaintPreservingCallable {
MultimapReadMethod() {
this.getDeclaringType() instanceof MultimapType and
// Collection<V> replaceValues(K key, Iterable<? extends V> values)
// Collection<V> removeAll(@CompatibleWith("K") Object key)
// Collection<V> get(K key)
// Collection<V> values()
// Collection<Map.Entry<K,V>> entries()
// Map<K,Collection<V>> asMap()
this.hasName(["replaceValues", "removeAll", "get", "values", "entries", "asMap"])
}
override predicate returnsTaintFrom(int arg) { arg = -1 }
// Not implemented: Some of these methods return "views", which when modified will modify the map itself.
// However, taint flow from these views to the map is not implemented.
}
/**
* A reference type that extends a parameterization of `com.google.common.collect.Table`.
*/
class TableType extends RefType {
TableType() {
this.getSourceDeclaration()
.getASourceSupertype*()
.hasQualifiedName(guavaCollectPackage(), "Table")
}
/** Gets the type of row keys stored in this table. */
RefType getRowType() {
exists(GenericInterface table | table.hasQualifiedName(guavaCollectPackage(), "Table") |
indirectlyInstantiates(this, table, 0, result)
)
}
/** Gets the type of column keys stored in this table. */
RefType getColumnType() {
exists(GenericInterface table | table.hasQualifiedName(guavaCollectPackage(), "Table") |
indirectlyInstantiates(this, table, 1, result)
)
}
/** Gets the type of values stored in this table. */
RefType getValueType() {
exists(GenericInterface table | table.hasQualifiedName(guavaCollectPackage(), "Table") |
indirectlyInstantiates(this, table, 2, result)
)
}
}
private class TableWriteMethod extends TaintPreservingCallable {
TableWriteMethod() {
this.getDeclaringType() instanceof TableType and
// V put(R rowKey, C columnKey, V value)
// void putAll(Table<? extends R,? extends C,? extends V> table)
this.hasName(["put", "putAll"])
}
override predicate transfersTaint(int src, int sink) {
src = getNumberOfParameters() - 1 and
sink = -1
}
}
private class TableReadMethod extends TaintPreservingCallable {
TableReadMethod() {
this.getDeclaringType() instanceof TableType and
// V put(R rowKey, C columnKey, V value)
// V remove(@CompatibleWith("R") Object rowKey, @CompatibleWith("C") Object columnKey)
// V get(@CompatibleWith("R") Object rowKey, @CompatibleWith("C") Object columnKey)
// Map<C,V> row(R rowKey)
// Map<R,V> column(C columnKey)
// Set<Table.Cell<R,C,V>> cellSet()
// Collection<V> values()
// Map<R,Map<C,V>> rowMap()
// Map<C,Map<R,V>> columnMap()
this.hasName([
"put", "remove", "get", "row", "column", "cellSet", "values", "rowMap", "columnMap"
])
}
override predicate returnsTaintFrom(int arg) { arg = -1 }
// Not implemented: Some of these methods return "views", which when modified will modify the table itself.
// However, taint flow from these views to the table is not implemented.
}
private class TableCellReadMethod extends TaintPreservingCallable {
TableCellReadMethod() {
exists(NestedType cell |
cell.getEnclosingType() instanceof TableType and
cell.hasName("Cell") and
this.getDeclaringType().getSourceDeclaration().getASourceSupertype*() = cell and
// V getValue()
this.hasName("getValue")
)
}
override predicate returnsTaintFrom(int arg) { arg = -1 }
}
/**
* An `of` static method on the various immutable container types.
*/
private class OfMethod extends TaintPreservingCallable {
string kind;
OfMethod() {
this.getDeclaringType().(ImmutableContainerType).getKind() = kind and
// static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6)
// static <K,V> ImmutableMap<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4)
// static <K,V> ImmutableMultimap<K,V> of(K k1, V v1, K k2, V v2, K k3, V v3, K k4, V v4)
// static <R,C,V> ImmutableTable<R,C,V> of(R rowKey, C columnKey, V value)
// etc for other types and numbers of parameters
this.hasName("of") and
this.isStatic()
}
override predicate returnsTaintFrom(int arg) {
arg = [0 .. getNumberOfParameters()] and
(kind.regexpMatch(".*[Mm]ap") implies arg % 2 = 1) and
(kind = "ImmutableTable" implies arg % 3 = 2)
}
}
private class ComparatorType extends RefType {
ComparatorType() { this.getASourceSupertype*().hasQualifiedName("java.util", "Comparator") }
}
/**
* A `copyOf`, `sortedCopyOf`, or `copyOfSorted` static method on the various immutable container types.
*/
private class CopyOfMethod extends TaintPreservingCallable {
CopyOfMethod() {
this.getDeclaringType() instanceof ImmutableContainerType and
// static <E> ImmutableList<E> copyOf(E[] elements)
// static <E> ImmutableList<E> copyOf(Iterable<? extends E> elements)
// static <E> ImmutableList<E> copyOf(Collection<? extends E> elements)
// static <E> ImmutableList<E> copyOf(Iterator<? extends E> elements)
// static <E extends Comparable<? super E>> ImmutableList<E> sortedCopyOf(Iterable<? extends E> elements)
// static <E> ImmutableList<E> sortedCopyOf(Comparator<? super E> comparator, Iterable<? extends E> elements)
// static <K,V> ImmutableMap<K,V> copyOf(Map<? extends K,? extends V> map)
// static <K,V> ImmutableMap<K,V> copyOf(Iterable<? extends Map.Entry<? extends K,? extends V>> entries)
// static <K,V> ImmutableMultimap<K,V> copyOf(Multimap<? extends K,? extends V> multimap)
// static <K,V> ImmutableMultimap<K,V> copyOf(Iterable<? extends Map.Entry<? extends K,? extends V>> entries)
// static <R,C,V> ImmutableTable<R,C,V> copyOf(Table<? extends R,? extends C,? extends V> table)
// static <K, V> ImmutableSortedMap<K, V> copyOf(Map<? extends K, ? extends V> map)
// static <K, V> ImmutableSortedMap<K, V> copyOf(Map<? extends K, ? extends V> map, Comparator<? super K> comparator)
// static <K, V> ImmutableSortedMap<K, V> copyOfSorted(SortedMap<K, ? extends V> map)
// static <E> ImmutableSortedSet<E> copyOf(Iterator<? extends E> elements)
// static <E> ImmutableSortedSet<E> copyOf(Comparator<? super E> comparator, Iterator<? extends E> elements)
// static <E> ImmutableSortedSet<E> copyOfSorted(SortedSet<E> sortedSet)
// etc
this.hasName(["copyOf", "sortedCopyOf", "copyOfSorted"]) and
this.isStatic()
}
override predicate returnsTaintFrom(int arg) {
arg = [0 .. getNumberOfParameters()] and
not getParameterType(arg) instanceof ComparatorType
}
}
private class CollectionAsListMethod extends TaintPreservingCallable {
CollectionAsListMethod() {
this.getDeclaringType()
.getASourceSupertype*()
.hasQualifiedName(guavaCollectPackage(), "ImmutableCollection") and
// public ImmutableList<E> asList()
this.hasName("asList")
}
override predicate returnsTaintFrom(int arg) { arg = -1 }
}
/**
* A taint-preserving static method of `com.google.common.collect.Sets`.
*/
private class SetsMethod extends TaintPreservingCallable {
int arg;
SetsMethod() {
this.getDeclaringType().hasQualifiedName(guavaCollectPackage(), "Sets") and
this.isStatic() and
(
// static <E> HashSet<E> newHashSet(E... elements)
// static <E> Set<E> newConcurrentHashSet(Iterable<? extends E> elements)
// static <E> CopyOnWriteArraySet<E> newCopyOnWriteArraySet(Iterable<? extends E> elements)
// etc
this.getName().matches("new%Set") and
arg = 0
or
// static <B> Set<List<B>> cartesianProduct(List<? extends Set<? extends B>> sets)
// static <B> Set<List<B>> cartesianProduct(Set<? extends B>... sets)
// static <E> Set<Set<E>> combinations(Set<E> set, int size)
// static <E> Sets.SetView<E> difference(Set<E> set1, Set<?> set2)
// static <E> NavigableSet<E> filter(NavigableSet<E> unfiltered, Predicate<? super E> predicate)
// static <E> Set<E> filter(Set<E> unfiltered, Predicate<? super E> predicate)
// static <E> SortedSet<E> filter(SortedSet<E> unfiltered, Predicate<? super E> predicate)
// static <E> Set<Set<E>> powerSet(Set<E> set)
// static <K extends Comparable<? super K>> NavigableSet<K> subSet(NavigableSet<K> set, Range<K> range)
// static <E> NavigableSet<E> synchronizedNavigableSet(NavigableSet<E> navigableSet)
// static <E> NavigableSet<E> unmodifiableNavigableSet(NavigableSet<E> set)
this.hasName([
"cartesianProduct", "combinations", "difference", "filter", "powerSet", "subSet",
"synchronizedNavigableSet", "unmodifyableNavigableSet"
]) and
arg = 0
or
// static <E> Sets.SetView<E> symmetricDifference(Set<? extends E> set1, Set<? extends E> set2)
// static <E> Sets.SetView<E> union(Set<? extends E> set1, Set<? extends E> set2)
this.hasName(["symmetricDifference", "union"]) and
arg = [0, 1]
)
}
override predicate returnsTaintFrom(int arg_) { arg_ = arg }
}

View File

@@ -4,3 +4,5 @@
import java
import StringUtils
import Collections
import Preconditions

View File

@@ -0,0 +1,23 @@
/** Definitions of flow steps through the Preconditions class in the Guava framework. */
import java
private import semmle.code.java.dataflow.FlowSteps
/**
* The class `com.google.common.base.Preconditions`.
*/
class TypeGuavaPreconditions extends Class {
TypeGuavaPreconditions() { this.hasQualifiedName("com.google.common.base", "Preconditions") }
}
/**
* A method that returns its argumnets.
*/
private class GuavaPreconditionsMethod extends TaintPreservingCallable {
GuavaPreconditionsMethod() {
this.getDeclaringType() instanceof TypeGuavaPreconditions and
this.hasName("checkNotNull")
}
override predicate returnsTaintFrom(int src) { src = 0 }
}

View File

@@ -38,6 +38,16 @@ class HostnameVerifier extends RefType {
HostnameVerifier() { hasQualifiedName("javax.net.ssl", "HostnameVerifier") }
}
/** The Java class `javax.crypto.KeyGenerator`. */
class KeyGenerator extends RefType {
KeyGenerator() { this.hasQualifiedName("javax.crypto", "KeyGenerator") }
}
/** The Java class `java.security.KeyPairGenerator`. */
class KeyPairGenerator extends RefType {
KeyPairGenerator() { this.hasQualifiedName("java.security", "KeyPairGenerator") }
}
/** The `verify` method of the class `javax.net.ssl.HostnameVerifier`. */
class HostnameVerifierVerify extends Method {
HostnameVerifierVerify() {
@@ -248,7 +258,7 @@ class JavaxCryptoSecretKey extends JavaxCryptoAlgoSpec {
class JavaxCryptoKeyGenerator extends JavaxCryptoAlgoSpec {
JavaxCryptoKeyGenerator() {
exists(Method m | m.getAReference() = this |
m.getDeclaringType().getQualifiedName() = "javax.crypto.KeyGenerator" and
m.getDeclaringType() instanceof KeyGenerator and
m.getName() = "getInstance"
)
}
@@ -304,3 +314,15 @@ class JavaSecuritySignature extends JavaSecurityAlgoSpec {
override Expr getAlgoSpec() { result = this.(ConstructorCall).getArgument(0) }
}
/** A method call to the Java class `java.security.KeyPairGenerator`. */
class JavaSecurityKeyPairGenerator extends JavaxCryptoAlgoSpec {
JavaSecurityKeyPairGenerator() {
exists(Method m | m.getAReference() = this |
m.getDeclaringType() instanceof KeyPairGenerator and
m.getName() = "getInstance"
)
}
override Expr getAlgoSpec() { result = this.(MethodAccess).getArgument(0) }
}

View File

@@ -28,7 +28,7 @@ class ProtoPom extends XMLElement {
Version getVersion() { result = this.getAChild() }
/**
* Gets a string representing the version, or an empty string if no version
* Gets a string representing the version, or an empty string if no `version`
* tag was provided.
*/
string getVersionString() {
@@ -53,7 +53,7 @@ class Pom extends ProtoPom {
Pom() {
this.getName() = "project" and
// Ignore "dependency-reduced-pom" files - these are generated by the
// shading plugin, and duplicate existing pom files.
// Maven Shade Plugin, and duplicate existing POM files.
this.getFile().getStem() != "dependency-reduced-pom"
}
@@ -77,7 +77,7 @@ class Pom extends ProtoPom {
/** Gets a child XML element named "dependencies". */
Dependencies getDependencies() { result = this.getAChild() }
/** Gets a child XML element named `dependencyManagement`. */
/** Gets a child XML element named "dependencyManagement". */
DependencyManagement getDependencyManagement() { result = getAChild() }
/** Gets a Dependency element for this POM. */
@@ -100,7 +100,8 @@ class Pom extends ProtoPom {
}
/**
* Gets a property value defined for this project with the given name.
* Gets a property value defined for this project with the given name, either in a local
* `<properties>` section, or in the `<properties>` section of an ancestor POM.
*/
PomProperty getProperty(string name) {
result.getName() = name and
@@ -112,7 +113,7 @@ class Pom extends ProtoPom {
*/
PomElement getProjectProperty() {
(
// It must either be a child of the pom, or a child of the parent node of the pom
// It must either be a child of the POM, or a child of the parent node of the POM
result = getAChild()
or
result = getParentPom().getAChild() and
@@ -124,8 +125,8 @@ class Pom extends ProtoPom {
}
/**
* Resolve the given placeholder (if possible) in the static context of this pom. Resolution
* occurs by considering the properties defined by this project.
* Resolve the given placeholder (if possible) in the static context of this POM. Resolution
* occurs by considering the properties defined by this project or an ancestor project.
*/
string resolvePlaceholder(string name) {
if name.prefix(8) = "project."
@@ -142,32 +143,33 @@ class Pom extends ProtoPom {
}
/**
* Gets all the dependencies that are exported by this pom. An exported dependency is one that
* is transitively available, i.e. one with scope compile.
* Gets all the dependencies that are exported by this POM. An exported dependency is one that
* is transitively available, i.e. one with scope "compile".
*/
Dependency getAnExportedDependency() {
result = getADependency() and result.getScope() = "compile"
}
/**
* Gets a pom dependency that is exported by this pom. An exported dependency is one that
* is transitively available, i.e. one with scope compile.
* Gets a POM dependency that is exported by this POM. An exported dependency is one that
* is transitively available, i.e. one with scope "compile".
*/
Pom getAnExportedPom() { result = getAnExportedDependency().getPom() }
/**
* Gets the `<parent>` element of this pom, if any.
* Gets the `<parent>` element of this POM, if any.
*/
Parent getParentElement() { result = getAChild() }
/**
* Gets the pom referred to by the `<parent>` element of this pom, if any.
* Gets the POM referred to by the `<parent>` element of this POM, if any.
*/
Pom getParentPom() { result = getParentElement().getPom() }
/**
* Gets the version specified for dependency `dep` in a `dependencyManagement`
* section if this pom or one of its ancestors.
* section in this POM or one of its ancestors, or an empty string if no version
* is specified.
*/
string getVersionStringForDependency(Dependency dep) {
if exists(getDependencyManagement().getDependency(dep))
@@ -223,12 +225,13 @@ class Dependency extends ProtoPom {
Pom getPom() { result.getShortCoordinate() = this.getShortCoordinate() }
/**
* Gets the jar file that we think maven resolved this dependency to (if any).
* Gets the jar file that Maven likely resolved this dependency to (if any).
* See `MavenRepo.getAnArtifact(ProtoPom)` for how this match is determined.
*/
File getJar() { exists(MavenRepo mr | result = mr.getAnArtifact(this)) }
/**
* Gets the scope of this dependency. If the scope tag is present, this will
* Gets the scope of this dependency. If the `scope` tag is present, this will
* be the string contents of that tag, otherwise it defaults to "compile".
*/
string getScope() {
@@ -249,14 +252,14 @@ class Dependency extends ProtoPom {
}
/**
* A Maven dependency element that represents an actual dependency from a given pom project.
* A Maven dependency element that represents an actual dependency from a given POM project.
*/
class PomDependency extends Dependency {
PomDependency() {
exists(Pom source |
// This dependency must be a dependency of a pom - dependency tags can also appear in the dependency
// management section, where they do not directly contribute to the dependencies of the containing
// pom.
// This dependency must be a dependency of a POM - dependency tags can also appear in the
// dependencyManagement section, where they do not directly contribute to the dependencies of
// the containing POM.
source.getADependency() = this and
// Consider dependencies that can be used at compile time.
(
@@ -284,7 +287,7 @@ class PomElement extends XMLElement {
s = allCharactersString() and
if s.matches("${%")
then
// Resolve the placeholder in the parent pom
// Resolve the placeholder in the parent POM
result = getParent*().(Pom).resolvePlaceholder(s.substring(2, s.length() - 1))
else result = s
)
@@ -330,7 +333,7 @@ class Dependencies extends PomElement {
Dependency getADependency() { result = this.getAChild() }
}
/** An XML element named `dependencyManagement`, as found in Maven POM XML files. */
/** An XML element named "dependencyManagement", as found in Maven POM XML files. */
class DependencyManagement extends PomElement {
DependencyManagement() { getName() = "dependencyManagement" }
@@ -349,7 +352,7 @@ class DependencyManagement extends PomElement {
}
/**
* An XML element name "properties", as found in Maven POM XML files.
* An XML element named "properties", as found in Maven POM XML files.
*/
class PomProperties extends PomElement {
PomProperties() { this.getName() = "properties" }
@@ -366,8 +369,8 @@ class PomProperty extends PomElement {
}
/**
* A folder that represents a maven local repository using the standard layout. Any folder called
* "repository" with a parent name ".m2" is considered to be a maven repository.
* A folder that represents a local Maven repository using the standard layout. Any folder called
* "repository" with a parent name ".m2" is considered to be a Maven repository.
*/
class MavenRepo extends Folder {
MavenRepo() { getBaseName() = "repository" and getParentContainer().getBaseName() = ".m2" }
@@ -378,10 +381,10 @@ class MavenRepo extends Folder {
File getAJarFile() { result = getAChildContainer*().(File) and result.getExtension() = "jar" }
/**
* Gets any jar artifacts in this repository that match the pom project definition. This is an
* over approximation. For soft qualifiers (e.g. 1.0) we return precise matches in preference to
* artefact only matches. For hard qualifiers (e.g. [1.0]) we return only precise matches. For
* all other qualifiers, we return all matches regardless of version.
* Gets any jar artifacts in this repository that match the POM project definition. This is an
* over approximation. For soft qualifiers (e.g. 1.0) precise matches are returned in preference
* to artifact-only matches. For hard qualifiers (e.g. [1.0]) only precise matches are returned.
* For all other qualifiers, all matches are returned regardless of version.
*/
MavenRepoJar getAnArtifact(ProtoPom pom) {
result = getAJarFile() and
@@ -389,7 +392,7 @@ class MavenRepo extends Folder {
then
// Either a hard match qualifier, or soft and there is at least one precise match
result.preciseMatch(pom)
else result.artefactMatches(pom)
else result.artifactMatches(pom)
}
}
@@ -401,16 +404,19 @@ private predicate versionHardMatch(ProtoPom pom) {
}
/**
* A jar file inside a maven repository.
* A jar file inside a Maven repository.
*
* See: https://cwiki.apache.org/confluence/display/MAVENOLD/Repository+Layout+-+Final
*/
class MavenRepoJar extends File {
MavenRepoJar() { exists(MavenRepo mr | mr.getAJarFile() = this) }
string getGroupID() {
/**
* Gets the `groupId` of this jar.
*/
string getGroupId() {
exists(MavenRepo mr | mr.getAJarFile() = this |
// Assuming the standard layout, the first part of the directory structure from the maven
// Assuming the standard layout, the first part of the directory structure from the Maven
// repository will be the groupId converted to a path by replacing "." with "/".
result =
getParentContainer()
@@ -422,24 +428,45 @@ class MavenRepoJar extends File {
)
}
string getArtefactID() { result = getParentContainer().getParentContainer().getBaseName() }
/**
* DEPRECATED: name changed to `getGroupId` for consistent use of camel-case.
*/
deprecated string getGroupID() { result = getGroupId() }
/**
* Gets the `artifactId` of this jar.
*/
string getArtifactId() { result = getParentContainer().getParentContainer().getBaseName() }
/**
* DEPRECATED: name changed to `getArtifactId` for consistent casing and consistent spelling with Maven.
*/
deprecated string getArtefactID() { result = getArtifactId() }
/**
* Gets the artifact version string of this jar.
*/
string getVersion() { result = getParentContainer().getBaseName() }
/**
* Holds if this jar is an artefact for the given pom or dependency, regardless of which version it is.
* Holds if this jar is an artifact for the given POM or dependency, regardless of which version it is.
*/
predicate artefactMatches(ProtoPom pom) {
pom.getGroup().getValue() = getGroupID() and
pom.getArtifact().getValue() = getArtefactID()
predicate artifactMatches(ProtoPom pom) {
pom.getGroup().getValue() = getGroupId() and
pom.getArtifact().getValue() = getArtifactId()
}
/**
* Holds if this jar is both an artefact for the pom, and has a version string that matches the pom
* DEPRECATED: name changed to `artifactMatches` for consistent spelling with Maven.
*/
deprecated predicate artefactMatches(ProtoPom pom) { artifactMatches(pom) }
/**
* Holds if this jar is both an artifact for the POM, and has a version string that matches the POM
* version string. Only soft and hard version matches are supported.
*/
predicate preciseMatch(ProtoPom pom) {
artefactMatches(pom) and
artifactMatches(pom) and
if versionHardMatch(pom)
then ("[" + getVersion() + "]").matches(pom.getVersionString() + "%")
else getVersion().matches(pom.getVersionString() + "%")

View File

@@ -87,7 +87,7 @@ public class UnsafeCertTrustTest {
/**
* Test the endpoint identification of SSL engine is set to null
*/
public void testSSLEngineEndpointIdSetNull() {
public void testSSLEngineEndpointIdSetNull() throws java.security.NoSuchAlgorithmException {
SSLContext sslContext = SSLContext.getInstance("TLS");
SSLEngine sslEngine = sslContext.createSSLEngine();
SSLParameters sslParameters = sslEngine.getSSLParameters();
@@ -98,7 +98,7 @@ public class UnsafeCertTrustTest {
/**
* Test the endpoint identification of SSL engine is not set
*/
public void testSSLEngineEndpointIdNotSet() {
public void testSSLEngineEndpointIdNotSet() throws java.security.NoSuchAlgorithmException {
SSLContext sslContext = SSLContext.getInstance("TLS");
SSLEngine sslEngine = sslContext.createSSLEngine();
}
@@ -106,7 +106,7 @@ public class UnsafeCertTrustTest {
/**
* Test the endpoint identification of SSL socket is not set
*/
public void testSSLSocketEndpointIdNotSet() {
public void testSSLSocketEndpointIdNotSet() throws java.security.NoSuchAlgorithmException, java.io.IOException {
SSLContext sslContext = SSLContext.getInstance("TLS");
final SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket("www.example.com", 443);
@@ -115,7 +115,7 @@ public class UnsafeCertTrustTest {
/**
* Test the endpoint identification of regular socket is not set
*/
public void testSocketEndpointIdNotSet() {
public void testSocketEndpointIdNotSet() throws java.io.IOException {
SocketFactory socketFactory = SocketFactory.getDefault();
Socket socket = socketFactory.createSocket("www.example.com", 80);
}
@@ -127,4 +127,4 @@ public class UnsafeCertTrustTest {
// ConnectionFactory connectionFactory = new ConnectionFactory();
// connectionFactory.useSslProtocol();
// }
}
}

View File

@@ -0,0 +1 @@
| JxBrowserWithoutCertValidationV6_23_1.java:17:27:17:39 | new Browser(...) | This JxBrowser instance may not check HTTPS certificates. |

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql

View File

@@ -0,0 +1,36 @@
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.LoadHandler;
import com.teamdev.jxbrowser.chromium.LoadParams;
import com.teamdev.jxbrowser.chromium.CertificateErrorParams;
public class JxBrowserWithoutCertValidationV6_23_1 {
public static void main(String[] args) {
badUsage();
goodUsage();
}
private static void badUsage() {
Browser browser = new Browser();
browser.loadURL("https://example.com");
// no further calls
// BAD: The browser ignores any certificate error by default!
}
private static void goodUsage() {
Browser browser = new Browser();
browser.setLoadHandler(new LoadHandler() {
public boolean onLoad(LoadParams params) {
return true;
}
public boolean onCertificateError(CertificateErrorParams params) {
return true; // GOOD: This means that loading will be cancelled on certificate errors
}
}); // GOOD: A secure `LoadHandler` is used.
browser.loadURL("https://example.com");
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/jxbrowser-6.23.1

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql

View File

@@ -0,0 +1,36 @@
import com.teamdev.jxbrowser.chromium.Browser;
import com.teamdev.jxbrowser.chromium.LoadHandler;
import com.teamdev.jxbrowser.chromium.LoadParams;
import com.teamdev.jxbrowser.chromium.CertificateErrorParams;
public class JxBrowserWithoutCertValidationV6_24 {
public static void main(String[] args) {
goodUsage();
goodUsage2();
}
private static void goodUsage() {
Browser browser = new Browser();
browser.loadURL("https://example.com");
// no further calls
// GOOD: On version 6.24 the browser properly validates certificates by default!
}
private static void goodUsage2() {
Browser browser = new Browser();
browser.setLoadHandler(new LoadHandler() {
public boolean onLoad(LoadParams params) {
return true;
}
public boolean onCertificateError(CertificateErrorParams params) {
return true; // GOOD: This means that loading will be cancelled on certificate errors
}
}); // GOOD: A secure `LoadHandler` is used.
browser.loadURL("https://example.com");
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/jxbrowser-6.24

View File

@@ -29,7 +29,7 @@ class InsecureJavaMail {
final Session session = Session.getInstance(properties, authenticator);
}
public void testSimpleMail() {
public void testSimpleMail() throws Exception {
Email email = new SimpleEmail();
email.setHostName("config.hostName");
email.setSmtpPort(25);
@@ -42,4 +42,4 @@ class InsecureJavaMail {
email.addTo("toAddress");
email.send();
}
}
}

View File

@@ -20,7 +20,7 @@ public class CleartextStorageSharedPrefs extends Activity {
}
// GOOD - save sensitive information in encrypted format
public void testSetSharedPrefs2(Context context, String name, String password) {
public void testSetSharedPrefs2(Context context, String name, String password) throws Exception {
SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE);
Editor editor = sharedPrefs.edit();
editor.putString("name", encrypt(name));
@@ -28,7 +28,7 @@ public class CleartextStorageSharedPrefs extends Activity {
editor.commit();
}
private static String encrypt(String cleartext) {
private static String encrypt(String cleartext) throws Exception {
// Use an encryption or hashing algorithm in real world. The demo below just returns its hash.
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(cleartext.getBytes(StandardCharsets.UTF_8));
@@ -37,7 +37,7 @@ public class CleartextStorageSharedPrefs extends Activity {
}
// GOOD - save sensitive information in encrypted format using separate variables
public void testSetSharedPrefs3(Context context, String name, String password) {
public void testSetSharedPrefs3(Context context, String name, String password) throws Exception {
String encUsername = encrypt(name);
String encPassword = encrypt(password);
SharedPreferences sharedPrefs = context.getSharedPreferences("user_prefs", Context.MODE_PRIVATE);
@@ -49,7 +49,7 @@ public class CleartextStorageSharedPrefs extends Activity {
// GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx
public void testSetSharedPrefs4(Context context, String name, String password) {
public void testSetSharedPrefs4(Context context, String name, String password) throws Exception {
MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
@@ -69,7 +69,7 @@ public class CleartextStorageSharedPrefs extends Activity {
}
// GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx
public void testSetSharedPrefs5(Context context, String name, String password) {
public void testSetSharedPrefs5(Context context, String name, String password) throws Exception {
MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();
@@ -89,7 +89,7 @@ public class CleartextStorageSharedPrefs extends Activity {
}
// GOOD - save sensitive information using the built-in `EncryptedSharedPreferences` class in androidx
public void testSetSharedPrefs6(Context context, String name, String password) {
public void testSetSharedPrefs6(Context context, String name, String password) throws Exception {
MasterKey masterKey = new MasterKey.Builder(context, MasterKey.DEFAULT_MASTER_KEY_ALIAS)
.setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
.build();

View File

@@ -0,0 +1,11 @@
| InsufficientKeySize.java:9:9:9:24 | init(...) | Key size should be at least 128 bits for AES encryption. |
| InsufficientKeySize.java:17:9:17:36 | initialize(...) | Key size should be at least 2048 bits for RSA encryption. |
| InsufficientKeySize.java:25:9:25:36 | initialize(...) | Key size should be at least 2048 bits for DSA encryption. |
| InsufficientKeySize.java:34:9:34:39 | initialize(...) | Key size should be at least 256 bits for EC encryption. |
| InsufficientKeySize.java:38:9:38:67 | initialize(...) | Key size should be at least 256 bits for EC encryption. |
| InsufficientKeySize.java:48:9:48:39 | initialize(...) | Key size should be at least 256 bits for EC encryption. |
| InsufficientKeySize.java:53:9:53:39 | initialize(...) | Key size should be at least 256 bits for EC encryption. |
| InsufficientKeySize.java:58:9:58:40 | initialize(...) | Key size should be at least 256 bits for EC encryption. |
| InsufficientKeySize.java:68:9:68:40 | initialize(...) | Key size should be at least 256 bits for EC encryption. |
| InsufficientKeySize.java:78:9:78:40 | initialize(...) | Key size should be at least 256 bits for EC encryption. |
| InsufficientKeySize.java:87:9:87:37 | initialize(...) | Key size should be at least 2048 bits for DH encryption. |

View File

@@ -0,0 +1,93 @@
import java.security.KeyPairGenerator;
import java.security.spec.ECGenParameterSpec;
import javax.crypto.KeyGenerator;
public class InsufficientKeySize {
public void CryptoMethod() throws java.security.NoSuchAlgorithmException, java.security.InvalidAlgorithmParameterException {
KeyGenerator keyGen1 = KeyGenerator.getInstance("AES");
// BAD: Key size is less than 128
keyGen1.init(64);
KeyGenerator keyGen2 = KeyGenerator.getInstance("AES");
// GOOD: Key size is no less than 128
keyGen2.init(128);
KeyPairGenerator keyPairGen1 = KeyPairGenerator.getInstance("RSA");
// BAD: Key size is less than 2048
keyPairGen1.initialize(1024);
KeyPairGenerator keyPairGen2 = KeyPairGenerator.getInstance("RSA");
// GOOD: Key size is no less than 2048
keyPairGen2.initialize(2048);
KeyPairGenerator keyPairGen3 = KeyPairGenerator.getInstance("DSA");
// BAD: Key size is less than 2048
keyPairGen3.initialize(1024);
KeyPairGenerator keyPairGen4 = KeyPairGenerator.getInstance("DSA");
// GOOD: Key size is no less than 2048
keyPairGen4.initialize(2048);
KeyPairGenerator keyPairGen5 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 256
ECGenParameterSpec ecSpec1 = new ECGenParameterSpec("secp112r1");
keyPairGen5.initialize(ecSpec1);
KeyPairGenerator keyPairGen6 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 256
keyPairGen6.initialize(new ECGenParameterSpec("secp112r1"));
KeyPairGenerator keyPairGen7 = KeyPairGenerator.getInstance("EC");
// GOOD: Key size is no less than 256
ECGenParameterSpec ecSpec2 = new ECGenParameterSpec("secp256r1");
keyPairGen7.initialize(ecSpec2);
KeyPairGenerator keyPairGen8 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 256
ECGenParameterSpec ecSpec3 = new ECGenParameterSpec("X9.62 prime192v2");
keyPairGen8.initialize(ecSpec3);
KeyPairGenerator keyPairGen9 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 256
ECGenParameterSpec ecSpec4 = new ECGenParameterSpec("X9.62 c2tnb191v3");
keyPairGen9.initialize(ecSpec4);
KeyPairGenerator keyPairGen10 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 256
ECGenParameterSpec ecSpec5 = new ECGenParameterSpec("sect163k1");
keyPairGen10.initialize(ecSpec5);
KeyPairGenerator keyPairGen11 = KeyPairGenerator.getInstance("EC");
// GOOD: Key size is no less than 256
ECGenParameterSpec ecSpec6 = new ECGenParameterSpec("X9.62 c2tnb359v1");
keyPairGen11.initialize(ecSpec6);
KeyPairGenerator keyPairGen12 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 256
ECGenParameterSpec ecSpec7 = new ECGenParameterSpec("prime192v2");
keyPairGen12.initialize(ecSpec7);
KeyPairGenerator keyPairGen13 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is no less than 256
ECGenParameterSpec ecSpec8 = new ECGenParameterSpec("prime256v1");
keyPairGen13.initialize(ecSpec8);
KeyPairGenerator keyPairGen14 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is less than 256
ECGenParameterSpec ecSpec9 = new ECGenParameterSpec("c2tnb191v1");
keyPairGen14.initialize(ecSpec9);
KeyPairGenerator keyPairGen15 = KeyPairGenerator.getInstance("EC");
// BAD: Key size is no less than 256
ECGenParameterSpec ecSpec10 = new ECGenParameterSpec("c2tnb431r1");
keyPairGen15.initialize(ecSpec10);
KeyPairGenerator keyPairGen16 = KeyPairGenerator.getInstance("dh");
// BAD: Key size is less than 2048
keyPairGen16.initialize(1024);
KeyPairGenerator keyPairGen17 = KeyPairGenerator.getInstance("DH");
// GOOD: Key size is no less than 2048
keyPairGen17.initialize(2048);
}
}

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-326/InsufficientKeySize.ql

View File

@@ -57,7 +57,7 @@ public class InsecureBasicAuth {
/**
* Test basic authentication with Apache HTTP POST request using the URI constructor with one argument.
*/
public void testApacheHttpRequest4(String username, String password) {
public void testApacheHttpRequest4(String username, String password) throws Exception {
String uriStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
URI uri = new URI(uriStr);
HttpRequestBase post = new HttpPost(uri);
@@ -74,7 +74,7 @@ public class InsecureBasicAuth {
/**
* Test basic authentication with Apache HTTP POST request using a URI constructor with multiple arguments.
*/
public void testApacheHttpRequest5(String username, String password) {
public void testApacheHttpRequest5(String username, String password) throws Exception {
HttpRequestBase post = new HttpPost(new URI("http", "www.example.com", "/test", "abc=123", null));
post.setHeader("Accept", "application/json");
post.setHeader("Content-type", "application/json");
@@ -122,7 +122,7 @@ public class InsecureBasicAuth {
/**
* Test basic authentication with Java HTTP URL connection using the `URL(String spec)` constructor.
*/
public void testHttpUrlConnection(String username, String password) {
public void testHttpUrlConnection(String username, String password) throws Exception {
String urlStr = "http://www.example.com/rest/getuser.do?uid=abcdx";
String authString = username + ":" + password;
String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));
@@ -136,7 +136,7 @@ public class InsecureBasicAuth {
/**
* Test basic authentication with Java HTTP URL connection using the `URL(String protocol, String host, String file)` constructor.
*/
public void testHttpUrlConnection2(String username, String password) {
public void testHttpUrlConnection2(String username, String password) throws Exception {
String host = "www.example.com";
String path = "/rest/getuser.do?uid=abcdx";
String protocol = "http";
@@ -152,7 +152,7 @@ public class InsecureBasicAuth {
/**
* Test basic authentication with Java HTTP URL connection using a constructor with private URL.
*/
public void testHttpUrlConnection3(String username, String password) {
public void testHttpUrlConnection3(String username, String password) throws Exception {
String host = "LOCALHOST";
String authString = username + ":" + password;
String encoding = Base64.getEncoder().encodeToString(authString.getBytes("UTF-8"));
@@ -161,4 +161,4 @@ public class InsecureBasicAuth {
conn.setDoOutput(true);
conn.setRequestProperty("Authorization", "Basic " + encoding);
}
}
}

View File

@@ -0,0 +1,70 @@
edges
| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:20:49:20:59 | environment |
| InsecureLdapAuth.java:17:3:17:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:20:49:20:59 | environment |
| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:34:49:34:59 | environment |
| InsecureLdapAuth.java:31:3:31:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:34:49:34:59 | environment |
| InsecureLdapAuth.java:45:3:45:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:48:49:48:59 | environment |
| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | InsecureLdapAuth.java:63:49:63:59 | environment |
| InsecureLdapAuth.java:59:3:59:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:63:49:63:59 | environment |
| InsecureLdapAuth.java:62:3:62:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:63:49:63:59 | environment |
| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:77:49:77:59 | environment |
| InsecureLdapAuth.java:88:3:88:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:91:49:91:59 | environment |
| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:105:59:105:69 | environment |
| InsecureLdapAuth.java:102:3:102:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:105:59:105:69 | environment |
| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:120:49:120:59 | environment |
| InsecureLdapAuth.java:117:3:117:13 | environment [post update] : Hashtable | InsecureLdapAuth.java:120:49:120:59 | environment |
| InsecureLdapAuth.java:124:3:124:5 | env [post update] : Hashtable | InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable |
| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable |
| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable |
| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | InsecureLdapAuth.java:142:50:142:60 | environment |
| InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | InsecureLdapAuth.java:142:50:142:60 | environment |
| InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | InsecureLdapAuth.java:142:50:142:60 | environment |
| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:153:50:153:60 | environment |
| InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | InsecureLdapAuth.java:153:50:153:60 | environment |
nodes
| InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String |
| InsecureLdapAuth.java:17:3:17:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:20:49:20:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:20:49:20:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | semmle.label | ... + ... : String |
| InsecureLdapAuth.java:31:3:31:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:34:49:34:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:34:49:34:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:45:3:45:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:48:49:48:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:53:20:53:50 | "ldap://ad.your-server.com:636" : String | semmle.label | "ldap://ad.your-server.com:636" : String |
| InsecureLdapAuth.java:59:3:59:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:62:3:62:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:63:49:63:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:68:20:68:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String |
| InsecureLdapAuth.java:77:49:77:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:88:3:88:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:91:49:91:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String |
| InsecureLdapAuth.java:102:3:102:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:105:59:105:69 | environment | semmle.label | environment |
| InsecureLdapAuth.java:105:59:105:69 | environment | semmle.label | environment |
| InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | semmle.label | "ldap://ad.your-server.com:389" : String |
| InsecureLdapAuth.java:117:3:117:13 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:120:49:120:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:120:49:120:59 | environment | semmle.label | environment |
| InsecureLdapAuth.java:124:3:124:5 | env [post update] : Hashtable | semmle.label | env [post update] : Hashtable |
| InsecureLdapAuth.java:128:3:128:5 | env [post update] : Hashtable | semmle.label | env [post update] : Hashtable |
| InsecureLdapAuth.java:135:20:135:39 | ... + ... : String | semmle.label | ... + ... : String |
| InsecureLdapAuth.java:137:10:137:20 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:141:16:141:26 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment |
| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment |
| InsecureLdapAuth.java:142:50:142:60 | environment | semmle.label | environment |
| InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | semmle.label | ... + ... : String |
| InsecureLdapAuth.java:152:16:152:26 | environment [post update] : Hashtable | semmle.label | environment [post update] : Hashtable |
| InsecureLdapAuth.java:153:50:153:60 | environment | semmle.label | environment |
| InsecureLdapAuth.java:153:50:153:60 | environment | semmle.label | environment |
#select
| InsecureLdapAuth.java:20:49:20:59 | environment | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:20:49:20:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:11:20:11:50 | "ldap://ad.your-server.com:389" | LDAP connection string |
| InsecureLdapAuth.java:34:49:34:59 | environment | InsecureLdapAuth.java:25:20:25:39 | ... + ... : String | InsecureLdapAuth.java:34:49:34:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:25:20:25:39 | ... + ... | LDAP connection string |
| InsecureLdapAuth.java:105:59:105:69 | environment | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:105:59:105:69 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:96:20:96:50 | "ldap://ad.your-server.com:389" | LDAP connection string |
| InsecureLdapAuth.java:120:49:120:59 | environment | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" : String | InsecureLdapAuth.java:120:49:120:59 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:111:20:111:50 | "ldap://ad.your-server.com:389" | LDAP connection string |
| InsecureLdapAuth.java:153:50:153:60 | environment | InsecureLdapAuth.java:147:20:147:39 | ... + ... : String | InsecureLdapAuth.java:153:50:153:60 | environment | Insecure LDAP authentication from $@. | InsecureLdapAuth.java:147:20:147:39 | ... + ... | LDAP connection string |

View File

@@ -0,0 +1,155 @@
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.ldap.InitialLdapContext;
public class InsecureLdapAuth {
// BAD - Test LDAP authentication in cleartext using `DirContext`.
public void testCleartextLdapAuth(String ldapUserName, String password) throws Exception {
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);
}
// BAD - Test LDAP authentication in cleartext using `DirContext`.
public void testCleartextLdapAuth(String ldapUserName, String password, String serverName) throws Exception {
String ldapUrl = "ldap://"+serverName+":389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);
}
// GOOD - Test LDAP authentication over SSL.
public void testSslLdapAuth(String ldapUserName, String password) throws Exception {
String ldapUrl = "ldaps://ad.your-server.com:636";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);
}
// GOOD - Test LDAP authentication over SSL.
public void testSslLdapAuth2(String ldapUserName, String password) throws Exception {
String ldapUrl = "ldap://ad.your-server.com:636";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
environment.put(Context.SECURITY_PROTOCOL, "ssl");
DirContext dirContext = new InitialDirContext(environment);
}
// GOOD - Test LDAP authentication with SASL authentication.
public void testSaslLdapAuth(String ldapUserName, String password) throws Exception {
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);
}
// GOOD - Test LDAP authentication in cleartext connecting to local LDAP server.
public void testCleartextLdapAuth2(String ldapUserName, String password) throws Exception {
String ldapUrl = "ldap://localhost:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
DirContext dirContext = new InitialDirContext(environment);
}
// BAD - Test LDAP authentication in cleartext using `InitialLdapContext`.
public void testCleartextLdapAuth3(String ldapUserName, String password) throws Exception {
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
environment.put(Context.REFERRAL, "follow");
environment.put(Context.SECURITY_AUTHENTICATION, "simple");
environment.put(Context.SECURITY_PRINCIPAL, ldapUserName);
environment.put(Context.SECURITY_CREDENTIALS, password);
InitialLdapContext ldapContext = new InitialLdapContext(environment, null);
}
// BAD - Test LDAP authentication in cleartext using `DirContext` and string literals.
public void testCleartextLdapAuth4(String ldapUserName, String password) throws Exception {
String ldapUrl = "ldap://ad.your-server.com:389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put("java.naming.factory.initial",
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put("java.naming.provider.url", ldapUrl);
environment.put("java.naming.referral", "follow");
environment.put("java.naming.security.authentication", "simple");
environment.put("java.naming.security.principal", ldapUserName);
environment.put("java.naming.security.credentials", password);
DirContext dirContext = new InitialDirContext(environment);
}
private void setSSL(Hashtable env) {
env.put(Context.SECURITY_PROTOCOL, "ssl");
}
private void setBasicAuth(Hashtable env, String ldapUserName, String password) {
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapUserName);
env.put(Context.SECURITY_CREDENTIALS, password);
}
// GOOD - Test LDAP authentication with `ssl` configuration and basic authentication.
public void testCleartextLdapAuth5(String ldapUserName, String password, String serverName) throws Exception {
String ldapUrl = "ldap://"+serverName+":389";
Hashtable<String, String> environment = new Hashtable<String, String>();
setSSL(environment);
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
setBasicAuth(environment, ldapUserName, password);
DirContext dirContext = new InitialLdapContext(environment, null);
}
// BAD - Test LDAP authentication with basic authentication.
public void testCleartextLdapAuth6(String ldapUserName, String password, String serverName) throws Exception {
String ldapUrl = "ldap://"+serverName+":389";
Hashtable<String, String> environment = new Hashtable<String, String>();
environment.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
environment.put(Context.PROVIDER_URL, ldapUrl);
setBasicAuth(environment, ldapUserName, password);
DirContext dirContext = new InitialLdapContext(environment, null);
}
}

View File

@@ -0,0 +1 @@
experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql

View File

@@ -1 +1 @@
experimental/CWE-918/RequestForgery.ql
experimental/Security/CWE/CWE-918/RequestForgery.ql

View File

@@ -26,7 +26,7 @@ public class SpringSSRF extends HttpServlet {
String fooResourceUrl = request2.getParameter("uri");;
RestTemplate restTemplate = new RestTemplate();
HttpEntity<String> request = new HttpEntity<>(new String("bar"));
try {
{
ResponseEntity<String> response =
restTemplate.getForEntity(fooResourceUrl + "/1", String.class);
@@ -68,5 +68,6 @@ public class SpringSSRF extends HttpServlet {
{
restTemplate.put(fooResourceUrl, new String("object"));
}
} catch (org.springframework.web.client.RestClientException | java.net.URISyntaxException e) {}
}
}

View File

@@ -0,0 +1,9 @@
package com.teamdev.jxbrowser.chromium;
public class Browser extends java.lang.Object {
public void setLoadHandler(LoadHandler handler) {
}
public void loadURL(String url) {
}
}

View File

@@ -0,0 +1,5 @@
package com.teamdev.jxbrowser.chromium;
public final class CertificateErrorParams extends Object {
}

View File

@@ -0,0 +1,7 @@
package com.teamdev.jxbrowser.chromium;
public interface LoadHandler {
boolean onCertificateError(CertificateErrorParams params);
boolean onLoad(LoadParams params);
}

View File

@@ -0,0 +1,5 @@
package com.teamdev.jxbrowser.chromium;
public final class LoadParams extends Object {
}

View File

@@ -0,0 +1,5 @@
package com.teamdev.jxbrowser.chromium;
public interface BoundsListener {
}

View File

@@ -0,0 +1,13 @@
package com.teamdev.jxbrowser.chromium;
public class Browser extends java.lang.Object {
public void setLoadHandler(LoadHandler handler) {
}
public void loadURL(String url) {
}
public void addBoundsListener(BoundsListener listener) {
}
}

View File

@@ -0,0 +1,5 @@
package com.teamdev.jxbrowser.chromium;
public final class CertificateErrorParams extends Object {
}

View File

@@ -0,0 +1,7 @@
package com.teamdev.jxbrowser.chromium;
public interface LoadHandler {
boolean onCertificateError(CertificateErrorParams params);
boolean onLoad(LoadParams params);
}

View File

@@ -0,0 +1,5 @@
package com.teamdev.jxbrowser.chromium;
public final class LoadParams extends Object {
}

View File

@@ -43,28 +43,28 @@ class Test {
new Bogus().exec("Irrelevant version of exec");
}
void apacheExecute1() {
void apacheExecute1() throws IOException {
String line = "AcroRd32.exe /p /h some.file";
CommandLine cmdLine = CommandLine.parse(line);
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(cmdLine);
}
void apacheExecute2() {
void apacheExecute2() throws IOException {
String line = "AcroRd32.exe /p /h some.file";
CommandLine cmdLine = CommandLine.parse(line, null);
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(cmdLine);
}
void apacheExecute3() {
void apacheExecute3() throws IOException {
CommandLine cmdLine = new CommandLine("AcroRd32.exe");
cmdLine.addArguments("/p /h some.file");
DefaultExecutor executor = new DefaultExecutor();
int exitValue = executor.execute(cmdLine);
}
void apacheExecute4() {
void apacheExecute4() throws IOException {
CommandLine cmdLine = new CommandLine("AcroRd32.exe");
cmdLine.addArguments("/p /h some.file", false);
DefaultExecutor executor = new DefaultExecutor();

View File

@@ -1,5 +1,5 @@
class Test {
public static void main(String[] args) {
public static void main(String[] args) throws java.io.IOException {
// Relative paths
Runtime.getRuntime().exec("make");
Runtime.getRuntime().exec("m");

View File

@@ -88,8 +88,8 @@ public class CommentedCode {
* &nbsp ;
* &nbsp ;
*/
return -1;
}
// public static int commentedOutMethod(){
//
// return 123;

View File

@@ -32,7 +32,7 @@ public class A {
case 0: return p;
case 1: return s;
case 2: return b1.getElem();
case 3: return b2.getElem();
default:return b2.getElem();
}
}
};

View File

@@ -8,7 +8,7 @@ import java.util.List;
import org.apache.commons.io.IOUtils;
class Test {
public static void ioutils() {
public static void ioutils() throws java.io.FileNotFoundException, java.io.IOException {
InputStream inp = new FileInputStream("test"); // user input
InputStream buf = IOUtils.buffer(inp);

View File

@@ -14,7 +14,7 @@ class Test {
return "tainted";
}
public static void jacksonObjectMapper() {
public static void jacksonObjectMapper() throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException {
String s = taint();
ObjectMapper om = new ObjectMapper();
File file = new File("testFile");
@@ -32,7 +32,7 @@ class Test {
System.out.println(reconstructed);
}
public static void jacksonObjectWriter() {
public static void jacksonObjectWriter() throws java.io.FileNotFoundException, java.io.UnsupportedEncodingException {
String s = taint();
ObjectWriter ow = new ObjectWriter();
File file = new File("testFile");

View File

@@ -15,7 +15,7 @@ public class A {
sink(b2);
}
void test2() {
void test2() throws IOException {
ByteArrayOutputStream bOutput = new ByteArrayOutputStream();
bOutput.write(taint());
byte[] b = bOutput.toByteArray();
@@ -25,11 +25,11 @@ public class A {
sink(b2);
}
void streamWrite(ByteArrayOutputStream baos, byte[] data) {
void streamWrite(ByteArrayOutputStream baos, byte[] data) throws IOException {
baos.write(data);
}
void test3(ByteArrayOutputStream baos) {
void test3(ByteArrayOutputStream baos) throws IOException {
streamWrite(baos, taint());
sink(baos.toByteArray());
}
@@ -38,11 +38,11 @@ public class A {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
}
void streamWriteHolder(BaosHolder bh, byte[] data) {
void streamWriteHolder(BaosHolder bh, byte[] data) throws IOException {
bh.baos.write(data);
}
void test4(BaosHolder bh) {
void test4(BaosHolder bh) throws IOException {
streamWriteHolder(bh, taint());
sink(bh.baos.toByteArray());
}
@@ -51,7 +51,7 @@ public class A {
byte[] data = new byte[10];
}
void test5_a(DataHolder dh) {
void test5_a(DataHolder dh) throws IOException {
ByteArrayInputStream bais = new ByteArrayInputStream(taint());
bais.read(dh.data);
test5_b(dh);

View File

@@ -11,7 +11,7 @@ public class B {
public static void sink(Object o) { }
public static void maintest() {
public static void maintest() throws java.io.UnsupportedEncodingException, java.net.MalformedURLException {
String[] args = taint();
// tainted - access to main args
String[] aaaargs = args;

View File

@@ -4,21 +4,21 @@ import android.app.Activity;
public class IntentSources extends Activity {
public void test() {
public void test() throws java.io.IOException {
String trouble = this.getIntent().getStringExtra("key");
Runtime.getRuntime().exec(trouble);
}
public void test2() {
public void test2() throws java.io.IOException {
String trouble = getIntent().getStringExtra("key");
Runtime.getRuntime().exec(trouble);
}
public void test3() {
public void test3() throws java.io.IOException {
String trouble = getIntent().getExtras().getString("key");
Runtime.getRuntime().exec(trouble);
@@ -29,9 +29,9 @@ public class IntentSources extends Activity {
class OtherClass {
public void test(IntentSources is) {
public void test(IntentSources is) throws java.io.IOException {
String trouble = is.getIntent().getStringExtra("key");
Runtime.getRuntime().exec(trouble);
}
}
}

View File

@@ -4,5 +4,5 @@ import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RmiFlow extends Remote {
String listDirectory(String path);
String listDirectory(String path) throws java.io.IOException;
}

View File

@@ -1,13 +1,13 @@
package security.library.dataflow;
public class RmiFlowImpl implements RmiFlow {
public String listDirectory(String path) {
public String listDirectory(String path) throws java.io.IOException {
String command = "ls " + path;
Runtime.getRuntime().exec(command);
return "pretend there are some results here";
}
public String notRemotable(String path) {
public String notRemotable(String path) throws java.io.IOException {
String command = "ls " + path;
Runtime.getRuntime().exec(command);
return "pretend there are some results here";

View File

@@ -5,21 +5,21 @@
| A.java:41:5:41:53 | getInputStream(...) | A.java:41:5:41:53 | getInputStream(...) |
| A.java:42:5:42:45 | getInputStream(...) | A.java:42:5:42:45 | getInputStream(...) |
| A.java:43:5:43:47 | getHostName(...) | A.java:43:5:43:47 | getHostName(...) |
| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1057:19:1057:32 | parameter this |
| IntentSources.java:9:20:9:35 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1059:19:1059:32 | parameter this |
| IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:35 | getIntent(...) |
| IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:9:20:9:57 | getStringExtra(...) |
| IntentSources.java:9:20:9:35 | getIntent(...) | IntentSources.java:10:29:10:35 | trouble |
| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1057:19:1057:32 | parameter this |
| IntentSources.java:16:20:16:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1059:19:1059:32 | parameter this |
| IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:30 | getIntent(...) |
| IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:16:20:16:52 | getStringExtra(...) |
| IntentSources.java:16:20:16:30 | getIntent(...) | IntentSources.java:17:29:17:35 | trouble |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1356:19:1356:27 | parameter this |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:599:19:599:27 | parameter this |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1358:19:1358:27 | parameter this |
| IntentSources.java:23:20:23:30 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/os/BaseBundle.java:600:19:600:27 | parameter this |
| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:30 | getIntent(...) |
| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:42 | getExtras(...) |
| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:23:20:23:59 | getString(...) |
| IntentSources.java:23:20:23:30 | getIntent(...) | IntentSources.java:24:29:24:35 | trouble |
| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1057:19:1057:32 | parameter this |
| IntentSources.java:33:20:33:33 | getIntent(...) | ../../../stubs/google-android-9.0.0/android/content/Intent.java:1059:19:1059:32 | parameter this |
| IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:33 | getIntent(...) |
| IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:33:20:33:55 | getStringExtra(...) |
| IntentSources.java:33:20:33:33 | getIntent(...) | IntentSources.java:34:29:34:35 | trouble |

View File

@@ -36,7 +36,7 @@ class ViableCallable {
i2.f("", 0l);
}
<TMock> TMock Mock() { throw new Exception(); }
<TMock> TMock Mock() { throw new Error(); }
void CreateTypeInstance() {
Run(new C2<Boolean>(), null, null, null);
@@ -63,7 +63,7 @@ abstract class C1<T1_C1, T2_C1> {
M(x, 8);
}
public void f(T1_C1 x, T2_C1 y) { throw new Exception(); }
public void f(T1_C1 x, T2_C1 y) { throw new Error(); }
}
interface I1<T_I1> {
@@ -80,27 +80,27 @@ interface I2<T_I2> {
class C2<T_C2> extends C1<String, T_C2> implements I1<T_C2> {
@Override
public <T3_C2> T_C2 M(String x, T3_C2 y) { throw new Exception(); }
public <T3_C2> T_C2 M(String x, T3_C2 y) { throw new Error(); }
}
class C3 extends C1<String, Long> implements I2<Long> {
@Override
public <T3_C3> Long M(String x, T3_C3 y) { throw new Exception(); }
public <T3_C3> Long M(String x, T3_C3 y) { throw new Error(); }
}
class C4<T_C4> extends C1<T_C4[], Boolean> {
@Override
public <T3_C4> Boolean M(T_C4[] x, T3_C4 y) { throw new Exception(); }
public <T3_C4> Boolean M(T_C4[] x, T3_C4 y) { throw new Error(); }
}
class C5 extends C1<String, Boolean> {
@Override
public <T3_C5> Boolean M(String x, T3_C5 y) { throw new Exception(); }
public <T3_C5> Boolean M(String x, T3_C5 y) { throw new Error(); }
}
class C6<T1_C6, T2_C6> extends C1<T1_C6, T2_C6> {
@Override
public <T3_C6> T2_C6 M(T1_C6 x, T3_C6 y) { throw new Exception(); }
public <T3_C6> T2_C6 M(T1_C6 x, T3_C6 y) { throw new Error(); }
public void Run(T1_C6 x) {
// Viable callables: C6.M(), C7.M()
@@ -113,7 +113,7 @@ class C6<T1_C6, T2_C6> extends C1<T1_C6, T2_C6> {
class C7<T1_C7> extends C6<T1_C7, Byte> {
@Override
public <T3_C7> Byte M(T1_C7 x, T3_C7 y) { throw new Exception(); }
public <T3_C7> Byte M(T1_C7 x, T3_C7 y) { throw new Error(); }
public void Run(T1_C7 x) {
// Viable callables: C7.M()
@@ -129,11 +129,11 @@ class C7<T1_C7> extends C6<T1_C7, Byte> {
class C8<T_C8, T2_C8> extends C1<String, T2_C8> {
@Override
public <T3_C8> T2_C8 M(String x, T3_C8 y) { throw new Exception(); }
public <T3_C8> T2_C8 M(String x, T3_C8 y) { throw new Error(); }
}
class C9<T_C9> extends C8<Boolean, Boolean> {
@Override
public <T3_C9> Boolean M(String x, T3_C9 y) { throw new Exception(); }
public <T3_C9> Boolean M(String x, T3_C9 y) { throw new Error(); }
}

View File

@@ -20,10 +20,10 @@ class ViableCallable2 {
}
class A {
public void m() { throw new Exception(); }
public void m() { throw new Error(); }
}
class B extends A {
@Override
public void m() { throw new Exception(); }
public void m() { throw new Error(); }
}

View File

@@ -0,0 +1,122 @@
package com.google.common.collect;
import java.util.Map;
import java.util.SortedSet;
import java.util.SortedMap;
import java.util.Comparator;
class TestCollect {
String taint() { return "tainted"; }
void sink(Object o) {}
void test1() {
String x = taint();
ImmutableSet<String> xs = ImmutableSet.of(x, "y", "z");
sink(xs.asList());
ImmutableSet<String> ys = ImmutableSet.of("a", "b", "c");
sink(Sets.filter(Sets.union(xs, ys), y -> true));
sink(Sets.newHashSet("a", "b", "c", "d", x));
}
void test2() {
sink(ImmutableList.of(taint(), taint(), taint(), taint())); // expect 4 alerts
sink(ImmutableMap.of(taint(), taint(), taint(), taint())); // expect 2 alerts
sink(ImmutableMultimap.of(taint(), taint(), taint(), taint())); // expect 2 alerts
sink(ImmutableTable.of(taint(),taint(), taint())); // expect 1 alert
}
void test3() {
String x = taint();
ImmutableList.Builder<String> b = ImmutableList.builder();
b.add("a");
sink(b);
b.add(x);
sink(b.build());
b = ImmutableList.builder();
b.add("a").add(x);
sink(b.build());
sink(ImmutableList.builder().add("a").add(x).build());
ImmutableMap.Builder<String, String> b2 = ImmutableMap.builder();
b2.put(x,"v");
sink(b2);
b2.put("k",x);
sink(b2.build());
}
void test4(Table<String, String, String> t1, Table<String, String, String> t2, Table<String, String, String> t3) {
String x = taint();
t1.put(x, "c", "v");
sink(t1);
t1.put("r", x, "v");
sink(t1);
t1.put("r", "c", x);
sink(t1);
sink(t1.row("r"));
t2.putAll(t1);
for (Table.Cell<String,String,String> c : t2.cellSet()) {
sink(c.getValue());
}
sink(t1.remove("r", "c"));
t3.row("r").put("c", x);
sink(t3); // Not detected
}
void test4(Multimap<String, String> m1, Multimap<String, String> m2, Multimap<String, String> m3,
Multimap<String, String> m4, Multimap<String, String> m5){
String x = taint();
m1.put("k", x);
sink(m1);
sink(m1.get("k"));
m2.putAll("k", ImmutableList.of("a", x, "b"));
sink(m2);
m3.putAll(m1);
sink(m3);
m4.replaceValues("k", m1.replaceValues("k", ImmutableList.of("a")));
for (Map.Entry<String, String> e : m4.entries()) {
sink(e.getValue());
}
m5.asMap().get("k").add(x);
sink(m5); // Not detected
}
void test5(Comparator<String> comp, SortedSet<String> sorS, SortedMap<String, String> sorM) {
ImmutableSortedSet<String> s = ImmutableSortedSet.of(taint());
sink(s);
sink(ImmutableSortedSet.copyOf(s));
sink(ImmutableSortedSet.copyOf(comp, s));
sorS.add(taint());
sink(ImmutableSortedSet.copyOfSorted(sorS));
sink(ImmutableList.sortedCopyOf(s));
sink(ImmutableList.sortedCopyOf(comp, s));
ImmutableSortedMap<String, String> m = ImmutableSortedMap.of("k", taint());
sink(m);
sink(ImmutableSortedMap.copyOf(m));
sink(ImmutableSortedMap.copyOf(m, comp));
sorM.put("k", taint());
sink(ImmutableSortedMap.copyOfSorted(sorM));
}
}

View File

@@ -6,7 +6,7 @@ import com.google.common.base.Joiner;
import java.util.Map;
import java.util.HashMap;
class Test {
class TestStrings {
String taint() { return "tainted"; }
void sink(Object o) {}

View File

@@ -1,17 +1,52 @@
| Test.java:15:20:15:26 | taint(...) | Test.java:17:14:17:41 | padStart(...) |
| Test.java:15:20:15:26 | taint(...) | Test.java:18:14:18:39 | padEnd(...) |
| Test.java:15:20:15:26 | taint(...) | Test.java:19:14:19:33 | repeat(...) |
| Test.java:15:20:15:26 | taint(...) | Test.java:20:14:20:56 | emptyToNull(...) |
| Test.java:15:20:15:26 | taint(...) | Test.java:21:14:21:40 | lenientFormat(...) |
| Test.java:15:20:15:26 | taint(...) | Test.java:24:14:24:51 | lenientFormat(...) |
| Test.java:28:20:28:26 | taint(...) | Test.java:32:14:32:23 | split(...) |
| Test.java:28:20:28:26 | taint(...) | Test.java:33:14:33:29 | splitToList(...) |
| Test.java:28:20:28:26 | taint(...) | Test.java:35:14:35:50 | split(...) |
| Test.java:39:20:39:26 | taint(...) | Test.java:46:14:46:54 | appendTo(...) |
| Test.java:39:20:39:26 | taint(...) | Test.java:47:14:47:26 | toString(...) |
| Test.java:39:20:39:26 | taint(...) | Test.java:48:14:48:51 | appendTo(...) |
| Test.java:39:20:39:26 | taint(...) | Test.java:49:14:49:26 | toString(...) |
| Test.java:39:20:39:26 | taint(...) | Test.java:52:14:52:42 | appendTo(...) |
| Test.java:39:20:39:26 | taint(...) | Test.java:57:14:57:56 | join(...) |
| Test.java:39:20:39:26 | taint(...) | Test.java:58:14:58:82 | join(...) |
| Test.java:39:20:39:26 | taint(...) | Test.java:60:14:60:58 | join(...) |
| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:17:14:17:24 | asList(...) |
| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:21:14:21:55 | filter(...) |
| TestCollect.java:14:20:14:26 | taint(...) | TestCollect.java:23:14:23:51 | newHashSet(...) |
| TestCollect.java:27:31:27:37 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
| TestCollect.java:27:40:27:46 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
| TestCollect.java:27:49:27:55 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
| TestCollect.java:27:58:27:64 | taint(...) | TestCollect.java:27:14:27:65 | of(...) |
| TestCollect.java:28:39:28:45 | taint(...) | TestCollect.java:28:14:28:64 | of(...) |
| TestCollect.java:28:57:28:63 | taint(...) | TestCollect.java:28:14:28:64 | of(...) |
| TestCollect.java:29:44:29:50 | taint(...) | TestCollect.java:29:14:29:69 | of(...) |
| TestCollect.java:29:62:29:68 | taint(...) | TestCollect.java:29:14:29:69 | of(...) |
| TestCollect.java:30:49:30:55 | taint(...) | TestCollect.java:30:14:30:56 | of(...) |
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:41:14:41:22 | build(...) |
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:46:14:46:22 | build(...) |
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:48:14:48:60 | build(...) |
| TestCollect.java:34:20:34:26 | taint(...) | TestCollect.java:54:14:54:23 | build(...) |
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:64:14:64:15 | t1 |
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:65:14:65:24 | row(...) |
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:69:18:69:29 | getValue(...) |
| TestCollect.java:58:20:58:26 | taint(...) | TestCollect.java:72:14:72:32 | remove(...) |
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:82:14:82:15 | m1 |
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:83:14:83:24 | get(...) |
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:86:14:86:15 | m2 |
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:89:14:89:15 | m3 |
| TestCollect.java:80:20:80:26 | taint(...) | TestCollect.java:93:18:93:29 | getValue(...) |
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:103:14:103:14 | s |
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:104:14:104:41 | copyOf(...) |
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:105:14:105:47 | copyOf(...) |
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:110:14:110:42 | sortedCopyOf(...) |
| TestCollect.java:101:62:101:68 | taint(...) | TestCollect.java:111:14:111:48 | sortedCopyOf(...) |
| TestCollect.java:107:18:107:24 | taint(...) | TestCollect.java:108:14:108:50 | copyOfSorted(...) |
| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:115:14:115:14 | m |
| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:116:14:116:41 | copyOf(...) |
| TestCollect.java:113:75:113:81 | taint(...) | TestCollect.java:117:14:117:47 | copyOf(...) |
| TestCollect.java:119:23:119:29 | taint(...) | TestCollect.java:120:14:120:50 | copyOfSorted(...) |
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:17:14:17:41 | padStart(...) |
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:18:14:18:39 | padEnd(...) |
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:19:14:19:33 | repeat(...) |
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:20:14:20:56 | emptyToNull(...) |
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:21:14:21:40 | lenientFormat(...) |
| TestStrings.java:15:20:15:26 | taint(...) | TestStrings.java:24:14:24:51 | lenientFormat(...) |
| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:32:14:32:23 | split(...) |
| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:33:14:33:29 | splitToList(...) |
| TestStrings.java:28:20:28:26 | taint(...) | TestStrings.java:35:14:35:50 | split(...) |
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:46:14:46:54 | appendTo(...) |
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:47:14:47:26 | toString(...) |
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:48:14:48:51 | appendTo(...) |
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:49:14:49:26 | toString(...) |
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:52:14:52:42 | appendTo(...) |
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:57:14:57:56 | join(...) |
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:58:14:58:82 | join(...) |
| TestStrings.java:39:20:39:26 | taint(...) | TestStrings.java:60:14:60:58 | join(...) |

View File

@@ -41,7 +41,7 @@ public class Logic {
}
private static void checkTrue(boolean b, String msg) {
if (!b) throw new Exception(msg);
if (!b) throw new Error (msg);
}
private static void checkFalse(boolean b, String msg) {

View File

@@ -3,7 +3,7 @@ class Test {
void test(int x) {
z = 0;
if (x < 0) {
throw new Exception();
throw new Error();
}
int y = 0;
while(x >= 0) {

View File

@@ -18,7 +18,7 @@ class PathCreation {
File f = new File(new File("dir"), "sub");
}
public void testNewFileWithURI() {
public void testNewFileWithURI() throws java.net.URISyntaxException {
File f = new File(new URI("dir"));
}
@@ -27,7 +27,7 @@ class PathCreation {
Path p2 = Path.of("dir", "sub");
}
public void testPathOfWithURI() {
public void testPathOfWithURI() throws java.net.URISyntaxException {
Path p = Path.of(new URI("dir"));
}
@@ -36,7 +36,7 @@ class PathCreation {
Path p2 = Paths.get("dir", "sub");
}
public void testPathsGetWithURI() {
public void testPathsGetWithURI() throws java.net.URISyntaxException {
Path p = Paths.get(new URI("dir"));
}
@@ -53,19 +53,19 @@ class PathCreation {
Path p = Path.of("dir").resolve("sub");
}
public void testNewFileWriterWithString() {
public void testNewFileWriterWithString() throws java.io.IOException {
FileWriter fw = new FileWriter("dir");
}
public void testNewFileReaderWithString() {
public void testNewFileReaderWithString() throws java.io.FileNotFoundException {
FileReader fr = new FileReader("dir");
}
public void testNewFileOutputStreamWithString() {
public void testNewFileOutputStreamWithString() throws java.io.FileNotFoundException {
FileOutputStream fos = new FileOutputStream("dir");
}
public void testNewFileInputStreamWithString() {
public void testNewFileInputStreamWithString() throws java.io.FileNotFoundException {
FileInputStream fis = new FileInputStream("dir");
}
}

View File

@@ -14,7 +14,7 @@ public class ReflectiveAccess {
return classContainingAnnotation.getAnnotation(annotationClass);
}
public static void main(String[] args) {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
Class<?> testClass = Class.forName("reflection.ReflectiveAccess$TestClass");
testClass.newInstance();

View File

@@ -5,8 +5,8 @@ class TestThrow2 {
{
try {
thrower();
} catch (Exception e) {
} catch (Throwable e) {
;
}
}
}
}

View File

@@ -2,3 +2,4 @@ name: codeql-java-tests
version: 0.0.0
libraryPathDependencies: codeql-java
extractor: java
tests: .

View File

@@ -100,7 +100,7 @@ class CloseReader {
private void init(InputStreamReader reader) {
fileRd = new BufferedReader(reader);
}
public void readStuff() {
public void readStuff() throws java.io.IOException {
System.out.println(fileRd.readLine());
fileRd.close();
}

View File

@@ -30,21 +30,21 @@ public class A {
break;
} while (c.cond());
// --- while, for loops ---
while (false) {
if (c.cond())
continue; // GOOD [never reached, if the condition changed so it was then the result would no longer apply]
if (c.cond())
break;
}
for (i = 0; false; i++) {
if (c.cond())
continue; // GOOD [never reached, if the condition changed so it was then the result would no longer apply]
if (c.cond())
break;
}
// --- nested loops ---

View File

@@ -1,10 +1,10 @@
class IAmAGoodCloneable implements Cloneable {
public Object clone() {
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Sub1 extends IAmAGoodCloneable { public Object clone() { return super.clone(); } }
class Sub1 extends IAmAGoodCloneable { public Object clone() throws CloneNotSupportedException { return super.clone(); } }
class IAmABadCloneable implements Cloneable {
public Object clone() {

View File

@@ -3,7 +3,7 @@ class GoodReturn {
@Override
public int hashCode() {
getClass().hashCode();
return getClass().hashCode();
}
@Override

View File

@@ -171,7 +171,7 @@ public class C {
private void verifyBool(boolean b) {
if (!b) {
throw new Exception();
throw new Error();
}
}
@@ -192,7 +192,7 @@ public class C {
private void verifyNotNull(Object obj) {
if (obj == null) {
throw new Exception();
throw new Error();
}
}

View File

@@ -5,7 +5,7 @@ public class A {
public A(int[] arr2, int n) {
if (arr2.length % 2 != 0)
throw new Exception();
throw new Error();
this.arr2 = arr2;
this.arr3 = new int[n << 1];
}
@@ -168,7 +168,7 @@ public class A {
if (n > 0) {
a = n > 0 ? new int[3 * n] : null;
}
int sum;
int sum = 0;
if (a != null) {
for (int i = 0; i < a.length; i += 3) {
sum += a[i + 2]; // OK

View File

@@ -7,9 +7,9 @@ class UseBraces
void f() { }
void g() { }
void h() { }
void test()
void test(boolean bb)
{
int x, y;
int x = 0, y;
int[] branches = new int[10];
// If-then statement
@@ -67,27 +67,27 @@ class UseBraces
// While statement
while(false)
while(bb)
{
f();
}
g(); // No alert
while(false)
while(bb)
f();
g();
while(false)
while(bb )
f();
g(); // Alert
g(); // No alert
while(false)
while(bb )
f(); g(); // Alert
while(false)
while(bb)
if (x != 0) x = 1;
// Do-while statement

View File

@@ -3,7 +3,7 @@ class Test {
void test(int x) {
z = getInt();
if (x < 0 || z < 0) {
throw new Exception();
throw new Error();
}
int y = 0;
if (x >= 0) y++; // useless test due to test in line 5 being false

View File

@@ -7,7 +7,7 @@ public class A {
new Object();
} catch(Exception e) {
if (e == null) { // Useless check
throw new Exception();
throw new Error();
}
}
}
@@ -16,7 +16,7 @@ public class A {
if (o instanceof A) {
A a = (A)o;
if (a != null) { // Useless check
throw new Exception();
throw new Error();
}
}
}

View File

@@ -16,7 +16,7 @@ public class ReflectionTest {
public int shadowedField;
}
public static void main(String[] args) {
public static void main(String[] args) throws NoSuchFieldException {
// Ensure the two classes are live, otherwise we might hide some results
new ParentClass();
new ChildClass();

View File

@@ -19,7 +19,7 @@ public class ReflectionMethodTest {
public void test4() { }
}
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException {
// Get class by name
Class.forName("ReflectionTest$TestObject1").getMethod("test1");
// Use classloader

View File

@@ -3,7 +3,7 @@ import java.nio.file.*;
import java.util.zip.*;
public class ZipTest {
public void m1(ZipEntry entry, File dir) {
public void m1(ZipEntry entry, File dir) throws Exception {
String name = entry.getName();
File file = new File(dir, name);
FileOutputStream os = new FileOutputStream(file); // ZipSlip
@@ -11,7 +11,7 @@ public class ZipTest {
FileWriter fw = new FileWriter(file); // ZipSlip
}
public void m2(ZipEntry entry, File dir) {
public void m2(ZipEntry entry, File dir) throws Exception {
String name = entry.getName();
File file = new File(dir, name);
File canFile = file.getCanonicalFile();
@@ -21,7 +21,7 @@ public class ZipTest {
FileOutputStream os = new FileOutputStream(file); // OK
}
public void m3(ZipEntry entry, File dir) {
public void m3(ZipEntry entry, File dir) throws Exception {
String name = entry.getName();
File file = new File(dir, name);
if (!file.toPath().normalize().startsWith(dir.toPath()))
@@ -29,20 +29,20 @@ public class ZipTest {
FileOutputStream os = new FileOutputStream(file); // OK
}
private void validate(File tgtdir, File file) {
private void validate(File tgtdir, File file) throws Exception {
File canFile = file.getCanonicalFile();
if (!canFile.toPath().startsWith(tgtdir.toPath()))
throw new Exception();
}
public void m4(ZipEntry entry, File dir) {
public void m4(ZipEntry entry, File dir) throws Exception {
String name = entry.getName();
File file = new File(dir, name);
validate(dir, file);
FileOutputStream os = new FileOutputStream(file); // OK
}
public void m5(ZipEntry entry, File dir) {
public void m5(ZipEntry entry, File dir) throws Exception {
String name = entry.getName();
File file = new File(dir, name);
Path absfile = file.toPath().toAbsolutePath().normalize();
@@ -52,7 +52,7 @@ public class ZipTest {
FileOutputStream os = new FileOutputStream(file); // OK
}
public void m6(ZipEntry entry, Path dir) {
public void m6(ZipEntry entry, Path dir) throws Exception {
String canonicalDest = dir.toFile().getCanonicalPath();
Path target = dir.resolve(entry.getName());
String canonicalTarget = target.toFile().getCanonicalPath();

View File

@@ -3,7 +3,7 @@ import java.util.List;
import java.util.ArrayList;
class Test {
public static void shellCommand(String arg) {
public static void shellCommand(String arg) throws java.io.IOException {
ProcessBuilder pb = new ProcessBuilder("/bin/bash -c echo " + arg);
pb.start();
@@ -25,7 +25,7 @@ class Test {
pb.start();
}
public static void nonShellCommand(String arg) {
public static void nonShellCommand(String arg) throws java.io.IOException {
ProcessBuilder pb = new ProcessBuilder("./customTool " + arg);
pb.start();
@@ -46,7 +46,7 @@ class Test {
pb.start();
}
public static void relativeCommand() {
public static void relativeCommand() throws java.io.IOException {
ProcessBuilder pb = new ProcessBuilder("ls");
pb.start();
@@ -54,11 +54,11 @@ class Test {
pb.start();
}
public static void main(String[] args) {
public static void main(String[] args) throws java.io.IOException {
String arg = args.length > 1 ? args[1] : "default";
shellCommand(arg);
nonShellCommand(arg);
relativeCommand();
}
}
}

View File

@@ -66,7 +66,7 @@ public class UnsafeHostnameVerification {
HostnameVerifier verifier = new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
verify(hostname, session.getPeerCertificates());
try { verify(hostname, session.getPeerCertificates()); } catch (Exception e) { throw new RuntimeException(); }
return true; // GOOD [but detected as BAD]. The verification of the certificate is done in
// another method and
// in the case of a mismatch, an `Exception` is thrown so the `return true`

View File

@@ -3,7 +3,7 @@ import javax.net.ssl.HttpsURLConnection;
import java.io.*;
class Test {
public void m1(HttpURLConnection connection) {
public void m1(HttpURLConnection connection) throws java.io.IOException {
InputStream input;
if (connection instanceof HttpsURLConnection) {
input = connection.getInputStream(); // OK

View File

@@ -31,7 +31,7 @@ class Test {
return true;
}
public void doConnect(int desiredPort, String username) {
public void doConnect(int desiredPort, String username) throws Exception {
ServerSocket listenSocket = new ServerSocket(desiredPort);
if (isAuthenticated(username)) {
@@ -56,7 +56,7 @@ class Test {
}
public void doConnectChannel(int desiredPort, String username) {
public void doConnectChannel(int desiredPort, String username) throws Exception {
ServerSocketChannel listenChannel = ServerSocketChannel.open();
SocketAddress port = new InetSocketAddress(desiredPort);
listenChannel.bind(port);

View File

@@ -9,32 +9,32 @@ import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.Yaml;
public class A {
public Object deserialize1(Socket sock) {
public Object deserialize1(Socket sock) throws java.io.IOException, ClassNotFoundException {
InputStream inputStream = sock.getInputStream();
ObjectInputStream in = new ObjectInputStream(inputStream);
return in.readObject(); // unsafe
}
public Object deserialize2(Socket sock) {
public Object deserialize2(Socket sock) throws java.io.IOException, ClassNotFoundException {
InputStream inputStream = sock.getInputStream();
ObjectInputStream in = new ObjectInputStream(inputStream);
return in.readUnshared(); // unsafe
}
public Object deserialize3(Socket sock) {
public Object deserialize3(Socket sock) throws java.io.IOException {
InputStream inputStream = sock.getInputStream();
XMLDecoder d = new XMLDecoder(inputStream);
return d.readObject(); // unsafe
}
public Object deserialize4(Socket sock) {
public Object deserialize4(Socket sock) throws java.io.IOException {
XStream xs = new XStream();
InputStream inputStream = sock.getInputStream();
Reader reader = new InputStreamReader(inputStream);
return xs.fromXML(reader); // unsafe
}
public void deserialize5(Socket sock) {
public void deserialize5(Socket sock) throws java.io.IOException {
Kryo kryo = new Kryo();
Input input = new Input(sock.getInputStream());
A a1 = kryo.readObject(input, A.class); // unsafe
@@ -42,20 +42,20 @@ public class A {
Object o = kryo.readClassAndObject(input); // unsafe
}
private Kryo getSafeKryo() {
private Kryo getSafeKryo() throws java.io.IOException {
Kryo kryo = new Kryo();
kryo.setRegistrationRequired(true);
// ... kryo.register(A.class) ...
return kryo;
}
public void deserialize6(Socket sock) {
public void deserialize6(Socket sock) throws java.io.IOException {
Kryo kryo = getSafeKryo();
Input input = new Input(sock.getInputStream());
Object o = kryo.readClassAndObject(input); // OK
}
public void deserializeSnakeYaml(Socket sock) {
public void deserializeSnakeYaml(Socket sock) throws java.io.IOException {
Yaml yaml = new Yaml();
InputStream input = sock.getInputStream();
Object o = yaml.load(input); //unsafe
@@ -65,7 +65,7 @@ public class A {
A o5 = yaml.loadAs(new InputStreamReader(input), A.class); //unsafe
}
public void deserializeSnakeYaml2(Socket sock) {
public void deserializeSnakeYaml2(Socket sock) throws java.io.IOException {
Yaml yaml = new Yaml(new Constructor());
InputStream input = sock.getInputStream();
Object o = yaml.load(input); //unsafe
@@ -75,7 +75,7 @@ public class A {
A o5 = yaml.loadAs(new InputStreamReader(input), A.class); //unsafe
}
public void deserializeSnakeYaml3(Socket sock) {
public void deserializeSnakeYaml3(Socket sock) throws java.io.IOException {
Yaml yaml = new Yaml(new SafeConstructor());
InputStream input = sock.getInputStream();
Object o = yaml.load(input); //OK
@@ -85,7 +85,7 @@ public class A {
A o5 = yaml.loadAs(new InputStreamReader(input), A.class); //OK
}
public void deserializeSnakeYaml4(Socket sock) {
public void deserializeSnakeYaml4(Socket sock) throws java.io.IOException {
Yaml yaml = new Yaml(new Constructor(A.class));
InputStream input = sock.getInputStream();
Object o = yaml.load(input); //OK

View File

@@ -3,19 +3,19 @@ import java.net.Socket;
import com.alibaba.fastjson.JSON;
public class B {
public Object deserializeJson1(Socket sock) {
public Object deserializeJson1(Socket sock) throws java.io.IOException {
InputStream inputStream = sock.getInputStream();
return JSON.parseObject(inputStream, null); // unsafe
}
public Object deserializeJson2(Socket sock) {
public Object deserializeJson2(Socket sock) throws java.io.IOException {
InputStream inputStream = sock.getInputStream();
byte[] bytes = new byte[100];
inputStream.read(bytes);
return JSON.parse(bytes); // unsafe
}
public Object deserializeJson3(Socket sock) {
public Object deserializeJson3(Socket sock) throws java.io.IOException {
InputStream inputStream = sock.getInputStream();
byte[] bytes = new byte[100];
inputStream.read(bytes);
@@ -23,7 +23,7 @@ public class B {
return JSON.parseObject(s); // unsafe
}
public Object deserializeJson4(Socket sock) {
public Object deserializeJson4(Socket sock) throws java.io.IOException {
InputStream inputStream = sock.getInputStream();
byte[] bytes = new byte[100];
inputStream.read(bytes);

View File

@@ -102,7 +102,7 @@ class DocumentBuilderTests {
builder.parse(source.getInputStream()); //unsafe
}
private static DocumentBuilderFactory getDocumentBuilderFactory() {
private static DocumentBuilderFactory getDocumentBuilderFactory() throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
String feature = "";
feature = "http://xml.org/sax/features/external-parameter-entities";
@@ -115,8 +115,8 @@ class DocumentBuilderTests {
private static final ThreadLocal<DocumentBuilder> XML_DOCUMENT_BUILDER = new ThreadLocal<DocumentBuilder>() {
@Override
protected DocumentBuilder initialValue() {
DocumentBuilderFactory factory = getDocumentBuilderFactory();
try {
DocumentBuilderFactory factory = getDocumentBuilderFactory();
return factory.newDocumentBuilder();
} catch (Exception ex) {
throw new RuntimeException(ex);

Some files were not shown because too many files have changed in this diff Show More