Merge pull request #20077 from d10c/d10c/diff-informed-phase-3-java

Java: Diff-informed queries: phase 3 (non-trivial locations)
This commit is contained in:
Nora Dimitrijević
2025-07-21 11:23:12 +02:00
committed by GitHub
53 changed files with 10491 additions and 2071 deletions

View File

@@ -149,6 +149,8 @@ module SensitiveCommunicationConfig implements DataFlow::ConfigSig {
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
isSink(node) and exists(c)
}
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -13,6 +13,14 @@ module ArithmeticOverflowConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node n) { overflowBarrier(n) }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
predicate observeDiffInformedIncrementalMode() {
any() // merged with ArithmeticUnderflow in ArithmeticTainted.ql
}
Location getASelectedSinkLocation(DataFlow::Node sink) {
exists(ArithExpr exp | result = exp.getLocation() | overflowSink(exp, sink.asExpr()))
}
}
/**
@@ -29,6 +37,14 @@ module ArithmeticUnderflowConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node n) { underflowBarrier(n) }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
predicate observeDiffInformedIncrementalMode() {
any() // merged with ArithmeticOverflow in ArithmeticTainted.ql
}
Location getASelectedSinkLocation(DataFlow::Node sink) {
exists(ArithExpr exp | result = exp.getLocation() | underflowSink(exp, sink.asExpr()))
}
}
/**

View File

@@ -19,6 +19,14 @@ module ArithmeticUncontrolledOverflowConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { overflowSink(_, sink.asExpr()) }
predicate isBarrier(DataFlow::Node n) { overflowBarrier(n) }
predicate observeDiffInformedIncrementalMode() {
any() // merged with ArithmeticUncontrolledUnderflow in ArithmeticUncontrolled.ql
}
Location getASelectedSinkLocation(DataFlow::Node sink) {
exists(ArithExpr exp | result = exp.getLocation() | overflowSink(exp, sink.asExpr()))
}
}
/** Taint-tracking flow to reason about overflow from arithmetic with uncontrolled values. */
@@ -32,6 +40,14 @@ module ArithmeticUncontrolledUnderflowConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { underflowSink(_, sink.asExpr()) }
predicate isBarrier(DataFlow::Node n) { underflowBarrier(n) }
predicate observeDiffInformedIncrementalMode() {
any() // merged with ArithmeticUncontrolledOverflow in ArithmeticUncontrolled.ql
}
Location getASelectedSinkLocation(DataFlow::Node sink) {
exists(ArithExpr exp | result = exp.getLocation() | underflowSink(exp, sink.asExpr()))
}
}
/** Taint-tracking flow to reason about underflow from arithmetic with uncontrolled values. */

View File

@@ -47,6 +47,15 @@ module ConditionalBypassFlowConfig implements DataFlow::ConfigSig {
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
endsWithStep(node1, node2)
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSinkLocation(DataFlow::Node sink) {
exists(MethodCall m, Expr e | result = [m, e].getLocation() |
conditionControlsMethod(m, e) and
sink.asExpr() = e
)
}
}
/**

View File

@@ -101,6 +101,10 @@ module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ActiveThreatModelSource }
predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode }
predicate observeDiffInformedIncrementalMode() {
any() // Simple use in UntrustedDataToExternalAPI.ql; also used through ExternalApiUsedWithUntrustedData in ExternalAPIsUsedWithUntrustedData.ql
}
}
/**

View File

@@ -17,6 +17,15 @@ module BoundedFlowSourceConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) {
any(CheckableArrayAccess caa).canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), _)
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSinkLocation(DataFlow::Node sink) {
exists(ArrayCreationExpr arrayCreation, CheckableArrayAccess arrayAccess |
result = [arrayCreation, arrayAccess.getIndexExpr()].getLocation() and
arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), arrayCreation)
)
}
}
/**

View File

@@ -14,6 +14,15 @@ module ImproperValidationOfArrayConstructionConfig implements DataFlow::ConfigSi
predicate isSink(DataFlow::Node sink) {
any(CheckableArrayAccess caa).canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), _)
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSinkLocation(DataFlow::Node sink) {
exists(ArrayCreationExpr arrayCreation, CheckableArrayAccess arrayAccess |
result = [arrayCreation, arrayAccess.getIndexExpr()].getLocation() and
arrayAccess.canThrowOutOfBoundsDueToEmptyArray(sink.asExpr(), arrayCreation)
)
}
}
/**

View File

@@ -14,6 +14,8 @@ module BoundedFlowSourceConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) {
exists(CheckableArrayAccess arrayAccess | arrayAccess.canThrowOutOfBounds(sink.asExpr()))
}
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -18,6 +18,8 @@ module ImproperValidationOfArrayIndexConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node node) { node.getType() instanceof BooleanType }
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -35,6 +35,10 @@ module SecureCookieConfig implements DataFlow::ConfigSig {
sink.asExpr() =
any(MethodCall add | add.getMethod() instanceof ResponseAddCookieMethod).getArgument(0)
}
predicate observeDiffInformedIncrementalMode() {
none() // only used negatively in InsecureCookie.ql
}
}
/** Data flow to reason about the failure to use secure cookies. */

View File

@@ -40,6 +40,10 @@ private module BasicAuthConfig implements DataFlow::ConfigSig {
}
predicate isSink(DataFlow::Node sink) { sink instanceof InsecureLdapUrlSink }
predicate observeDiffInformedIncrementalMode() {
none() // used as secondary flow to InsecureLdapUrlFlow in InsecureLdapAuth.ql
}
}
module BasicAuthFlow = DataFlow::Global<BasicAuthConfig>;
@@ -56,6 +60,10 @@ private module RequiresSslConfig implements DataFlow::ConfigSig {
}
predicate isSink(DataFlow::Node sink) { sink instanceof InsecureLdapUrlSink }
predicate observeDiffInformedIncrementalMode() {
none() // only used negatively in InsecureLdapAuth.ql
}
}
module RequiresSslFlow = DataFlow::Global<RequiresSslConfig>;

View File

@@ -19,6 +19,10 @@ module LogInjectionConfig implements DataFlow::ConfigSig {
}
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
predicate observeDiffInformedIncrementalMode() {
none() // straightforward case; but the large test source is causing OOMs under `--check-diff-informed`.
}
}
/**

View File

@@ -77,6 +77,12 @@ module InsecureCryptoConfig implements DataFlow::ConfigSig {
objectToString(n.asExpr()) or
n.getType().getErasure() instanceof TypeObject
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSinkLocation(DataFlow::Node sink) {
exists(CryptoAlgoSpec c | result = c.getLocation() | sink.asExpr() = c.getAlgoSpec())
}
}
/**

View File

@@ -53,6 +53,8 @@ module SensitiveLoggerConfig implements DataFlow::ConfigSig {
}
predicate isBarrierIn(DataFlow::Node node) { isSource(node) }
predicate observeDiffInformedIncrementalMode() { any() }
}
module SensitiveLoggerFlow = TaintTracking::Global<SensitiveLoggerConfig>;

View File

@@ -24,6 +24,15 @@ module UncontrolledStringBuilderSourceFlowConfig implements DataFlow::ConfigSig
predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) {
exists(Expr uncontrolled, StringBuilderVar sbv | result = uncontrolled.getLocation() |
uncontrolledStringBuilderQuery(sbv, uncontrolled) and
source = DataFlow::exprNode(sbv.getToStringCall())
)
}
}
/**

View File

@@ -38,6 +38,10 @@ module ExecTaintedEnvironmentConfig implements DataFlow::ConfigSig {
ProcessBuilderEnvironmentFlow::flowToExpr(mm.getQualifier())
)
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
}
/**

View File

@@ -145,6 +145,10 @@ module TempDirSystemGetPropertyToCreateConfig implements DataFlow::ConfigSig {
or
sanitizer instanceof WindowsOsSanitizer
}
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSinkLocation(DataFlow::Node sink) { none() }
}
/**

View File

@@ -62,6 +62,8 @@ module TrustBoundaryConfig implements DataFlow::ConfigSig {
}
predicate isSink(DataFlow::Node sink) { sink instanceof TrustBoundaryViolationSink }
predicate observeDiffInformedIncrementalMode() { any() }
}
/**

View File

@@ -14,6 +14,10 @@ module SslEndpointIdentificationFlowConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation }
predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof SslUnsafeCertTrustSanitizer }
predicate observeDiffInformedIncrementalMode() { any() }
Location getASelectedSourceLocation(DataFlow::Node source) { none() }
}
/**

View File

@@ -97,6 +97,10 @@ module WebViewDisallowContentAccessConfig implements DataFlow::StateConfigSig {
state instanceof IsSettings and
node instanceof WebSettingsDisallowContentAccessSink
}
predicate observeDiffInformedIncrementalMode() {
none() // only used negatively
}
}
module WebViewDisallowContentAccessFlow =

View File

@@ -0,0 +1,14 @@
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
public class ExternalAPISinkExample extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// BAD: a request parameter is written directly to an error response page
response.sendError(HttpServletResponse.SC_NOT_FOUND,
"The page \"" + request.getParameter("page") + "\" was not found."); // $ Alert
}
}

View File

@@ -0,0 +1,19 @@
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletException;
import java.io.IOException;
public class ExternalAPITaintStepExample extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
StringBuilder sqlQueryBuilder = new StringBuilder();
sqlQueryBuilder.append("SELECT * FROM user WHERE user_id='");
// BAD: a request parameter is concatenated directly into a SQL query
sqlQueryBuilder.append(request.getParameter("user_id"));
sqlQueryBuilder.append("'");
// ...
}
}

View File

@@ -0,0 +1 @@
| javax.servlet.http.HttpServletResponse.sendError(int,java.lang.String) [param 1] | 1 | 1 |

View File

@@ -0,0 +1 @@
Security/CWE/CWE-020/ExternalAPIsUsedWithUntrustedData.ql

View File

@@ -0,0 +1,11 @@
#select
| ExternalAPISinkExample.java:12:5:12:70 | ... + ... | ExternalAPISinkExample.java:12:21:12:48 | getParameter(...) : String | ExternalAPISinkExample.java:12:5:12:70 | ... + ... | Call to javax.servlet.http.HttpServletResponse.sendError with untrusted data from $@. | ExternalAPISinkExample.java:12:21:12:48 | getParameter(...) : String | getParameter(...) : String |
edges
| ExternalAPISinkExample.java:12:21:12:48 | getParameter(...) : String | ExternalAPISinkExample.java:12:5:12:70 | ... + ... | provenance | Src:MaD:2 Sink:MaD:1 |
models
| 1 | Sink: javax.servlet.http; HttpServletResponse; false; sendError; (int,String); ; Argument[1]; information-leak; manual |
| 2 | Source: javax.servlet; ServletRequest; false; getParameter; (String); ; ReturnValue; remote; manual |
nodes
| ExternalAPISinkExample.java:12:5:12:70 | ... + ... | semmle.label | ... + ... |
| ExternalAPISinkExample.java:12:21:12:48 | getParameter(...) : String | semmle.label | getParameter(...) : String |
subpaths

View File

@@ -0,0 +1,4 @@
query: Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql
postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -3,4 +3,4 @@ extensions:
pack: codeql/java-all
extensible: sourceModel
data:
- ["loginjection", "LogInjectionTest", False, "source", "()", "", "ReturnValue", "remote", "manual"]
- ["loginjection", "LogInjectionTest", False, "source", "()", "", "ReturnValue", "remote", "manual"]

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +0,0 @@
import java
import semmle.code.java.security.LogInjectionQuery
import utils.test.InlineFlowTest
import TaintFlowTest<LogInjectionConfig>

View File

@@ -0,0 +1,4 @@
query: Security/CWE/CWE-117/LogInjection.ql
postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,13 @@
| UnsafeCertTrustTest.java:24:3:24:11 | sslEngine | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:25:3:25:11 | sslEngine | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:26:3:26:11 | sslEngine | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:35:3:35:11 | sslEngine | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:36:3:36:11 | sslEngine | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:37:3:37:11 | sslEngine | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:64:3:64:8 | socket | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:74:3:74:8 | socket | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:84:3:84:8 | socket | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:91:3:91:8 | socket | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:141:3:141:8 | socket | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:153:4:153:60 | useSslProtocol(...) | Unsafe configuration of trusted certificates. |
| UnsafeCertTrustTest.java:157:4:157:70 | setSslContextFactory(...) | Unsafe configuration of trusted certificates. |

View File

@@ -21,9 +21,9 @@ public class UnsafeCertTrustTest {
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm(null);
sslEngine.setSSLParameters(sslParameters);
sslEngine.beginHandshake(); // $hasUnsafeCertTrust
sslEngine.wrap(new ByteBuffer[] {}, null); // $hasUnsafeCertTrust
sslEngine.unwrap(null, null, 0, 0); // $hasUnsafeCertTrust
sslEngine.beginHandshake(); // $ Alert
sslEngine.wrap(new ByteBuffer[] {}, null); // $ Alert
sslEngine.unwrap(null, null, 0, 0); // $ Alert
}
public void testSSLEngineEndpointIdSetEmpty() throws Exception {
@@ -32,9 +32,9 @@ public class UnsafeCertTrustTest {
SSLParameters sslParameters = sslEngine.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("");
sslEngine.setSSLParameters(sslParameters);
sslEngine.beginHandshake(); // $hasUnsafeCertTrust
sslEngine.wrap(new ByteBuffer[] {}, null); // $hasUnsafeCertTrust
sslEngine.unwrap(null, null, 0, 0); // $hasUnsafeCertTrust
sslEngine.beginHandshake(); // $ Alert
sslEngine.wrap(new ByteBuffer[] {}, null); // $ Alert
sslEngine.unwrap(null, null, 0, 0); // $ Alert
}
public void testSSLEngineEndpointIdSafe() throws Exception {
@@ -61,7 +61,7 @@ public class UnsafeCertTrustTest {
SSLContext sslContext = SSLContext.getInstance("TLS");
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket();
socket.getOutputStream(); // $hasUnsafeCertTrust
socket.getOutputStream(); // $ Alert
}
public void testSSLSocketEndpointIdSetNull() throws Exception {
@@ -71,7 +71,7 @@ public class UnsafeCertTrustTest {
SSLParameters sslParameters = socket.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm(null);
socket.setSSLParameters(sslParameters);
socket.getOutputStream(); // $hasUnsafeCertTrust
socket.getOutputStream(); // $ Alert
}
public void testSSLSocketEndpointIdSetEmpty() throws Exception {
@@ -81,14 +81,14 @@ public class UnsafeCertTrustTest {
SSLParameters sslParameters = socket.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("");
socket.setSSLParameters(sslParameters);
socket.getOutputStream(); // $hasUnsafeCertTrust
socket.getOutputStream(); // $ Alert
}
public void testSSLSocketEndpointIdAfterConnecting() throws Exception {
SSLContext sslContext = SSLContext.getInstance("TLS");
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
SSLSocket socket = (SSLSocket) socketFactory.createSocket();
socket.getOutputStream(); // $hasUnsafeCertTrust
socket.getOutputStream(); // $ Alert
SSLParameters sslParameters = socket.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
socket.setSSLParameters(sslParameters);
@@ -138,7 +138,7 @@ public class UnsafeCertTrustTest {
SSLParameters sslParameters = sslSocket.getSSLParameters();
sslParameters.setEndpointIdentificationAlgorithm("HTTPS");
sslSocket.setSSLParameters(sslParameters);
socket.getOutputStream(); // $ SPURIOUS: hasUnsafeCertTrust
socket.getOutputStream(); // $ SPURIOUS: Alert
}
public void testSocketEndpointIdNotSet() throws Exception {
@@ -150,11 +150,11 @@ public class UnsafeCertTrustTest {
public void testRabbitMQFactoryEnableHostnameVerificationNotSet() throws Exception {
{
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.useSslProtocol(SSLContext.getDefault()); // $hasUnsafeCertTrust
connectionFactory.useSslProtocol(SSLContext.getDefault()); // $ Alert
}
{
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setSslContextFactory(new TestSslContextFactory()); // $hasUnsafeCertTrust
connectionFactory.setSslContextFactory(new TestSslContextFactory()); // $ Alert
}
}

View File

@@ -1,22 +0,0 @@
import java
import semmle.code.java.security.UnsafeCertTrustQuery
import utils.test.InlineExpectationsTest
module UnsafeCertTrustTest implements TestSig {
string getARelevantTag() { result = "hasUnsafeCertTrust" }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasUnsafeCertTrust" and
exists(Expr unsafeTrust |
unsafeTrust instanceof RabbitMQEnableHostnameVerificationNotSet
or
SslEndpointIdentificationFlow::flowTo(DataFlow::exprNode(unsafeTrust))
|
unsafeTrust.getLocation() = location and
element = unsafeTrust.toString() and
value = ""
)
}
}
import MakeTest<UnsafeCertTrustTest>

View File

@@ -0,0 +1,4 @@
query: Security/CWE/CWE-273/UnsafeCertTrust.ql
postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,11 @@
#select
| TrustBoundaryViolations.java:14:52:14:56 | input | TrustBoundaryViolations.java:11:24:11:52 | getParameter(...) : String | TrustBoundaryViolations.java:14:52:14:56 | input | This servlet reads data from a $@ and writes it to a session variable. | TrustBoundaryViolations.java:11:24:11:52 | getParameter(...) : String | remote source |
edges
| TrustBoundaryViolations.java:11:24:11:52 | getParameter(...) : String | TrustBoundaryViolations.java:14:52:14:56 | input | provenance | Src:MaD:2 Sink:MaD:1 |
models
| 1 | Sink: javax.servlet.http; HttpSession; true; setAttribute; ; ; Argument[0..1]; trust-boundary-violation; manual |
| 2 | Source: javax.servlet; ServletRequest; false; getParameter; (String); ; ReturnValue; remote; manual |
nodes
| TrustBoundaryViolations.java:11:24:11:52 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| TrustBoundaryViolations.java:14:52:14:56 | input | semmle.label | input |
subpaths

View File

@@ -8,10 +8,10 @@ public class TrustBoundaryViolations extends HttpServlet {
Validator validator;
public void doGet(HttpServletRequest request, HttpServletResponse response) {
String input = request.getParameter("input");
String input = request.getParameter("input"); // $ Source
// BAD: The input is written to the session without being sanitized.
request.getSession().setAttribute("input", input); // $ hasTaintFlow
request.getSession().setAttribute("input", input); // $ Alert
String input2 = request.getParameter("input2");

View File

@@ -1,4 +0,0 @@
import java
import semmle.code.java.security.TrustBoundaryViolationQuery
import utils.test.InlineFlowTest
import TaintFlowTest<TrustBoundaryConfig>

View File

@@ -0,0 +1,4 @@
query: Security/CWE/CWE-501/TrustBoundaryViolation.ql
postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -0,0 +1,15 @@
#select
| Test.java:7:21:7:53 | ... + ... | Test.java:7:46:7:53 | password : String | Test.java:7:21:7:53 | ... + ... | This $@ is written to a log file. | Test.java:7:46:7:53 | password | potentially sensitive information |
| Test.java:8:22:8:52 | ... + ... | Test.java:8:44:8:52 | authToken : String | Test.java:8:22:8:52 | ... + ... | This $@ is written to a log file. | Test.java:8:44:8:52 | authToken | potentially sensitive information |
edges
| Test.java:7:46:7:53 | password : String | Test.java:7:21:7:53 | ... + ... | provenance | Sink:MaD:2 |
| Test.java:8:44:8:52 | authToken : String | Test.java:8:22:8:52 | ... + ... | provenance | Sink:MaD:1 |
models
| 1 | Sink: org.apache.logging.log4j; Logger; true; error; (String); ; Argument[0]; log-injection; manual |
| 2 | Sink: org.apache.logging.log4j; Logger; true; info; (String); ; Argument[0]; log-injection; manual |
nodes
| Test.java:7:21:7:53 | ... + ... | semmle.label | ... + ... |
| Test.java:7:46:7:53 | password : String | semmle.label | password : String |
| Test.java:8:22:8:52 | ... + ... | semmle.label | ... + ... |
| Test.java:8:44:8:52 | authToken : String | semmle.label | authToken : String |
subpaths

View File

@@ -1,4 +0,0 @@
import java
import utils.test.InlineFlowTest
import semmle.code.java.security.SensitiveLoggingQuery
import TaintFlowTest<SensitiveLoggerConfig>

View File

@@ -0,0 +1,4 @@
query: Security/CWE/CWE-532/SensitiveInfoLog.ql
postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -4,8 +4,8 @@ class Test {
void test(String password, String authToken, String username, String nullToken, String stringTokenizer) {
Logger logger = null;
logger.info("User's password is: " + password); // $ hasTaintFlow
logger.error("Auth failed for: " + authToken); // $ hasTaintFlow
logger.info("User's password is: " + password); // $ Alert
logger.error("Auth failed for: " + authToken); // $ Alert
logger.error("Auth failed for: " + username); // Safe
logger.error("Auth failed for: " + nullToken); // Safe
logger.error("Auth failed for: " + stringTokenizer); // Safe

View File

@@ -0,0 +1,31 @@
#select
| ConditionalBypassTest.java:24:4:24:24 | login(...) | ConditionalBypassTest.java:19:20:19:50 | getParameter(...) : String | ConditionalBypassTest.java:23:7:23:24 | ... == ... | Sensitive method may not be executed depending on a $@, which flows from $@. | ConditionalBypassTest.java:23:7:23:24 | ... == ... | this condition | ConditionalBypassTest.java:19:20:19:50 | getParameter(...) | user-controlled value |
| ConditionalBypassTest.java:30:4:30:24 | login(...) | ConditionalBypassTest.java:29:7:29:28 | getValue(...) : String | ConditionalBypassTest.java:29:7:29:44 | equals(...) | Sensitive method may not be executed depending on a $@, which flows from $@. | ConditionalBypassTest.java:29:7:29:44 | equals(...) | this condition | ConditionalBypassTest.java:29:7:29:28 | getValue(...) | user-controlled value |
| ConditionalBypassTest.java:77:4:77:24 | login(...) | ConditionalBypassTest.java:76:7:76:28 | getValue(...) : String | ConditionalBypassTest.java:76:7:76:39 | ... == ... | Sensitive method may not be executed depending on a $@, which flows from $@. | ConditionalBypassTest.java:76:7:76:39 | ... == ... | this condition | ConditionalBypassTest.java:76:7:76:28 | getValue(...) | user-controlled value |
| ConditionalBypassTest.java:89:4:89:24 | login(...) | ConditionalBypassTest.java:88:7:88:28 | getValue(...) : String | ConditionalBypassTest.java:88:7:88:39 | ... == ... | Sensitive method may not be executed depending on a $@, which flows from $@. | ConditionalBypassTest.java:88:7:88:39 | ... == ... | this condition | ConditionalBypassTest.java:88:7:88:28 | getValue(...) | user-controlled value |
| ConditionalBypassTest.java:134:4:134:24 | login(...) | ConditionalBypassTest.java:133:7:133:28 | getValue(...) : String | ConditionalBypassTest.java:133:7:133:39 | ... == ... | Sensitive method may not be executed depending on a $@, which flows from $@. | ConditionalBypassTest.java:133:7:133:39 | ... == ... | this condition | ConditionalBypassTest.java:133:7:133:28 | getValue(...) | user-controlled value |
| ConditionalBypassTest.java:146:5:146:29 | authorize(...) | ConditionalBypassTest.java:145:8:145:29 | getValue(...) : String | ConditionalBypassTest.java:145:8:145:40 | ... == ... | Sensitive method may not be executed depending on a $@, which flows from $@. | ConditionalBypassTest.java:145:8:145:40 | ... == ... | this condition | ConditionalBypassTest.java:145:8:145:29 | getValue(...) | user-controlled value |
edges
| ConditionalBypassTest.java:19:20:19:50 | getParameter(...) : String | ConditionalBypassTest.java:23:7:23:24 | ... == ... | provenance | Src:MaD:2 |
| ConditionalBypassTest.java:29:7:29:28 | getValue(...) : String | ConditionalBypassTest.java:29:7:29:44 | equals(...) | provenance | Src:MaD:1 |
| ConditionalBypassTest.java:76:7:76:28 | getValue(...) : String | ConditionalBypassTest.java:76:7:76:39 | ... == ... | provenance | Src:MaD:1 |
| ConditionalBypassTest.java:88:7:88:28 | getValue(...) : String | ConditionalBypassTest.java:88:7:88:39 | ... == ... | provenance | Src:MaD:1 |
| ConditionalBypassTest.java:133:7:133:28 | getValue(...) : String | ConditionalBypassTest.java:133:7:133:39 | ... == ... | provenance | Src:MaD:1 |
| ConditionalBypassTest.java:145:8:145:29 | getValue(...) : String | ConditionalBypassTest.java:145:8:145:40 | ... == ... | provenance | Src:MaD:1 |
models
| 1 | Source: javax.servlet.http; Cookie; false; getValue; (); ; ReturnValue; remote; manual |
| 2 | Source: javax.servlet; ServletRequest; false; getParameter; (String); ; ReturnValue; remote; manual |
nodes
| ConditionalBypassTest.java:19:20:19:50 | getParameter(...) : String | semmle.label | getParameter(...) : String |
| ConditionalBypassTest.java:23:7:23:24 | ... == ... | semmle.label | ... == ... |
| ConditionalBypassTest.java:29:7:29:28 | getValue(...) : String | semmle.label | getValue(...) : String |
| ConditionalBypassTest.java:29:7:29:44 | equals(...) | semmle.label | equals(...) |
| ConditionalBypassTest.java:76:7:76:28 | getValue(...) : String | semmle.label | getValue(...) : String |
| ConditionalBypassTest.java:76:7:76:39 | ... == ... | semmle.label | ... == ... |
| ConditionalBypassTest.java:88:7:88:28 | getValue(...) : String | semmle.label | getValue(...) : String |
| ConditionalBypassTest.java:88:7:88:39 | ... == ... | semmle.label | ... == ... |
| ConditionalBypassTest.java:133:7:133:28 | getValue(...) : String | semmle.label | getValue(...) : String |
| ConditionalBypassTest.java:133:7:133:39 | ... == ... | semmle.label | ... == ... |
| ConditionalBypassTest.java:145:8:145:29 | getValue(...) : String | semmle.label | getValue(...) : String |
| ConditionalBypassTest.java:145:8:145:40 | ... == ... | semmle.label | ... == ... |
subpaths

View File

@@ -16,18 +16,18 @@ class ConditionalBypassTest {
String user = request.getParameter("user");
String password = request.getParameter("password");
String isAdmin = request.getParameter("isAdmin");
String isAdmin = request.getParameter("isAdmin"); // $ Source
// BAD: login is only executed if isAdmin is false, but isAdmin
// is controlled by the user
if (isAdmin == "false") // $ hasConditionalBypassTest
login(user, password);
if (isAdmin == "false") // $ Sink
login(user, password); // $ Alert
Cookie adminCookie = getCookies()[0];
// BAD: login is only executed if the cookie value is false, but the cookie
// is controlled by the user
if (adminCookie.getValue().equals("false")) // $ hasConditionalBypassTest
login(user, password);
if (adminCookie.getValue().equals("false")) // $ Source Sink
login(user, password); // $ Alert
// GOOD: both methods are conditionally executed, but they probably
// both perform the security-critical action
@@ -38,7 +38,7 @@ class ConditionalBypassTest {
}
// FALSE NEGATIVE: we have no way of telling that the skipped method is sensitive
if (adminCookie.getValue() == "false") // $ MISSING: hasConditionalBypassTest
if (adminCookie.getValue() == "false") // $ MISSING: Alert
doReallyImportantSecurityWork();
InetAddress local = InetAddress.getLocalHost();
@@ -73,8 +73,8 @@ class ConditionalBypassTest {
public static void test2(String user, String password) {
Cookie adminCookie = getCookies()[0];
// BAD: login may happen once or twice
if (adminCookie.getValue() == "false") // $ hasConditionalBypassTest
login(user, password);
if (adminCookie.getValue() == "false") // $ Source Sink
login(user, password); // $ Alert
else {
// do something else
doIt();
@@ -85,8 +85,8 @@ class ConditionalBypassTest {
public static void test3(String user, String password) {
Cookie adminCookie = getCookies()[0];
// BAD: login may not happen
if (adminCookie.getValue() == "false") // $ hasConditionalBypassTest
login(user, password);
if (adminCookie.getValue() == "false") // $ Source Sink
login(user, password); // $ Alert
else {
// do something else
doIt();
@@ -130,8 +130,8 @@ class ConditionalBypassTest {
public static void test7(String user, String password) {
Cookie adminCookie = getCookies()[0];
// BAD: login is bypasseable
if (adminCookie.getValue() == "false") { // $ hasConditionalBypassTest
login(user, password);
if (adminCookie.getValue() == "false") { // $ Source Sink
login(user, password); // $ Alert
return;
} else {
doIt();
@@ -142,8 +142,8 @@ class ConditionalBypassTest {
Cookie adminCookie = getCookies()[0];
{
// BAD: login may not happen
if (adminCookie.getValue() == "false") // $ hasConditionalBypassTest
authorize(user, password);
if (adminCookie.getValue() == "false") // $ Source Sink
authorize(user, password); // $ Alert
else {
// do something else
doIt();

View File

@@ -1,18 +0,0 @@
import java
import semmle.code.java.security.ConditionalBypassQuery
import utils.test.InlineExpectationsTest
module ConditionalBypassTest implements TestSig {
string getARelevantTag() { result = "hasConditionalBypassTest" }
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasConditionalBypassTest" and
exists(DataFlow::Node sink | ConditionalBypassFlow::flowTo(sink) |
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}
import MakeTest<ConditionalBypassTest>

View File

@@ -0,0 +1,4 @@
query: Security/CWE/CWE-807/ConditionalBypass.ql
postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

@@ -1,4 +0,0 @@
import java
import semmle.code.java.security.AndroidSensitiveCommunicationQuery
import utils.test.InlineFlowTest
import TaintFlowTest<SensitiveCommunicationConfig>

View File

@@ -0,0 +1,80 @@
#select
| SensitiveCommunication.java:14:31:14:36 | intent | SensitiveCommunication.java:12:34:12:38 | token : String | SensitiveCommunication.java:14:31:14:36 | intent | This call may leak $@. | SensitiveCommunication.java:12:34:12:38 | token | sensitive information |
| SensitiveCommunication.java:14:31:14:36 | intent | SensitiveCommunication.java:13:41:13:52 | refreshToken : String | SensitiveCommunication.java:14:31:14:36 | intent | This call may leak $@. | SensitiveCommunication.java:13:41:13:52 | refreshToken | sensitive information |
| SensitiveCommunication.java:26:31:26:36 | intent | SensitiveCommunication.java:25:32:25:39 | password : String | SensitiveCommunication.java:26:31:26:36 | intent | This call may leak $@. | SensitiveCommunication.java:25:32:25:39 | password | sensitive information |
| SensitiveCommunication.java:38:31:38:36 | intent | SensitiveCommunication.java:36:35:36:39 | email : String | SensitiveCommunication.java:38:31:38:36 | intent | This call may leak $@. | SensitiveCommunication.java:36:35:36:39 | email | sensitive information |
| SensitiveCommunication.java:52:31:52:36 | intent | SensitiveCommunication.java:50:22:50:29 | password : String | SensitiveCommunication.java:52:31:52:36 | intent | This call may leak $@. | SensitiveCommunication.java:50:22:50:29 | password | sensitive information |
| SensitiveCommunication.java:98:54:98:59 | intent | SensitiveCommunication.java:97:35:97:40 | ticket : String | SensitiveCommunication.java:98:54:98:59 | intent | This call may leak $@. | SensitiveCommunication.java:97:35:97:40 | ticket | sensitive information |
| SensitiveCommunication.java:111:54:111:59 | intent | SensitiveCommunication.java:109:32:109:39 | passcode : String | SensitiveCommunication.java:111:54:111:59 | intent | This call may leak $@. | SensitiveCommunication.java:109:32:109:39 | passcode | sensitive information |
| SensitiveCommunication.java:140:54:140:59 | intent | SensitiveCommunication.java:136:33:136:38 | passwd : String | SensitiveCommunication.java:140:54:140:59 | intent | This call may leak $@. | SensitiveCommunication.java:136:33:136:38 | passwd | sensitive information |
| SensitiveCommunication.java:158:54:158:59 | intent | SensitiveCommunication.java:155:45:155:52 | password : String | SensitiveCommunication.java:158:54:158:59 | intent | This call may leak $@. | SensitiveCommunication.java:155:45:155:52 | password | sensitive information |
edges
| SensitiveCommunication.java:12:9:12:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | SensitiveCommunication.java:14:31:14:36 | intent | provenance | Sink:MaD:1 Sink:MaD:1 |
| SensitiveCommunication.java:12:34:12:38 | token : String | SensitiveCommunication.java:12:9:12:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | provenance | MaD:3 |
| SensitiveCommunication.java:13:9:13:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | SensitiveCommunication.java:14:31:14:36 | intent | provenance | Sink:MaD:1 Sink:MaD:1 |
| SensitiveCommunication.java:13:41:13:52 | refreshToken : String | SensitiveCommunication.java:13:9:13:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | provenance | MaD:3 |
| SensitiveCommunication.java:25:9:25:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | SensitiveCommunication.java:26:31:26:36 | intent | provenance | Sink:MaD:1 Sink:MaD:1 |
| SensitiveCommunication.java:25:32:25:39 | password : String | SensitiveCommunication.java:25:9:25:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | provenance | MaD:3 |
| SensitiveCommunication.java:36:9:36:14 | bundle [post update] : Bundle [<map.value>] : String | SensitiveCommunication.java:37:26:37:31 | bundle : Bundle [<map.value>] : String | provenance | |
| SensitiveCommunication.java:36:35:36:39 | email : String | SensitiveCommunication.java:36:9:36:14 | bundle [post update] : Bundle [<map.value>] : String | provenance | MaD:6 |
| SensitiveCommunication.java:37:9:37:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | SensitiveCommunication.java:38:31:38:36 | intent | provenance | Sink:MaD:1 Sink:MaD:1 |
| SensitiveCommunication.java:37:26:37:31 | bundle : Bundle [<map.value>] : String | SensitiveCommunication.java:37:9:37:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | provenance | MaD:4 |
| SensitiveCommunication.java:50:9:50:16 | userinfo [post update] : ArrayList [<element>] : String | SensitiveCommunication.java:51:52:51:59 | userinfo : ArrayList [<element>] : String | provenance | |
| SensitiveCommunication.java:50:22:50:29 | password : String | SensitiveCommunication.java:50:9:50:16 | userinfo [post update] : ArrayList [<element>] : String | provenance | MaD:7 |
| SensitiveCommunication.java:51:9:51:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>, <element>] : String | SensitiveCommunication.java:52:31:52:36 | intent | provenance | Sink:MaD:1 Sink:MaD:1 |
| SensitiveCommunication.java:51:9:51:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>, <element>] : String | SensitiveCommunication.java:52:31:52:36 | intent | provenance | Sink:MaD:1 Sink:MaD:1 Sink:MaD:1 |
| SensitiveCommunication.java:51:52:51:59 | userinfo : ArrayList [<element>] : String | SensitiveCommunication.java:51:9:51:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>, <element>] : String | provenance | MaD:5 |
| SensitiveCommunication.java:97:9:97:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | SensitiveCommunication.java:98:54:98:59 | intent | provenance | Sink:MaD:2 Sink:MaD:2 |
| SensitiveCommunication.java:97:35:97:40 | ticket : String | SensitiveCommunication.java:97:9:97:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | provenance | MaD:3 |
| SensitiveCommunication.java:109:9:109:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | SensitiveCommunication.java:111:54:111:59 | intent | provenance | Sink:MaD:2 Sink:MaD:2 |
| SensitiveCommunication.java:109:32:109:39 | passcode : String | SensitiveCommunication.java:109:9:109:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | provenance | MaD:3 |
| SensitiveCommunication.java:136:9:136:14 | bundle [post update] : Bundle [<map.value>] : String | SensitiveCommunication.java:137:26:137:31 | bundle : Bundle [<map.value>] : String | provenance | |
| SensitiveCommunication.java:136:33:136:38 | passwd : String | SensitiveCommunication.java:136:9:136:14 | bundle [post update] : Bundle [<map.value>] : String | provenance | MaD:6 |
| SensitiveCommunication.java:137:9:137:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | SensitiveCommunication.java:140:54:140:59 | intent | provenance | Sink:MaD:2 Sink:MaD:2 |
| SensitiveCommunication.java:137:26:137:31 | bundle : Bundle [<map.value>] : String | SensitiveCommunication.java:137:9:137:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | provenance | MaD:4 |
| SensitiveCommunication.java:155:9:155:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | SensitiveCommunication.java:158:54:158:59 | intent | provenance | Sink:MaD:2 Sink:MaD:2 |
| SensitiveCommunication.java:155:9:155:26 | getExtras(...) [post update] : Bundle [<map.value>] : String | SensitiveCommunication.java:155:9:155:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | provenance | |
| SensitiveCommunication.java:155:45:155:52 | password : String | SensitiveCommunication.java:155:9:155:26 | getExtras(...) [post update] : Bundle [<map.value>] : String | provenance | MaD:6 |
models
| 1 | Sink: android.content; Context; true; sendBroadcast; ; ; Argument[0]; intent-redirection; manual |
| 2 | Sink: android.content; Context; true; sendBroadcastWithMultiplePermissions; ; ; Argument[0]; intent-redirection; manual |
| 3 | Summary: android.content; Intent; true; putExtra; ; ; Argument[1]; Argument[this].SyntheticField[android.content.Intent.extras].MapValue; value; manual |
| 4 | Summary: android.content; Intent; true; putExtras; (Bundle); ; Argument[0].MapValue; Argument[this].SyntheticField[android.content.Intent.extras].MapValue; value; manual |
| 5 | Summary: android.content; Intent; true; putStringArrayListExtra; ; ; Argument[1]; Argument[this].SyntheticField[android.content.Intent.extras].MapValue; value; manual |
| 6 | Summary: android.os; BaseBundle; true; putString; ; ; Argument[1]; Argument[this].MapValue; value; manual |
| 7 | Summary: java.util; Collection; true; add; ; ; Argument[0]; Argument[this].Element; value; manual |
nodes
| SensitiveCommunication.java:12:9:12:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | semmle.label | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String |
| SensitiveCommunication.java:12:34:12:38 | token : String | semmle.label | token : String |
| SensitiveCommunication.java:13:9:13:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | semmle.label | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String |
| SensitiveCommunication.java:13:41:13:52 | refreshToken : String | semmle.label | refreshToken : String |
| SensitiveCommunication.java:14:31:14:36 | intent | semmle.label | intent |
| SensitiveCommunication.java:25:9:25:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | semmle.label | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String |
| SensitiveCommunication.java:25:32:25:39 | password : String | semmle.label | password : String |
| SensitiveCommunication.java:26:31:26:36 | intent | semmle.label | intent |
| SensitiveCommunication.java:36:9:36:14 | bundle [post update] : Bundle [<map.value>] : String | semmle.label | bundle [post update] : Bundle [<map.value>] : String |
| SensitiveCommunication.java:36:35:36:39 | email : String | semmle.label | email : String |
| SensitiveCommunication.java:37:9:37:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | semmle.label | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String |
| SensitiveCommunication.java:37:26:37:31 | bundle : Bundle [<map.value>] : String | semmle.label | bundle : Bundle [<map.value>] : String |
| SensitiveCommunication.java:38:31:38:36 | intent | semmle.label | intent |
| SensitiveCommunication.java:50:9:50:16 | userinfo [post update] : ArrayList [<element>] : String | semmle.label | userinfo [post update] : ArrayList [<element>] : String |
| SensitiveCommunication.java:50:22:50:29 | password : String | semmle.label | password : String |
| SensitiveCommunication.java:51:9:51:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>, <element>] : String | semmle.label | intent [post update] : Intent [android.content.Intent.extras, <map.value>, <element>] : String |
| SensitiveCommunication.java:51:52:51:59 | userinfo : ArrayList [<element>] : String | semmle.label | userinfo : ArrayList [<element>] : String |
| SensitiveCommunication.java:52:31:52:36 | intent | semmle.label | intent |
| SensitiveCommunication.java:97:9:97:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | semmle.label | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String |
| SensitiveCommunication.java:97:35:97:40 | ticket : String | semmle.label | ticket : String |
| SensitiveCommunication.java:98:54:98:59 | intent | semmle.label | intent |
| SensitiveCommunication.java:109:9:109:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | semmle.label | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String |
| SensitiveCommunication.java:109:32:109:39 | passcode : String | semmle.label | passcode : String |
| SensitiveCommunication.java:111:54:111:59 | intent | semmle.label | intent |
| SensitiveCommunication.java:136:9:136:14 | bundle [post update] : Bundle [<map.value>] : String | semmle.label | bundle [post update] : Bundle [<map.value>] : String |
| SensitiveCommunication.java:136:33:136:38 | passwd : String | semmle.label | passwd : String |
| SensitiveCommunication.java:137:9:137:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | semmle.label | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String |
| SensitiveCommunication.java:137:26:137:31 | bundle : Bundle [<map.value>] : String | semmle.label | bundle : Bundle [<map.value>] : String |
| SensitiveCommunication.java:140:54:140:59 | intent | semmle.label | intent |
| SensitiveCommunication.java:155:9:155:14 | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String | semmle.label | intent [post update] : Intent [android.content.Intent.extras, <map.value>] : String |
| SensitiveCommunication.java:155:9:155:26 | getExtras(...) [post update] : Bundle [<map.value>] : String | semmle.label | getExtras(...) [post update] : Bundle [<map.value>] : String |
| SensitiveCommunication.java:155:45:155:52 | password : String | semmle.label | password : String |
| SensitiveCommunication.java:158:54:158:59 | intent | semmle.label | intent |
subpaths

View File

@@ -9,9 +9,9 @@ class SensitiveBroadcast {
public void sendBroadcast1(Context context, String token, String refreshToken) {
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
intent.putExtra("token", token);
intent.putExtra("refreshToken", refreshToken);
context.sendBroadcast(intent); // $ hasTaintFlow
intent.putExtra("token", token); // $ Source
intent.putExtra("refreshToken", refreshToken); // $ Source
context.sendBroadcast(intent); // $ Alert
}
// BAD - Tests broadcast of sensitive user information with intent extra.
@@ -22,41 +22,41 @@ class SensitiveBroadcast {
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
intent.putExtra("name", userName);
intent.putExtra("pwd", password);
context.sendBroadcast(intent); // $ hasTaintFlow
intent.putExtra("pwd", password); // $ Source
context.sendBroadcast(intent); // $ Alert
}
// BAD - Tests broadcast of email information with extra bundle.
public void sendBroadcast3(Context context) {
String email = "user123@example.com";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
Bundle bundle = new Bundle();
bundle.putString("email", email);
bundle.putString("email", email); // $ Source
intent.putExtras(bundle);
context.sendBroadcast(intent); // $ hasTaintFlow
}
context.sendBroadcast(intent); // $ Alert
}
// BAD - Tests broadcast of sensitive user information with null permission.
public void sendBroadcast4(Context context) {
String username = "test123";
String password = "abc12345";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
ArrayList<String> userinfo = new ArrayList<String>();
userinfo.add(username);
userinfo.add(password);
userinfo.add(password); // $ Source
intent.putStringArrayListExtra("userinfo", userinfo);
context.sendBroadcast(intent, null); // $ hasTaintFlow
context.sendBroadcast(intent, null); // $ Alert
}
// GOOD - Tests broadcast of sensitive user information with permission using string literal.
public void sendBroadcast5(Context context) {
String username = "test123";
String password = "abc12345";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
intent.putExtra("name", username);
@@ -67,106 +67,106 @@ class SensitiveBroadcast {
// GOOD - Tests broadcast of access ticket with permission using string object.
public void sendBroadcast6(Context context) {
String ticket = "Tk9UIFNlY3VyZSBUaWNrZXQ=";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
intent.putExtra("ticket", ticket);
String perm = "com.example.user_permission";
context.sendBroadcast(intent, perm);
context.sendBroadcast(intent, perm);
}
// GOOD - Tests broadcast of sensitive user information to a specific application.
public void sendBroadcast7(Context context) {
String username = "test123";
String password = "abc12345";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
intent.setClassName("com.example2", "com.example2.UserInfoHandler");
intent.putExtra("name", username);
intent.putExtra("pwd", password);
context.sendBroadcast(intent);
}
}
// BAD - Tests broadcast of access ticket with multiple permissions using direct empty array initialization.
public void sendBroadcast8(Context context) {
String ticket = "Tk9UIFNlY3VyZSBUaWNrZXQ=";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
intent.putExtra("ticket", ticket);
context.sendBroadcastWithMultiplePermissions(intent, new String[]{}); // $ hasTaintFlow
}
intent.putExtra("ticket", ticket); // $ Source
context.sendBroadcastWithMultiplePermissions(intent, new String[]{}); // $ Alert
}
// BAD - Tests broadcast of sensitive user information with multiple permissions using empty array initialization through a variable.
public void sendBroadcast9(Context context) {
String username = "test123";
String passcode = "abc12345";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
intent.putExtra("name", username);
intent.putExtra("pwd", passcode);
intent.putExtra("pwd", passcode); // $ Source
String[] perms = new String[0];
context.sendBroadcastWithMultiplePermissions(intent, perms); // $ hasTaintFlow
}
context.sendBroadcastWithMultiplePermissions(intent, perms); // $ Alert
}
// GOOD - Tests broadcast of sensitive user information with multiple permissions.
public void sendBroadcast10(Context context) {
String username = "test123";
String password = "abc12345";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
intent.putExtra("name", username);
intent.putExtra("pwd", password);
String[] perms = new String[]{"com.example.custom_action", "com.example.custom_action2"};
context.sendBroadcastWithMultiplePermissions(intent, perms);
}
}
// BAD - Tests broadcast of sensitive user information with multiple permissions using empty array initialization through two variables and `intent.putExtras(bundle)`.
public void sendBroadcast11(Context context) {
String username = "test123";
String passwd = "abc12345";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
Bundle bundle = new Bundle();
bundle.putString("name", username);
bundle.putString("pwd", passwd);
bundle.putString("pwd", passwd); // $ Source
intent.putExtras(bundle);
String[] perms = new String[0];
String[] perms2 = perms;
context.sendBroadcastWithMultiplePermissions(intent, perms2); // $ hasTaintFlow
}
context.sendBroadcastWithMultiplePermissions(intent, perms2); // $ Alert
}
/**
/**
* BAD - Tests broadcast of sensitive user information with multiple permissions using empty array initialization through two variables and `intent.getExtras().putString()`.
*/
*/
public void sendBroadcast12(Context context) {
String username = "test123";
String password = "abc12345";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
Bundle bundle = new Bundle();
intent.putExtras(bundle);
intent.getExtras().putString("name", username);
intent.getExtras().putString("pwd", password);
intent.getExtras().putString("pwd", password); // $ Source
String[] perms = new String[0];
String[] perms2 = perms;
context.sendBroadcastWithMultiplePermissions(intent, perms2); // $ hasTaintFlow
}
context.sendBroadcastWithMultiplePermissions(intent, perms2); // $ Alert
}
// GOOD - Tests broadcast of sensitive user information with ordered broadcast.
public void sendBroadcast13(Context context) {
String username = "test123";
String password = "abc12345";
Intent intent = new Intent();
intent.setAction("com.example.custom_action");
intent.putExtra("name", username);
intent.putExtra("pwd", password);
context.sendOrderedBroadcast(intent, "com.example.USER_PERM");
}
}
}

View File

@@ -0,0 +1,4 @@
query: Security/CWE/CWE-927/SensitiveCommunication.ql
postprocess:
- utils/test/PrettyPrintModels.ql
- utils/test/InlineExpectationsTestQuery.ql

View File

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