Skip to content

Java: Potentially duplicated results and paths from a custom data flow query #7449

@KiruaLawliet

Description

@KiruaLawliet

project:

log4j 2.14.0 -> https://github.com/apache/logging-log4j2/tree/rel/2.14.0

environment:

vscode version:1.63.2
vscode plugin:CodeQL v1.5.9
CodeQL command-line toolchain release 2.7.0
os platform:windows10 20H2

ql script:

/** @kind path-problem */
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking

import DataFlow::PathGraph

module TaintPropagation{

    // strategy.log(this, getName(), fqcn, marker, level, tainted, t);
    class ReliabilityStrategySubClass extends Parameter
    {
        ReliabilityStrategySubClass()
        {
            (
            this.getCallable().getDeclaringType().getASourceSupertype*().hasQualifiedName("org.apache.logging.log4j.core.config", "LocationAwareReliabilityStrategy") 
            ) 
            and this.getCallable().hasName("log")
            and this.hasName("data")
        }
    }

    predicate strategylog(DataFlow::Node node1, DataFlow::Node node2) {
        exists(MethodAccess ma |
            ma.getMethod().hasName("log")
            and (
                ma.getCallee().getDeclaringType().hasQualifiedName("org.apache.logging.log4j.core.config", "LocationAwareReliabilityStrategy")
            )
            and node2.asParameter() instanceof ReliabilityStrategySubClass
            and ma.getMethod().getSignature() = node2.asParameter().getCallable().getSignature()
            and ma.getArgument(node2.asParameter().getPosition()) = node1.asExpr()
            )
    }

    // loggerConfig.log(loggerName, fqcn, marker, level, data, t);
    class LoggerConfigSubClass extends Parameter
    {
        LoggerConfigSubClass()
        {
            this.getCallable().getDeclaringType().getASourceSupertype*().hasQualifiedName("org.apache.logging.log4j.core.config", "LoggerConfig")
            and this.getCallable().hasName("log")
            and this.hasName("data")
        }
    }

    predicate loggerConfiglog(DataFlow::Node node1, DataFlow::Node node2) {
        exists(MethodAccess ma |
            ma.getMethod().hasName("log")
            and ma.getCallee().getDeclaringType().hasQualifiedName("org.apache.logging.log4j.core.config", "LoggerConfig")
            and node2.asParameter() instanceof LoggerConfigSubClass
            and ma.getMethod().getSignature() = node2.asParameter().getCallable().getSignature()
            and ma.getArgument(node2.asParameter().getPosition()) = node1.asExpr()
            )
    }

}

class Test extends TaintTracking::Configuration
{
    Test(){ this = "Test"}
    override predicate isSource(DataFlow::Node source) {
        source.asParameter().getCallable().getDeclaringType().hasQualifiedName("org.apache.logging.log4j.core", "Logger")
        and source.asParameter().getCallable().hasName("log")
        and source.asParameter().hasName("message")
        and source.asParameter().getPosition() = 4
    }
    
    override predicate isSink(DataFlow::Node sink) {
        sink.asParameter().hasName("data")
        and sink.asParameter().getCallable().hasQualifiedName("org.apache.logging.log4j.core.config", "LoggerConfig", "log")
    }

    override predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
        TaintPropagation::strategylog(node1, node2)
        or TaintPropagation::loggerConfiglog(node1, node2)
    }

}

from Test config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "jndi injection vulnerability due to $@.",
source.getNode(), "user-provided value"

query result:

image

Question:

There're four classes(AwaitCompletionReliabilityStrategy、AwaitUnconditionallyReliabilityStrategy、DefaultReliabilityStrategy、LockingReliabilityStrategy)implements LocationAwareReliabilityStrategy interface and override this method:
void log(Supplier<LoggerConfig> reconfigured, String loggerName, String fqcn, StackTraceElement location, Marker marker, Level level, Message data, Throwable t);
All of this method have a call statement like: LoggerConfig.log(...), and signature of log method is here below:
public void log(final String loggerName, final String fqcn, final Marker marker, final Level level, final Message data, final Throwable t)
The Message data formal parameter is the sink as you can see from ql script I paste above。

my question is:
why just only two classes(AwaitCompletionReliabilityStrategy、AwaitUnconditionallyReliabilityStrateg)are shown in taint flow result and their path node taint tracking result even have been presented twice ?Is it a BUG ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    JavaacknowledgedGitHub staff acknowledges this issuequestionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions