@@ -49,6 +49,8 @@ public class Log4JDetector {
49
49
private static final String FILE_LOG4J_2_10 = "appender/nosql/NoSqlAppender." .toLowerCase (Locale .ROOT );
50
50
private static final String FILE_LOG4J_JNDI_LOOKUP = "core/lookup/JndiLookup." .toLowerCase (Locale .ROOT );
51
51
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
+
52
54
private static final String FILE_GONE_LOG4J_2_17 = "core/util/SetUtils." .toLowerCase (Locale .ROOT );
53
55
54
56
private static final String ACTUAL_FILE_LOG4J_2 = "core/Appender.class" ;
@@ -59,6 +61,7 @@ public class Log4JDetector {
59
61
private static final String ACTUAL_FILE_GONE_LOG4J_2_17 = "core/util/SetUtils.class" ;
60
62
private static final String ACTUAL_FILE_LOG4J_JNDI_LOOKUP = "core/lookup/JndiLookup.class" ;
61
63
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" ;
62
65
63
66
// This occurs in "JndiManager.class" in 2.15.0
64
67
private static final byte [] IS_LOG4J_SAFE_2_15_0 = Bytes .fromString ("Invalid JNDI URI - {}" );
@@ -75,6 +78,9 @@ public class Log4JDetector {
75
78
// This occurs in "JndiManager.class" in 2.3.1
76
79
private static final byte [] IS_LOG4J_SAFE_2_3_1 = Bytes .fromString ("Unsupported JNDI URI - {}" );
77
80
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
+
78
84
private static boolean verbose = false ;
79
85
private static boolean debug = false ;
80
86
private static boolean json = false ;
@@ -131,7 +137,7 @@ public static void main(String[] args) throws IOException {
131
137
132
138
if (argsList .isEmpty ()) {
133
139
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...]" );
135
141
System .out .println ();
136
142
System .out .println (" --json - Output STDOUT results in JSON. (Errors/warning still emitted to STDERR)" );
137
143
System .out .println (" --stdin - Parse STDIN for paths to explore." );
@@ -143,14 +149,14 @@ public static void main(String[] args) throws IOException {
143
149
System .out .println (" 1 = At least one legacy Log4J 1.x version found." );
144
150
System .out .println (" 2 = At least one vulnerable Log4J 2.x version found." );
145
151
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 )" );
147
153
System .out .println ("Docs - https://github.com/mergebase/log4j-detector " );
148
154
System .out .println ("(C) Copyright 2021 Mergebase Software Inc. Licensed to you via GPLv3." );
149
155
System .out .println ();
150
156
System .exit (100 );
151
157
}
152
158
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)." );
154
160
System .err .println ("-- Note: specify the '--verbose' flag to have every file examined printed to STDERR." );
155
161
if (json ) {
156
162
System .out .println ("{\" hits\" :[" );
@@ -186,11 +192,12 @@ private static int nextByte(int[] four, InputStream in) throws IOException {
186
192
four [1 ] = four [2 ];
187
193
four [2 ] = four [3 ];
188
194
four [3 ] = in .read ();
195
+ File f = new File ("blah" );
189
196
return four [3 ];
190
197
}
191
198
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 ;
194
201
}
195
202
196
203
private static final Comparator <File > FILES_ORDER_BY_NAME = new Comparator <File >() {
@@ -227,12 +234,9 @@ private static int fileType(String fileName) {
227
234
} else if ("class" .equalsIgnoreCase (suffix )) {
228
235
return 1 ;
229
236
} else if ("zip" .equalsIgnoreCase (suffix )
230
- || "jar" .equalsIgnoreCase (suffix )
231
237
|| "jpi" .equalsIgnoreCase (suffix )
232
238
|| "hpi" .equalsIgnoreCase (suffix )
233
- || "war" .equalsIgnoreCase (suffix )
234
- || "ear" .equalsIgnoreCase (suffix )
235
- || "aar" .equalsIgnoreCase (suffix )) {
239
+ || suffix .endsWith ("ar" )) {
236
240
return 0 ;
237
241
}
238
242
}
@@ -273,6 +277,7 @@ private static void findLog4jRecursive(
273
277
boolean isLog4j2_10 = false ;
274
278
boolean hasJndiLookup = false ;
275
279
boolean hasJndiManager = false ;
280
+ boolean hasJdbcJndiDisabled = false ;
276
281
boolean hasSetUtils = false ;
277
282
boolean isLog4J1_X = false ;
278
283
boolean isLog4j2_15 = false ;
@@ -316,12 +321,9 @@ private static void findLog4jRecursive(
316
321
boolean needClassBytes = false ;
317
322
final boolean isJndiLookup = pathLower .contains (FILE_LOG4J_JNDI_LOOKUP );
318
323
final boolean isJndiManager = pathLower .contains (FILE_LOG4J_JNDI_MANAGER );
324
+ final boolean isJdbcConnManager = pathLower .contains (FILE_LOG4J_JDBC_DSCS );
319
325
320
- if (isPomProperties ) {
321
- needClassBytes = true ;
322
- } else if (isJndiLookup ) {
323
- needClassBytes = true ;
324
- } else if (isJndiManager ) {
326
+ if (isPomProperties || isJndiLookup || isJndiManager || isJdbcConnManager ) {
325
327
needClassBytes = true ;
326
328
}
327
329
@@ -380,6 +382,10 @@ public void close() {
380
382
if (pathLower .endsWith (POM_PROPERTIES )) {
381
383
pomProperties = bytes ;
382
384
pomPath = "!/" + path ;
385
+ } else if (isJdbcConnManager ) {
386
+ if (containsMatch (bytes , IS_CVE_2021_44832_SAFE )) {
387
+ hasJdbcJndiDisabled = true ;
388
+ }
383
389
} else if (pathLower .contains (FILE_OLD_LOG4J )) {
384
390
isLog4J1_X = true ;
385
391
} else if (pathLower .contains (FILE_LOG4J_1 )) {
@@ -414,9 +420,9 @@ public void close() {
414
420
}
415
421
} else {
416
422
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 ;
420
426
}
421
427
}
422
428
}
@@ -499,9 +505,17 @@ public void close() {
499
505
foundHits = true ;
500
506
} else {
501
507
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
+ }
503
513
} 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
+ }
505
519
} else if (isLog4j2_16 ) {
506
520
buf .append ("== 2.16.0 _OKAY_" );
507
521
foundHits = true ;
@@ -516,7 +530,11 @@ public void close() {
516
530
} else {
517
531
if (isLog4j2_3_1 ) {
518
532
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
+ }
520
538
} else {
521
539
buf .append (">= 2.0-beta9 (< 2.10.0) _VULNERABLE_" );
522
540
}
@@ -750,6 +768,15 @@ private static void analyze(File f) {
750
768
jndiManagerBytes = Bytes .fileToBytes (jndiManager );
751
769
}
752
770
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
+
753
780
boolean hasSetUtils = exists (f .getParent () + "/../" + ACTUAL_FILE_GONE_LOG4J_2_17 );
754
781
if (exists (f .getParent () + "/../" + ACTUAL_FILE_LOG4J_2 )) {
755
782
if (exists (f .getParent () + "/../" + ACTUAL_FILE_LOG4J_3 )) {
@@ -808,9 +835,17 @@ private static void analyze(File f) {
808
835
if (isLog4J_2_10 ) {
809
836
if (isLog4J_2_17 ) {
810
837
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
+ }
812
843
} 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
+ }
814
849
}
815
850
} else if (isLog4J_2_15 ) {
816
851
foundHits = true ;
@@ -829,7 +864,11 @@ private static void analyze(File f) {
829
864
}
830
865
} else {
831
866
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
+ }
833
872
} else {
834
873
buf .append (">= 2.0-beta9 (< 2.10.0) _VULNERABLE_" );
835
874
foundHits = true ;
0 commit comments