mirror of
https://github.com/github/codeql.git
synced 2026-04-29 02:35:15 +02:00
Merge remote-tracking branch 'upstream/main' into main
This commit is contained in:
@@ -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");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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."
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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\\]?(?:[:/?#].*)?")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
360
java/ql/src/semmle/code/java/frameworks/guava/Collections.qll
Normal file
360
java/ql/src/semmle/code/java/frameworks/guava/Collections.qll
Normal 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 }
|
||||
}
|
||||
@@ -4,3 +4,5 @@
|
||||
|
||||
import java
|
||||
import StringUtils
|
||||
import Collections
|
||||
import Preconditions
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
@@ -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() + "%")
|
||||
|
||||
@@ -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();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| JxBrowserWithoutCertValidationV6_23_1.java:17:27:17:39 | new Browser(...) | This JxBrowser instance may not check HTTPS certificates. |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/jxbrowser-6.23.1
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-295/JxBrowserWithoutCertValidation.ql
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/jxbrowser-6.24
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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. |
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-326/InsufficientKeySize.ql
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-522/InsecureLdapAuth.ql
|
||||
@@ -1 +1 @@
|
||||
experimental/CWE-918/RequestForgery.ql
|
||||
experimental/Security/CWE/CWE-918/RequestForgery.ql
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.teamdev.jxbrowser.chromium;
|
||||
|
||||
public final class CertificateErrorParams extends Object {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.teamdev.jxbrowser.chromium;
|
||||
|
||||
public interface LoadHandler {
|
||||
boolean onCertificateError(CertificateErrorParams params);
|
||||
|
||||
boolean onLoad(LoadParams params);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.teamdev.jxbrowser.chromium;
|
||||
|
||||
public final class LoadParams extends Object {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.teamdev.jxbrowser.chromium;
|
||||
|
||||
public interface BoundsListener {
|
||||
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.teamdev.jxbrowser.chromium;
|
||||
|
||||
public final class CertificateErrorParams extends Object {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.teamdev.jxbrowser.chromium;
|
||||
|
||||
public interface LoadHandler {
|
||||
boolean onCertificateError(CertificateErrorParams params);
|
||||
|
||||
boolean onLoad(LoadParams params);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.teamdev.jxbrowser.chromium;
|
||||
|
||||
public final class LoadParams extends Object {
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -88,8 +88,8 @@ public class CommentedCode {
|
||||
*   ;
|
||||
*   ;
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
// public static int commentedOutMethod(){
|
||||
//
|
||||
// return 123;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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(); }
|
||||
}
|
||||
|
||||
|
||||
@@ -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(); }
|
||||
}
|
||||
|
||||
122
java/ql/test/library-tests/frameworks/guava/TestCollect.java
Normal file
122
java/ql/test/library-tests/frameworks/guava/TestCollect.java
Normal 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));
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
@@ -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(...) |
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -5,8 +5,8 @@ class TestThrow2 {
|
||||
{
|
||||
try {
|
||||
thrower();
|
||||
} catch (Exception e) {
|
||||
} catch (Throwable e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@ name: codeql-java-tests
|
||||
version: 0.0.0
|
||||
libraryPathDependencies: codeql-java
|
||||
extractor: java
|
||||
tests: .
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 ---
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -3,7 +3,7 @@ class GoodReturn {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
getClass().hashCode();
|
||||
return getClass().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user