Skip to content
This repository was archived by the owner on Apr 4, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion codeql
Submodule codeql updated 1152 files
35 changes: 35 additions & 0 deletions java/CWE-798/HardcodedBase64Usage.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @name Base64 Hardcoded Password
* @description Static hardcoded base64 password / key
* @kind path-problem
* @problem.severity error
* @security-severity 8.0
* @precision low
* @sub-severity high
* @id java/hardcoded-password
* @tags security
* external/cwe/cwe-798
*/

import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking2
import DataFlow::PathGraph
// Internal
import github.Encoding
import github.Hardcoded

class HardcodedPasswordBase64 extends TaintTracking::Configuration {
HardcodedPasswordBase64() { this = "HardcodedPasswordBase64" }

override predicate isSource(DataFlow::Node source) { source instanceof Hardcoded }

override predicate isSink(DataFlow::Node sink) { sink instanceof Base64::Decoding }
}

// ========== Query ==========
from DataFlow::PathNode source, DataFlow::PathNode sink, HardcodedPasswordBase64 config
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "Sensitive data is being logged $@.", source.getNode(),
"user-provided value"
43 changes: 43 additions & 0 deletions java/github/Encoding.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.dataflow.TaintTracking2

module Base64 {
abstract class Encoding extends DataFlow::Node { }

abstract class Decoding extends DataFlow::Node { }

// codeql/java/ql/lib/semmle/code/java/security/HardcodedCredentialsApiCallQuery.qll
class Encoders extends Base64::Encoding {
Encoders() {
exists(MethodAccess ma |
ma.getMethod()
.hasQualifiedName([
"java.util", "cn.hutool.core.codec", "org.apache.shiro.codec",
"apache.commons.codec.binary", "org.springframework.util"
], ["Base64$Encoder", "Base64", "Base64Utils"],
[
"encode", "encodeToString", "encodeBase64", "encodeBase64Chunked",
"encodeBase64String", "encodeBase64URLSafe", "encodeBase64URLSafeString"
])
|
this.asExpr() = ma.getArgument(0)
)
}
}

class Decoders extends Base64::Decoding {
Decoders() {
exists(MethodAccess ma |
ma.getMethod()
.hasQualifiedName([
"java.util", "cn.hutool.core.codec", "org.apache.shiro.codec",
"apache.commons.codec.binary", "org.springframework.util"
], ["Base64$Decoder", "Base64", "Base64Utils"], ["decode", "decodeBase64"])
|
this.asExpr() = ma.getArgument(0)
)
}
}
}
14 changes: 14 additions & 0 deletions java/github/Hardcoded.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.security.HardcodedCredentials


abstract class Hardcoded extends DataFlow::Node { }

class HCExpr extends Hardcoded {
HCExpr() {
this.asExpr() instanceof HardcodedExpr and
not this.asExpr().getEnclosingCallable() instanceof ToStringMethod
}
}

10 changes: 10 additions & 0 deletions tests/java-tests/CWE-798/base64/HardcodedBase64Usage.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
sources
| HardcodedBase64Usage.java:4:32:4:49 | "VGVzdFBhc3N3b3Jk" |
| HardcodedBase64Usage.java:5:33:6:17 | new byte[] |
| HardcodedBase64Usage.java:39:58:39:71 | "U2VjcmV0S2V5" |
sinks
| HardcodedBase64Usage.java:9:58:9:66 | MyApp.KEY |
| HardcodedBase64Usage.java:16:58:16:67 | MyApp.KEY2 |
| HardcodedBase64Usage.java:24:58:24:60 | key |
| HardcodedBase64Usage.java:32:58:32:60 | key |
| HardcodedBase64Usage.java:39:58:39:71 | "U2VjcmV0S2V5" |
45 changes: 45 additions & 0 deletions tests/java-tests/CWE-798/base64/HardcodedBase64Usage.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import java.util.Base64;

class MyApp {
public static String KEY = "VGVzdFBhc3N3b3Jk";
public static byte[] KEY2 = new byte[] { 'V', 'G', 'V', 'z', 'd', 'F', 'B', 'h', 'c', '3', 'N', '3', 'b', '3', 'J',
'k' };

public String getDecoderString() {
byte[] decodedBytes = Base64.getDecoder().decode(MyApp.KEY);

String decodedString = new String(decodedBytes);
return decodedString;
}

public String getDecoderBytes() {
byte[] decodedBytes = Base64.getDecoder().decode(MyApp.KEY2);

String decodedString = new String(decodedBytes);
return decodedString;
}

public String getDecoderConvertString() {
String key = new String(MyApp.KEY2);
byte[] decodedBytes = Base64.getDecoder().decode(key);

String decodedString = new String(decodedBytes);
return decodedString;
}

public String getDecoderConvertBytes() {
byte[] key = MyApp.KEY.getBytes();
byte[] decodedBytes = Base64.getDecoder().decode(key);

String decodedString = new String(decodedBytes);
return decodedString;
}

public String simpleDecoderString() {
byte[] decodedBytes = Base64.getDecoder().decode("U2VjcmV0S2V5");

String decodedString = new String(decodedBytes);
return decodedString;
}

}
12 changes: 12 additions & 0 deletions tests/java-tests/CWE-798/base64/HardcodedBase64Usage.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import java
import semmle.code.java.security.HardcodedCredentials
import github.Encoding
import github.Hardcoded

query predicate sources(DataFlow::Node sources) {
sources instanceof Hardcoded
}

query predicate sinks(DataFlow::Node sinks) {
sinks instanceof Base64::Decoding
}
4 changes: 4 additions & 0 deletions tests/java-tests/qlpack.lock.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
dependencies: {}
compiled: false
lockVersion: 1.0.0