Skip to content

Commit 770dd0d

Browse files
committed
add detection for 2.3.2, 2.12.4, and 2.17.1
1 parent d8225c6 commit 770dd0d

File tree

3 files changed

+75
-32
lines changed

3 files changed

+75
-32
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
Please see the tags page: https://github.com/mergebase/log4j-detector/tags
55

6+
## v2021.12.29
7+
8+
- Ability to detect log4j-core-2.3.2.jar, log4j-core-2.12.4.jar, and log4j-core-2.17.1.jar (all are \_SAFE\_).
9+
610
## v2021.12.22
711

812
- Ability to detect log4j-core-2.3.1.jar and log4j-core-2.12.3.jar (both are \_SAFE\_).

README.md

+9-9
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,16 @@ We currently maintain a collection of [log4j-samples](https://github.com/mergeba
3737

3838
# Example Usage: <a name="itemexample"></a>
3939

40-
java -jar log4j-detector-2021.12.22.jar [path-to-scan] > hits.txt
40+
java -jar log4j-detector-2021.12.29.jar [path-to-scan] > hits.txt
4141

4242
![Terminal output from running java -jar log4j-detector.jar in a terminal](./images/log4j-detector.png)
4343

4444
# More Example Usage: <a name="itemmore"></a>
4545

4646
```
47-
java -jar log4j-detector-2021.12.22.jar ./samples
47+
java -jar log4j-detector-2021.12.29.jar ./samples
4848
49-
-- github.com/mergebase/log4j-detector v2021.12.22 (by mergebase.com) analyzing paths (could take a while).
49+
-- github.com/mergebase/log4j-detector v2021.12.29 (by mergebase.com) analyzing paths (could take a while).
5050
-- Note: specify the '--verbose' flag to have every file examined printed to STDERR.
5151
/opt/mergebase/log4j-detector/samples/clt-1.0-SNAPSHOT.jar contains Log4J-2.x >= 2.10.0 _VULNERABLE_
5252
/opt/mergebase/log4j-detector/samples/infinispan-embedded-query-8.2.12.Final.jar contains Log4J-2.x >= 2.0-beta9 (< 2.10.0) _VULNERABLE_
@@ -85,9 +85,9 @@ java -jar log4j-detector-2021.12.22.jar ./samples
8585
# Usage <a name="itemusage"></a>
8686

8787
```
88-
java -jar log4j-detector-2021.12.22.jar
88+
java -jar log4j-detector-2021.12.29.jar
8989
90-
Usage: java -jar log4j-detector-2021.12.22.jar [--verbose] [--json] [--stdin] [--exclude=X] [paths to scan...]
90+
Usage: java -jar log4j-detector-2021.12.29.jar [--verbose] [--json] [--stdin] [--exclude=X] [paths to scan...]
9191
9292
--json - Output STDOUT results in JSON. (Errors/warning still emitted to STDERR)
9393
--stdin - Read STDIN for paths to explore (one path per line)
@@ -99,7 +99,7 @@ Exit codes: 0 = No vulnerable Log4J versions found.
9999
1 = At least one legacy Log4J 1.x version found.
100100
2 = At least one vulnerable Log4J version found.
101101
102-
About - MergeBase log4j detector (version 2021.12.22)
102+
About - MergeBase log4j detector (version 2021.12.29)
103103
Docs - https://github.com/mergebase/log4j-detector
104104
(C) Copyright 2021 Mergebase Software Inc. Licensed to you via GPLv3.
105105
```
@@ -110,7 +110,7 @@ Docs - https://github.com/mergebase/log4j-detector
110110
git clone https://github.com/mergebase/log4j-detector.git
111111
cd log4j-detector/
112112
mvn install
113-
java -jar target/log4j-detector-2021.12.22.jar
113+
java -jar target/log4j-detector-2021.12.29.jar
114114
```
115115
# Testing: <a name="itemtesting"></a>
116116

@@ -173,8 +173,8 @@ to build it, and since this tool has zero dependencies, it shouldn't take too lo
173173
satisfaction. If you don't trust Maven you can go directly into the "src/main/java/com/mergebase/log4j" directory and
174174
type "javac \*.java". That works, too!
175175

176-
We also sign the pre-compiled jars we keep in the root of the repository (e.g., ./log4j-detector-2021.12.22.jar) with the
177-
MergeBase code signing key. Please run "jarsigner -verbose -verify log4j-detector-2021.12.22.jar" to confirm this.
176+
We also sign the pre-compiled jar we keep in the root of the repository (./log4j-detector-2021.12.29.jar) with the
177+
MergeBase code signing key. Please run "jarsigner -verbose -verify log4j-detector-2021.12.29.jar" to confirm this.
178178

179179
# What Is MergeBase All About? <a name="itemmergebase"></a>
180180

src/main/java/com/mergebase/log4j/Log4JDetector.java

+62-23
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class Log4JDetector {
4949
private static final String FILE_LOG4J_2_10 = "appender/nosql/NoSqlAppender.".toLowerCase(Locale.ROOT);
5050
private static final String FILE_LOG4J_JNDI_LOOKUP = "core/lookup/JndiLookup.".toLowerCase(Locale.ROOT);
5151
private static final String FILE_LOG4J_JNDI_MANAGER = "core/net/JndiManager.".toLowerCase(Locale.ROOT);
52+
private static final String FILE_LOG4J_JDBC_DSCS = "core/appender/db/jdbc/DataSourceConnectionSource.".toLowerCase(Locale.ROOT);
53+
5254
private static final String FILE_GONE_LOG4J_2_17 = "core/util/SetUtils.".toLowerCase(Locale.ROOT);
5355

5456
private static final String ACTUAL_FILE_LOG4J_2 = "core/Appender.class";
@@ -59,6 +61,7 @@ public class Log4JDetector {
5961
private static final String ACTUAL_FILE_GONE_LOG4J_2_17 = "core/util/SetUtils.class";
6062
private static final String ACTUAL_FILE_LOG4J_JNDI_LOOKUP = "core/lookup/JndiLookup.class";
6163
private static final String ACTUAL_FILE_LOG4J_JNDI_MANAGER = "core/net/JndiManager.class";
64+
private static final String ACTUAL_FILE_LOG4J_JDBC_DSCS = "core/appender/db/jdbc/DataSourceConnectionSource.class";
6265

6366
// This occurs in "JndiManager.class" in 2.15.0
6467
private static final byte[] IS_LOG4J_SAFE_2_15_0 = Bytes.fromString("Invalid JNDI URI - {}");
@@ -75,6 +78,9 @@ public class Log4JDetector {
7578
// This occurs in "JndiManager.class" in 2.3.1
7679
private static final byte[] IS_LOG4J_SAFE_2_3_1 = Bytes.fromString("Unsupported JNDI URI - {}");
7780

81+
// This occurs in "DataSourceConnectionSource.class" in 2.17.1 and friends.
82+
private static final byte[] IS_CVE_2021_44832_SAFE = Bytes.fromString("JNDI must be enabled by setting log4j2.enableJndiJdbc=true");
83+
7884
private static boolean verbose = false;
7985
private static boolean debug = false;
8086
private static boolean json = false;
@@ -131,7 +137,7 @@ public static void main(String[] args) throws IOException {
131137

132138
if (argsList.isEmpty()) {
133139
System.out.println();
134-
System.out.println("Usage: java -jar log4j-detector-2021.12.22.jar [--verbose] [--json] [--stdin] [--exclude=X] [paths to scan...]");
140+
System.out.println("Usage: java -jar log4j-detector-2021.12.29.jar [--verbose] [--json] [--stdin] [--exclude=X] [paths to scan...]");
135141
System.out.println();
136142
System.out.println(" --json - Output STDOUT results in JSON. (Errors/warning still emitted to STDERR)");
137143
System.out.println(" --stdin - Parse STDIN for paths to explore.");
@@ -143,14 +149,14 @@ public static void main(String[] args) throws IOException {
143149
System.out.println(" 1 = At least one legacy Log4J 1.x version found.");
144150
System.out.println(" 2 = At least one vulnerable Log4J 2.x version found.");
145151
System.out.println();
146-
System.out.println("About - MergeBase log4j detector (version 2021.12.22)");
152+
System.out.println("About - MergeBase log4j detector (version 2021.12.29)");
147153
System.out.println("Docs - https://github.com/mergebase/log4j-detector ");
148154
System.out.println("(C) Copyright 2021 Mergebase Software Inc. Licensed to you via GPLv3.");
149155
System.out.println();
150156
System.exit(100);
151157
}
152158

153-
System.err.println("-- github.com/mergebase/log4j-detector v2021.12.22 (by mergebase.com) analyzing paths (could take a while).");
159+
System.err.println("-- github.com/mergebase/log4j-detector v2021.12.29 (by mergebase.com) analyzing paths (could take a while).");
154160
System.err.println("-- Note: specify the '--verbose' flag to have every file examined printed to STDERR.");
155161
if (json) {
156162
System.out.println("{\"hits\":[");
@@ -186,11 +192,12 @@ private static int nextByte(int[] four, InputStream in) throws IOException {
186192
four[1] = four[2];
187193
four[2] = four[3];
188194
four[3] = in.read();
195+
File f = new File("blah");
189196
return four[3];
190197
}
191198

192-
private static boolean isZipSentinel(int[] four) {
193-
return four[0] == 0x50 && four[1] == 0x4B && four[2] == 3 && four[3] == 4;
199+
private static boolean isZipSentinel(int[] chunk) {
200+
return chunk[0] == 0x50 && chunk[1] == 0x4B && chunk[2] == 3 && chunk[3] == 4;
194201
}
195202

196203
private static final Comparator<File> FILES_ORDER_BY_NAME = new Comparator<File>() {
@@ -227,12 +234,9 @@ private static int fileType(String fileName) {
227234
} else if ("class".equalsIgnoreCase(suffix)) {
228235
return 1;
229236
} else if ("zip".equalsIgnoreCase(suffix)
230-
|| "jar".equalsIgnoreCase(suffix)
231237
|| "jpi".equalsIgnoreCase(suffix)
232238
|| "hpi".equalsIgnoreCase(suffix)
233-
|| "war".equalsIgnoreCase(suffix)
234-
|| "ear".equalsIgnoreCase(suffix)
235-
|| "aar".equalsIgnoreCase(suffix)) {
239+
|| suffix.endsWith("ar")) {
236240
return 0;
237241
}
238242
}
@@ -273,6 +277,7 @@ private static void findLog4jRecursive(
273277
boolean isLog4j2_10 = false;
274278
boolean hasJndiLookup = false;
275279
boolean hasJndiManager = false;
280+
boolean hasJdbcJndiDisabled = false;
276281
boolean hasSetUtils = false;
277282
boolean isLog4J1_X = false;
278283
boolean isLog4j2_15 = false;
@@ -316,12 +321,9 @@ private static void findLog4jRecursive(
316321
boolean needClassBytes = false;
317322
final boolean isJndiLookup = pathLower.contains(FILE_LOG4J_JNDI_LOOKUP);
318323
final boolean isJndiManager = pathLower.contains(FILE_LOG4J_JNDI_MANAGER);
324+
final boolean isJdbcConnManager = pathLower.contains(FILE_LOG4J_JDBC_DSCS);
319325

320-
if (isPomProperties) {
321-
needClassBytes = true;
322-
} else if (isJndiLookup) {
323-
needClassBytes = true;
324-
} else if (isJndiManager) {
326+
if (isPomProperties || isJndiLookup || isJndiManager || isJdbcConnManager) {
325327
needClassBytes = true;
326328
}
327329

@@ -380,6 +382,10 @@ public void close() {
380382
if (pathLower.endsWith(POM_PROPERTIES)) {
381383
pomProperties = bytes;
382384
pomPath = "!/" + path;
385+
} else if (isJdbcConnManager) {
386+
if (containsMatch(bytes, IS_CVE_2021_44832_SAFE)) {
387+
hasJdbcJndiDisabled = true;
388+
}
383389
} else if (pathLower.contains(FILE_OLD_LOG4J)) {
384390
isLog4J1_X = true;
385391
} else if (pathLower.contains(FILE_LOG4J_1)) {
@@ -414,9 +420,9 @@ public void close() {
414420
}
415421
} else {
416422
isLog4j2_15_override = true;
417-
if (containsMatch(bytes, IS_LOG4J_SAFE_2_3_1)) {
418-
isLog4j2_3_1 = true;
419-
}
423+
}
424+
if (containsMatch(bytes, IS_LOG4J_SAFE_2_3_1)) {
425+
isLog4j2_3_1 = true;
420426
}
421427
}
422428
}
@@ -499,9 +505,17 @@ public void close() {
499505
foundHits = true;
500506
} else {
501507
if (isLog4j2_12_3) {
502-
buf.append("== 2.12.3 _SAFE_");
508+
if (hasJdbcJndiDisabled) {
509+
buf.append("== 2.12.4 _SAFE_");
510+
} else {
511+
buf.append("== 2.12.3 _OKAY_");
512+
}
503513
} else if (isLog4j2_17) {
504-
buf.append(">= 2.17.0 _SAFE_");
514+
if (hasJdbcJndiDisabled) {
515+
buf.append(">= 2.17.1 _SAFE_");
516+
} else {
517+
buf.append("== 2.17.0 _OKAY_");
518+
}
505519
} else if (isLog4j2_16) {
506520
buf.append("== 2.16.0 _OKAY_");
507521
foundHits = true;
@@ -516,7 +530,11 @@ public void close() {
516530
} else {
517531
if (isLog4j2_3_1) {
518532
isSafe = true;
519-
buf.append("== 2.3.1 _SAFE_");
533+
if (hasJdbcJndiDisabled) {
534+
buf.append("== 2.3.2 _SAFE_");
535+
} else {
536+
buf.append("== 2.3.1 _OKAY_");
537+
}
520538
} else {
521539
buf.append(">= 2.0-beta9 (< 2.10.0) _VULNERABLE_");
522540
}
@@ -750,6 +768,15 @@ private static void analyze(File f) {
750768
jndiManagerBytes = Bytes.fileToBytes(jndiManager);
751769
}
752770

771+
boolean hasJdbcJndiDisabled = false;
772+
File jdbcConn = new File(f.getParent() + "/../" + ACTUAL_FILE_LOG4J_JDBC_DSCS);
773+
if (jdbcConn.canRead()) {
774+
byte[] jdbcConnBytes = Bytes.fileToBytes(jdbcConn);
775+
if (containsMatch(jdbcConnBytes, IS_CVE_2021_44832_SAFE)) {
776+
hasJdbcJndiDisabled = true;
777+
}
778+
}
779+
753780
boolean hasSetUtils = exists(f.getParent() + "/../" + ACTUAL_FILE_GONE_LOG4J_2_17);
754781
if (exists(f.getParent() + "/../" + ACTUAL_FILE_LOG4J_2)) {
755782
if (exists(f.getParent() + "/../" + ACTUAL_FILE_LOG4J_3)) {
@@ -808,9 +835,17 @@ private static void analyze(File f) {
808835
if (isLog4J_2_10) {
809836
if (isLog4J_2_17) {
810837
if (hasSetUtils) {
811-
buf.append(">= 2.12.3 _SAFE_");
838+
if (hasJdbcJndiDisabled) {
839+
buf.append("== 2.12.4 _SAFE_");
840+
} else {
841+
buf.append("== 2.12.3 _OKAY_");
842+
}
812843
} else {
813-
buf.append(">= 2.17.0 _SAFE_");
844+
if (hasJdbcJndiDisabled) {
845+
buf.append(">= 2.17.1 _SAFE_");
846+
} else {
847+
buf.append("== 2.17.0 _OKAY_");
848+
}
814849
}
815850
} else if (isLog4J_2_15) {
816851
foundHits = true;
@@ -829,7 +864,11 @@ private static void analyze(File f) {
829864
}
830865
} else {
831866
if (isLog4J_2_3_1) {
832-
buf.append("== 2.3.1 _SAFE_");
867+
if (hasJdbcJndiDisabled) {
868+
buf.append("== 2.3.2 _SAFE_");
869+
} else {
870+
buf.append("== 2.3.1 _OKAY_");
871+
}
833872
} else {
834873
buf.append(">= 2.0-beta9 (< 2.10.0) _VULNERABLE_");
835874
foundHits = true;

0 commit comments

Comments
 (0)