Refactor into separate libraries

This commit is contained in:
Tony Torralba
2021-10-29 17:36:02 +02:00
parent 7f15177498
commit 3ea1af3819
6 changed files with 299 additions and 61 deletions

View File

@@ -92,6 +92,7 @@ private module Frameworks {
private import semmle.code.java.frameworks.JaxWS
private import semmle.code.java.frameworks.JoddJson
private import semmle.code.java.frameworks.JsonJava
private import semmle.code.java.frameworks.Logging
private import semmle.code.java.frameworks.Objects
private import semmle.code.java.frameworks.Optional
private import semmle.code.java.frameworks.Stream

View File

@@ -0,0 +1,237 @@
/** Provides classes and predicates to reason about logging. */
import java
import semmle.code.java.dataflow.ExternalFlow
private class LoggingSummaryModels extends SummaryModelCsv {
override predicate row(string row) {
row =
[
"org.apache.logging.log4j;Logger;true;entry;(Object[]);;Argument[0];ReturnValue;taint",
"org.apache.logging.log4j;Logger;true;traceEntry;(Message);;Argument[0];ReturnValue;taint",
"org.apache.logging.log4j;Logger;true;traceEntry;(String,Object[]);;Argument[0..1];ReturnValue;taint",
"org.apache.logging.log4j;Logger;true;traceEntry;(String,Supplier);;Argument[0..1];ReturnValue;taint",
"org.apache.logging.log4j;Logger;true;traceEntry;(Supplier);;Argument[0];ReturnValue;taint",
"org.apache.logging.log4j;Logger;true;traceExit;(EntryMessage,Object);;Argument[1];ReturnValue;value",
"org.apache.logging.log4j;Logger;true;traceExit;(Message,Object);;Argument[1];ReturnValue;value",
"org.apache.logging.log4j;Logger;true;traceExit;(Object);;Argument[0];ReturnValue;value",
"org.apache.logging.log4j;Logger;true;traceExit;(String,Object);;Argument[1];ReturnValue;value",
"org.slf4j.spi.LoggingEventBuilder;true;addArgument;;;Argument[1];Argument[-1];taint",
"org.slf4j.spi.LoggingEventBuilder;true;addArgument;;;Argument[-1];ReturnValue;value",
"org.slf4j.spi.LoggingEventBuilder;true;addKeyValue;;;Argument[1];Argument[-1];taint",
"org.slf4j.spi.LoggingEventBuilder;true;addKeyValue;;;Argument[-1];ReturnValue;value",
"org.slf4j.spi.LoggingEventBuilder;true;addMarker;;;Argument[-1];ReturnValue;value",
"org.slf4j.spi.LoggingEventBuilder;true;setCause;;;Argument[-1];ReturnValue;value",
"java.util.logging;LogRecord;false;LogRecord;;;Argument[1];Argument[-1];taint"
]
}
}
private string jBossLogger() { result = "org.jboss.logging;" + ["BasicLogger", "Logger"] }
private class LoggingSinkModels extends SinkModelCsv {
override predicate row(string row) {
row =
[
// org.apache.log4j.Category
"org.apache.log4j;Category;true;assertLog;;;Argument[1];logging",
"org.apache.log4j;Category;true;debug;;;Argument[0];logging",
"org.apache.log4j;Category;true;error;;;Argument[0];logging",
"org.apache.log4j;Category;true;fatal;;;Argument[0];logging",
"org.apache.log4j;Category;true;forcedLog;;;Argument[2];logging",
"org.apache.log4j;Category;true;info;;;Argument[0];logging",
"org.apache.log4j;Category;true;l7dlog;(Priority,String,Object[],Throwable);;Argument[2];logging",
"org.apache.log4j;Category;true;log;(Priority,Object);;Argument[1];logging",
"org.apache.log4j;Category;true;log;(String,Priority,Object,Throwable);;Argument[2];logging",
"org.apache.log4j;Category;true;warn;;;Argument[0];logging",
// org.apache.logging.log4j.Logger
"org.apache.logging.log4j;Logger;true;" +
[["debug", "error", "fatal", "info", "trace", "warn"] + ";(", "log;(Level,"] +
[
"CharSequence);;Argument[0];logging", "CharSequence,Throwable);;Argument[0];logging",
"Marker,CharSequence);;Argument[1];logging",
"Marker,CharSequence,Throwable);;Argument[1];logging",
"Marker,Message);;Argument[1];logging", "Marker,MessageSupplier);;Argument[1];logging",
"Marker,MessageSupplier,Throwable);;Argument[1];logging",
"Marker,Object);;Argument[1];logging", "Marker,Object,Throwable);;Argument[1];logging",
"Marker,String);;Argument[1];logging",
"Marker,String,Object[]);;Argument[1..2];logging",
"Marker,String,Object);;Argument[1..2];logging",
"Marker,String,Object,Object);;Argument[1..3];logging",
"Marker,String,Object,Object,Object);;Argument[1..4];logging",
"Marker,String,Object,Object,Object,Object);;Argument[1..5];logging",
"Marker,String,Object,Object,Object,Object,Object);;Argument[1..6];logging",
"Marker,String,Object,Object,Object,Object,Object,Object);;Argument[1..7];logging",
"Marker,String,Object,Object,Object,Object,Object,Object,Object);;Argument[1..8];logging",
"Marker,String,Object,Object,Object,Object,Object,Object,Object,Object);;Argument[1..9];logging",
"Marker,String,Object,Object,Object,Object,Object,Object,Object,Object,Object);;Argument[1..10];logging",
"Marker,String,Object,Object,Object,Object,Object,Object,Object,Object,Object,Object);;Argument[1..11];logging",
"Marker,String,Supplier);;Argument[1..2];logging",
"Marker,String,Throwable);;Argument[1];logging",
"Marker,Supplier);;Argument[1];logging",
"Marker,Supplier,Throwable);;Argument[1];logging", ";(Message);;Argument[0];logging",
"MessageSupplier);;Argument[0];logging",
"MessageSupplier,Throwable);;Argument[0];logging",
"Message,Throwable);;Argument[0];logging", ";(Object);;Argument[0];logging",
"Object,Throwable);;Argument[0];logging", ";(String);;Argument[0];logging",
"String,Object[]);;Argument[0..1];logging", "String,Object);;Argument[0..1];logging",
"String,Object,Object);;Argument[0..2];logging",
"String,Object,Object,Object);;Argument[0..3];logging",
"String,Object,Object,Object,Object);;Argument[0..4];logging",
"String,Object,Object,Object,Object,Object);;Argument[0..5];logging",
"String,Object,Object,Object,Object,Object,Object);;Argument[0..6];logging",
"String,Object,Object,Object,Object,Object,Object,Object);;Argument[0..7];logging",
"String,Object,Object,Object,Object,Object,Object,Object,Object);;Argument[0..9];logging",
"String,Object,Object,Object,Object,Object,Object,Object,Object,Object);;Argument[0..10];logging",
"String,Supplier);;Argument[0..1];logging", "String,Throwable);;Argument[0];logging",
"Supplier);;Argument[0];logging", "Supplier,Throwable);;Argument[0];logging"
], "org.apache.logging.log4j;Logger;true;entry;(Object[]);;Argument[0];logging",
"org.apache.logging.log4j;Logger;true;logMessage;(Level,Marker,String,StackTraceElement,Message,Throwable);;Argument[4];logging",
"org.apache.logging.log4j;Logger;true;printf;(Level,Marker,String,Object[]);;Argument[2..3];logging",
"org.apache.logging.log4j;Logger;true;printf;(Level,String,Object[]);;Argument[1..2];logging",
"org.apache.logging.log4j;Logger;true;traceEntry;(Message);;Argument[0];logging",
"org.apache.logging.log4j;Logger;true;traceEntry;(String,Object[]);;Argument[0..1];logging",
"org.apache.logging.log4j;Logger;true;traceEntry;(String,Supplier);;Argument[0..1];logging",
"org.apache.logging.log4j;Logger;true;traceEntry;(Supplier);;Argument[0];logging",
"org.apache.logging.log4j;Logger;true;traceExit;(EntryMessage);;Argument[0];logging",
"org.apache.logging.log4j;Logger;true;traceExit;(EntryMessage,Object);;Argument[0..1];logging",
"org.apache.logging.log4j;Logger;true;traceExit;(Message,Object);;Argument[0..1];logging",
"org.apache.logging.log4j;Logger;true;traceExit;(Object);;Argument[0];logging",
"org.apache.logging.log4j;Logger;true;traceExit;(String,Object);;Argument[0..1];logging",
// org.apache.logging.log4j.LogBuilder
"org.apache.logging.log4j;LogBuilder;true;log;(CharSequence);;Argument[0];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(Message);;Argument[0];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(Object);;Argument[0];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String);;Argument[0];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object[]);;Argument[0..1];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object);;Argument[0..1];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object,Object);;Argument[0..2];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object,Object,Object);;Argument[0..3];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object,Object,Object,Object);;Argument[0..4];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object,Object,Object,Object,Object);;Argument[0..5];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object,Object,Object,Object,Object,Object);;Argument[0..6];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object,Object,Object,Object,Object,Object,Object);;Argument[0..7];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object,Object,Object,Object,Object,Object,Object,Object);;Argument[0..8];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object,Object,Object,Object,Object,Object,Object,Object,Object);;Argument[0..9];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Object,Object,Object,Object,Object,Object,Object,Object,Object,Object);;Argument[0..10];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(String,Supplier);;Argument[0..1];logging",
"org.apache.logging.log4j;LogBuilder;true;log;(Supplier);;Argument[0];logging",
// org.apache.commons.logging.Log
"org.apache.commons.logging;Log;true;" +
["debug", "error", "fatal", "info", "trace", "warn"] + ";;;Argument[0];logging",
// org.jboss.logging.BasicLogger and org.jboss.logging.Logger
// (org.jboss.logging.Logger does not implement BasicLogger in some implementations like JBoss Application Server 4.0.4)
jBossLogger() + ";true;" +
[["debug", "error", "fatal", "info", "trace", "warn"] + ";(", "log;(Level,"] +
[
"Object);;Argument[0];logging", ";(Object,Object[]);;Argument[0..1];logging",
"Object,Object[],Throwable);;Argument[0..1];logging",
"Object,Throwable);;Argument[0];logging",
"String,Object,Object[],Throwable);;Argument[1..2];logging",
"String,Object,Throwable);;Argument[1];logging"
],
jBossLogger() + ";true;log;(String,Level,Object,Object[],Throwable);;Argument[2..3];logging",
jBossLogger() + ";true;" +
[
["debug", "error", "fatal", "info", "trace", "warn"] + ["f", "v"] + ";(",
"log" + ["f", "v"] + ";(Level,"
] +
[
"String,Object[]);;Argument[0..1];logging", "String,Object);;Argument[0..1];logging",
"String,Object,Object);;Argument[0..2];logging",
"String,Object,Object,Object);;Argument[0..3];logging",
"String,Object,Object,Object,Object);;Argument[0..4];logging",
"Throwable,String,Object);;Argument[1..2];logging",
"Throwable,String,Object,Object);;Argument[1..3];logging",
"Throwable,String,Object,Object,Object);;Argument[0..4];logging",
],
jBossLogger() + ";true;log" + ["f", "v"] +
[
";(String,Level,Throwable,String,Object[]);;Argument[3..4];logging",
";(String,Level,Throwable,String,Object);;Argument[3..4];logging",
";(String,Level,Throwable,String,Object,Object);;Argument[3..5];logging",
";(String,Level,Throwable,String,Object,Object,Object);;Argument[3..6];logging"
],
// org.slf4j.spi.LoggingEventBuilder
"org.slf4j.spi;LoggingEventBuilder;true;log;;;Argument[0];logging",
"org.slf4j.spi;LoggingEventBuilder;true;log;(String,Object);;Argument[1];logging",
"org.slf4j.spi;LoggingEventBuilder;true;log;(String,Object[]);;Argument[1];logging",
"org.slf4j.spi;LoggingEventBuilder;true;log;(String,Object,Object);;Argument[1..2];logging",
"org.slf4j;Logger;true;" + ["debug", "error", "info", "trace", "warn"] +
[
";(String);;Argument[0];logging", ";(String,Object);;Argument[0..1];logging",
";(String,Object[]);;Argument[0..1];logging",
";(String,Object,Object);;Argument[0..2];logging",
";(String,Throwable);;Argument[0];logging", ";(Marker,String);;Argument[1];logging",
";(Marker,String,Object);;Argument[1..2];logging",
";(Marker,String,Object[]);;Argument[1..2];logging",
";(Marker,String,Object[],Object);;Argument[1..3];logging",
";(Marker,String,Object[],Object,Object);;Argument[1..4];logging"
],
// org.slf4j.Logger
"org.scijava.log;Logger;true;alwaysLog;(int,Object,Throwable);;Argument[1];logging",
"org.scijava.log;Logger;true;" +
[["debug", "error", "info", "trace", "warn"] + ";(", "log;(int,"] +
["Object);;Argument[0];logging", "Object,Throwable);;Argument[0];logging"],
// com.google.common.flogger.LoggingApi
"com.google.common.flogger;LoggingApi;true;log;" +
[
";;;Argument[0];logging", "(String,Object);;Argument[1]",
"(String,Object,Object);;Argument[1..2]",
"(String,Object,Object,Object);;Argument[1..3]", "(String,Object,boolean);;Argument[1]",
"(String,Object,char);;Argument[1]", "(String,Object,byte);;Argument[1]",
"(String,Object,short);;Argument[1]", "(String,Object,int);;Argument[1]",
"(String,Object,long);;Argument[1]", "(String,Object,float);;Argument[1]",
"(String,Object,double);;Argument[1]", "(String,boolean,Object);;Argument[2]",
"(String,char,Object);;Argument[2]", "(String,byte,Object);;Argument[2]",
"(String,short,Object);;Argument[2]", "(String,int,Object);;Argument[2]",
"(String,long,Object);;Argument[2]", "(String,float,Object);;Argument[2]",
"(String,double,Object);;Argument[2]"
] + ";logging",
// java.lang.System$Logger
"java.lang;System$Logger;true;log;" +
[
"(Level,Object);;Argument[1]", "(Level,String);;Argument[1]",
"(Level,String,Object[]);;Argument[1..2]", "(Level,String,Throwable);;Argument[1]",
"(Level,String,Supplier);;Argument[1..2]",
"(Level,String,Supplier,Throwable);;Argument[1..2]",
"(Level,ResourceBundle,String,Object[]);;Argument[2..3]",
"(Level,ResourceBundle,String,Throwable);;Argument[2]"
] + ";logging",
// java.util.logging.Logger
"java.util.logging;Logger;true;" +
["config", "fine", "finer", "finest", "info", "severe", "warning"] +
";;;Argument[0];logging",
"java.util.logging;Logger;true;entering;(String,String);;Argument[0..1];logging",
"java.util.logging;Logger;true;entering;(String,String,Object);;Argument[0..2];logging",
"java.util.logging;Logger;true;entering;(String,String,Object[]);;Argument[0..2];logging",
"java.util.logging;Logger;true;exiting;(String,String);;Argument[0..1];logging",
"java.util.logging;Logger;true;exiting;(String,String,Object);;Argument[0..2];logging",
"java.util.logging;Logger;true;log;(Level,String);;Argument[1];logging",
"java.util.logging;Logger;true;log;(Level,String,Object);;Argument[1..2];logging",
"java.util.logging;Logger;true;log;(Level,String,Object[]);;Argument[1..2];logging",
"java.util.logging;Logger;true;log;(Level,String,Throwable);;Argument[1];logging",
"java.util.logging;Logger;true;log;(Level,Supplier);;Argument[1];logging",
"java.util.logging;Logger;true;log;(Level,Throwable,Supplier);;Argument[2];logging",
"java.util.logging;Logger;true;log;(LogRecord);;Argument[1];logging",
"java.util.logging;Logger;true;logp;(Level,String,String,String);;Argument[1..3];logging",
"java.util.logging;Logger;true;logp;(Level,String,String,String,Object);;Argument[1..4];logging",
"java.util.logging;Logger;true;logp;(Level,String,String,String,Object[]);;Argument[1..4];logging",
"java.util.logging;Logger;true;logp;(Level,String,String,String,Object[]);;Argument[1..4];logging",
"java.util.logging;Logger;true;logp;(Level,String,String,String,Throwable);;Argument[1..3];logging",
"java.util.logging;Logger;true;logp;(Level,String,String,Supplier);;Argument[1..3];logging",
"java.util.logging;Logger;true;logp;(Level,String,String,Throwable,Supplier);;Argument[1..2];logging",
"java.util.logging;Logger;true;logp;(Level,String,String,Throwable,Supplier);;Argument[4];logging",
"java.util.logging;Logger;true;logrb;(Level,String,String,ResourceBundle,String,Object[]);;Argument[1..2];logging",
"java.util.logging;Logger;true;logrb;(Level,String,String,ResourceBundle,String,Object[]);;Argument[4..5];logging",
"java.util.logging;Logger;true;logrb;(Level,String,String,ResourceBundle,String,Throwable);;Argument[1..2];logging",
"java.util.logging;Logger;true;logrb;(Level,String,String,ResourceBundle,String,Throwable);;Argument[3];logging",
"java.util.logging;Logger;true;logrb;(Level,String,String,String,String);;Argument[1..4];logging",
"java.util.logging;Logger;true;logrb;(Level,String,String,String,String,Object);;Argument[1..5];logging",
"java.util.logging;Logger;true;logrb;(Level,String,String,String,String,Object[]);;Argument[1..5];logging",
"java.util.logging;Logger;true;logrb;(Level,String,String,String,String,Throwable);;Argument[1..4];logging",
// android.util.Log
"android.util;Log;true;" + ["d", "v", "i", "w", "e", "wtf"] + ";;;Argument[1];logging"
]
}
}

View File

@@ -0,0 +1,36 @@
/** Provides classes and predicates related to Log Injection vulnerabilities. */
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.ExternalFlow
/** A data flow sink for unvalidated user input that is used to log messages. */
abstract class LogInjectionSink extends DataFlow::Node { }
/**
* A node that sanitizes a message before logging to avoid log injection.
*/
abstract class LogInjectionSanitizer extends DataFlow::Node { }
/**
* A unit class for adding additional taint steps.
*
* Extend this class to add additional taint steps that should apply to the `LogInjectionConfiguration`.
*/
class LogInjectionAdditionalTaintStep extends Unit {
/**
* Holds if the step from `node1` to `node2` should be considered a taint
* step for the `LogInjectionConfiguration` configuration.
*/
abstract predicate step(DataFlow::Node node1, DataFlow::Node node2);
}
private class DefaultLogInjectionSink extends LogInjectionSink {
DefaultLogInjectionSink() { sinkNode(this, "logging") }
}
private class DefaultLogInjectionSanitizer extends LogInjectionSanitizer {
DefaultLogInjectionSanitizer() {
this.getType() instanceof BoxedType or this.getType() instanceof PrimitiveType
}
}

View File

@@ -0,0 +1,22 @@
/** Provides taint tracking configurations to be used in queries related to the Log Injection vulnerability. */
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.LogInjection
/**
* A taint-tracking configuration for tracking untrusted user input used in log entries.
*/
class LogInjectionConfiguration extends TaintTracking::Configuration {
LogInjectionConfiguration() { this = "Log Injection" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof LogInjectionSink }
override predicate isSanitizer(DataFlow::Node node) { node instanceof LogInjectionSanitizer }
override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
any(LogInjectionAdditionalTaintStep c).step(node1, node2)
}
}

View File

@@ -11,28 +11,10 @@
*/
import java
import semmle.code.java.security.LogInjectionQuery
import DataFlow::PathGraph
import experimental.semmle.code.java.Logging
import semmle.code.java.dataflow.FlowSources
/**
* A taint-tracking configuration for tracking untrusted user input used in log entries.
*/
private class LogInjectionConfiguration extends TaintTracking::Configuration {
LogInjectionConfiguration() { this = "Log Injection" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
sink.asExpr() = any(LoggingCall c).getALogArgument()
}
override predicate isSanitizer(DataFlow::Node node) {
node.getType() instanceof BoxedType or node.getType() instanceof PrimitiveType
}
}
from LogInjectionConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "$@ flows to log entry.", source.getNode(),
"User-provided value"
select sink.getNode(), source, sink, "This $@ flows to a log entry.", source.getNode(),
"user-provided value"

View File

@@ -1,40 +0,0 @@
/**
* Provides classes and predicates for working with loggers.
*/
import java
/** Models a call to a logging method. */
class LoggingCall extends MethodAccess {
LoggingCall() {
exists(RefType t, Method m |
t.hasQualifiedName("org.apache.log4j", "Category") or // Log4j 1
t.hasQualifiedName("org.apache.logging.log4j", ["Logger", "LogBuilder"]) or // Log4j 2
t.hasQualifiedName("org.apache.commons.logging", "Log") or
// JBoss Logging (`org.jboss.logging.Logger` in some implementations like JBoss Application Server 4.0.4 did not implement `BasicLogger`)
t.hasQualifiedName("org.jboss.logging", ["BasicLogger", "Logger"]) or
t.hasQualifiedName("org.slf4j.spi", "LoggingEventBuilder") or
t.hasQualifiedName("org.slf4j", "Logger") or
t.hasQualifiedName("org.scijava.log", "Logger") or
t.hasQualifiedName("com.google.common.flogger", "LoggingApi") or
t.hasQualifiedName("java.lang", "System$Logger") or
t.hasQualifiedName("java.util.logging", "Logger")
|
(
m.getDeclaringType().getASourceSupertype*() = t or
m.getDeclaringType().extendsOrImplements*(t)
) and
m.getReturnType() instanceof VoidType and
this = m.getAReference()
)
or
exists(RefType t, Method m | t.hasQualifiedName("android.util", "Log") |
m.hasName(["d", "e", "i", "v", "w", "wtf"]) and
m.getDeclaringType() = t and
this = m.getAReference()
)
}
/** Returns an argument which would be logged by this call. */
Argument getALogArgument() { result = this.getArgument(_) }
}