Skip to content

Commit

Permalink
v2021.12.20 - some new options (--json, --stdin, --excludes)
Browse files Browse the repository at this point in the history
  • Loading branch information
juliusmusseau committed Dec 20, 2021
1 parent f8883b4 commit 6a885a3
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 23 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ We currently maintain a collection of [log4j-samples](https://github.com/mergeba

# Example Usage:

java -jar log4j-detector-2021.12.17.jar [path-to-scan] > hits.txt
java -jar log4j-detector-2021.12.20.jar [path-to-scan] > hits.txt

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

# More Example Usage:

```
java -jar log4j-detector-2021.12.17.jar ./samples
java -jar log4j-detector-2021.12.20.jar ./samples
-- github.com/mergebase/log4j-detector v2021.12.17 (by mergebase.com) analyzing paths (could take a while).
-- github.com/mergebase/log4j-detector v2021.12.20 (by mergebase.com) analyzing paths (could take a while).
-- Note: specify the '--verbose' flag to have every file examined printed to STDERR.
/opt/mergebase/log4j-detector/samples/clt-1.0-SNAPSHOT.jar contains Log4J-2.x >= 2.10.0 _VULNERABLE_ :-(
/opt/mergebase/log4j-detector/samples/infinispan-embedded-query-8.2.12.Final.jar contains Log4J-2.x >= 2.0-beta9 (< 2.10.0) _VULNERABLE_ :-(
Expand Down Expand Up @@ -85,15 +85,15 @@ your system (e.g., 1 GB or larger).
# Usage

```
java -jar log4j-detector-2021.12.17.jar
java -jar log4j-detector-2021.12.20.jar
Usage: java -jar log4j-detector-2021.12.17.jar [--verbose] [paths to scan...]
Usage: java -jar log4j-detector-2021.12.20.jar [--verbose] [paths to scan...]
Exit codes: 0 = No vulnerable Log4J versions found.
1 = At least one legacy Log4J 1.x version found.
2 = At least one vulnerable Log4J version found.
About - MergeBase log4j detector (version 2021.12.17)
About - MergeBase log4j detector (version 2021.12.20)
Docs - https://github.com/mergebase/log4j-detector
(C) Copyright 2021 Mergebase Software Inc. Licensed to you via GPLv3.
```
Expand All @@ -104,7 +104,7 @@ Docs - https://github.com/mergebase/log4j-detector
git clone https://github.com/mergebase/log4j-detector.git
cd log4j-detector/
mvn install
java -jar target/log4j-detector-2021.12.17.jar
java -jar target/log4j-detector-2021.12.20.jar
```
# Testing:

Expand Down
Binary file added log4j-detector-2021.12.20.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.mergebase</groupId>
<artifactId>log4j-detector</artifactId>
<version>2021.12.17</version>
<version>2021.12.20</version>
<licenses>
<license>
<name>GPL-3.0-only</name>
Expand Down
104 changes: 89 additions & 15 deletions src/main/java/com/mergebase/log4j/Log4JDetector.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

Expand Down Expand Up @@ -68,22 +72,48 @@ public class Log4JDetector {

private static boolean verbose = false;
private static boolean debug = false;
private static boolean json = false;
private static Set<String> excludes = new TreeSet<String>();
private static boolean foundHits = false;
private static boolean foundLog4j1 = false;

public static void main(String[] args) {
public static void main(String[] args) throws IOException {
List<String> argsList = new ArrayList<String>();
Collections.addAll(argsList, args);

Iterator<String> it = argsList.iterator();
List<String> stdinLines = new ArrayList<String>();
while (it.hasNext()) {
final String argOrig = it.next();
final String argOrig = it.next().trim();
if ("--debug".equals(argOrig)) {
debug = true;
it.remove();
} else if ("--verbose".equals(argOrig)) {
verbose = true;
it.remove();
} else if ("--json".equals(argOrig)) {
json = true;
it.remove();
} else if (argOrig.startsWith("--exclude=[")) {
int x = argOrig.indexOf("]");
if (x > 0) {
it.remove();
String json = argOrig.substring("--exclude=".length());
Object o = Java2Json.parse(json);
if (o instanceof List) {
List<Object> list = (List) o;
for (Object obj : list) {
if (obj != null) {
excludes.add(String.valueOf(obj));
}
}
}
}
} else if ("--stdin".equals(argOrig)) {
it.remove();
byte[] b = Bytes.streamToBytes(System.in);
String s = new String(b, Bytes.UTF_8);
stdinLines = Strings.intoLines(s);
} else {
File f = new File(argOrig);
if (!f.exists()) {
Expand All @@ -92,28 +122,41 @@ public static void main(String[] args) {
}
}
}
argsList.addAll(stdinLines);

if (argsList.isEmpty()) {
System.out.println();
System.out.println("Usage: java -jar log4j-detector-2021.12.17.jar [--verbose] [paths to scan...]");
System.out.println("Usage: java -jar log4j-detector-2021.12.20.jar [--verbose] [--json] [--stdin] [--exclude=X] [paths to scan...]");
System.out.println();
System.out.println(" --json - Output STDOUT results in JSON. (Errors/warning still emitted to STDERR)");
System.out.println(" --stdin - Parse STDIN for paths to explore.");
System.out.println(" --exclude=X - Where X is a JSON list containing full paths to exclude. Must be valid JSON.");
System.out.println();
System.out.println(" Example: --excludes=[\"/dev\", \"/media\", \"Z:\\TEMP\"]");
System.out.println();
System.out.println("Exit codes: 0 = No vulnerable Log4J versions found.");
System.out.println(" 1 = At least one legacy Log4J 1.x version found.");
System.out.println(" 2 = At least one vulnerable Log4J 2.x version found.");
System.out.println();
System.out.println("About - MergeBase log4j detector (version 2021.12.17)");
System.out.println("About - MergeBase log4j detector (version 2021.12.20)");
System.out.println("Docs - https://github.com/mergebase/log4j-detector ");
System.out.println("(C) Copyright 2021 Mergebase Software Inc. Licensed to you via GPLv3.");
System.out.println();
System.exit(100);
}

System.out.println("-- github.com/mergebase/log4j-detector v2021.12.17 (by mergebase.com) analyzing paths (could take a while).");
System.out.println("-- Note: specify the '--verbose' flag to have every file examined printed to STDERR.");
System.err.println("-- github.com/mergebase/log4j-detector v2021.12.20 (by mergebase.com) analyzing paths (could take a while).");
System.err.println("-- Note: specify the '--verbose' flag to have every file examined printed to STDERR.");
if (json) {
System.out.println("{\"hits\":[");
}
for (String arg : argsList) {
File dir = new File(arg);
analyze(dir);
}
if (json) {
System.out.println("{\"_THE_END_\":true}]}");
}
if (foundHits) {
System.exit(2);
} else if (foundLog4j1) {
Expand Down Expand Up @@ -422,10 +465,10 @@ public void close() {
StringBuilder buf = new StringBuilder();
if (isLog4j) {
if (isLog4J1_X) {
buf.append(zipPath).append(" contains Log4J-1.x AND Log4J-2.x _CRAZY_ ");
buf.append(" contains Log4J-1.x AND Log4J-2.x _CRAZY_ ");
foundLog4j1 = true;
} else {
buf.append(zipPath).append(" contains Log4J-2.x ");
buf.append(" contains Log4J-2.x ");
}
if (isVulnerable) {
if (isLog4j_2_10_0) {
Expand Down Expand Up @@ -455,11 +498,11 @@ public void close() {
if (!isSafe) {
foundHits = true;
}
System.out.println(buf);
System.out.println(prepareOutput(zipPath, buf));
} else if (isLog4J1_X) {
buf.append(zipPath).append(" contains Log4J-1.x <= 1.2.17 _OLD_");
buf.append(" contains Log4J-1.x <= 1.2.17 _OLD_");
foundLog4j1 = true;
System.out.println(buf);
System.out.println(prepareOutput(zipPath, buf));
}
}
} finally {
Expand All @@ -469,6 +512,24 @@ public void close() {
}
}

private static String prepareOutput(String zipPath, StringBuilder buf) {
if (json) {
String msg = buf.toString().trim();
int x = msg.lastIndexOf(" _");
String status = "_UNKNOWN_";
if (x >= 0) {
status = msg.substring(x).trim();
msg = msg.substring(0, x).trim();
}
Map<String, String> m = new LinkedHashMap<String, String>();
m.put(status, zipPath);
m.put("info", msg);
return Java2Json.format(m) + ",";
} else {
return zipPath + buf;
}
}

private static boolean containsMatch(byte[] bytes, byte[] needle) {
int matched = Bytes.kmp(bytes, needle);
return matched >= 0;
Expand Down Expand Up @@ -590,6 +651,19 @@ private static void analyze(File f) {
// Hopefully this stops symlink cycles.
// Using CRC-64 of path to save on memory (since we're storing *EVERY* path we come across).
String path = f.getPath();
if (excludes.contains(path)) {
System.err.println("-- Info: Skipping [" + path + "] because --excludes mentions it.");
return;
}
File parent = f.getParentFile();
while (parent != null) {
String parentPath = parent.getPath();
if (excludes.contains(parentPath)) {
System.err.println("-- Info: Skipping [" + path + "] because --excludes mentions it.");
return;
}
parent = parent.getParentFile();
}
long crc = CRC64.hash(path);
if (visited.contains(crc)) {
return;
Expand Down Expand Up @@ -626,8 +700,8 @@ private static void analyze(File f) {
if (isLog4J_1_X) {
StringBuilder buf = new StringBuilder();
String grandParent = f.getParentFile().getParent();
buf.append(grandParent).append(" contains contains Log4J-1.x <= 1.2.17 _OLD_ :-|");
System.out.println(buf);
buf.append(" contains Log4J-1.x <= 1.2.17 _OLD_ :-|");
System.out.println(prepareOutput(grandParent, buf));
} else {
maybe = currentPathLower.endsWith(FILE_LOG4J_1);
}
Expand Down Expand Up @@ -683,7 +757,7 @@ private static void analyze(File f) {
}
}
StringBuilder buf = new StringBuilder();
buf.append(f.getParentFile().getParent()).append(" contains Log4J-2.x ");
buf.append(" contains Log4J-2.x ");
if (isVulnerable) {
if (isLog4J_2_10) {
if (isLog4J_2_17) {
Expand Down Expand Up @@ -711,7 +785,7 @@ private static void analyze(File f) {
} else {
buf.append("<= 2.0-beta8 _POTENTIALLY_SAFE_ (Did you remove JndiLookup.class?)");
}
System.out.println(buf);
System.out.println(prepareOutput(f.getParentFile().getParent(), buf));
}
} else if (verbose) {
System.err.println("-- Skipping " + f.getPath() + " - Not a zip/jar/war file.");
Expand Down

0 comments on commit 6a885a3

Please sign in to comment.