Skip to content

Commit

Permalink
Merge pull request #15291 from egregius313/egregius313/java/dataflow/…
Browse files Browse the repository at this point in the history
…default-sanitizers

Java: Introduce a common sanitizer type for types which cannot realistically carry taint.
  • Loading branch information
egregius313 authored Jan 23, 2024
2 parents 145b5a3 + fcbee19 commit 3c8b093
Show file tree
Hide file tree
Showing 29 changed files with 80 additions and 119 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
category: feature
---
* Added a new library `semmle.code.java.security.Sanitizers` which contains a new sanitizer class `SimpleTypeSanitizer`, which represents nodes which cannot realistically carry taint for most queries (e.g. primitives, their boxed equivalents, and numeric types).
* Converted definitions of `isBarrier` and sanitizer classes to use `SimpleTypeSanitizer` instead of checking if `node.getType()` is `PrimitiveType` or `BoxedType`.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java
private import semmle.code.java.security.Encryption
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.security.Sanitizers

private class ShortStringLiteral extends StringLiteral {
ShortStringLiteral() { this.getValue().length() < 100 }
Expand All @@ -27,9 +28,7 @@ module InsecureCryptoConfig implements DataFlow::ConfigSig {

predicate isSink(DataFlow::Node n) { exists(CryptoAlgoSpec c | n.asExpr() = c.getAlgoSpec()) }

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
}
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
}

/**
Expand Down
7 changes: 2 additions & 5 deletions java/ql/lib/semmle/code/java/security/CommandLineQuery.qll
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.security.CommandArguments
private import semmle.code.java.security.ExternalProcess
private import semmle.code.java.security.Sanitizers

/** A sink for command injection vulnerabilities. */
abstract class CommandInjectionSink extends DataFlow::Node { }
Expand All @@ -38,11 +39,7 @@ private class DefaultCommandInjectionSink extends CommandInjectionSink {

private class DefaultCommandInjectionSanitizer extends CommandInjectionSanitizer {
DefaultCommandInjectionSanitizer() {
this.getType() instanceof PrimitiveType
or
this.getType() instanceof BoxedType
or
this.getType() instanceof NumberType
this instanceof SimpleTypeSanitizer
or
isSafeCommandArgument(this.asExpr())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.security.ExternalProcess
private import semmle.code.java.security.CommandArguments
private import semmle.code.java.security.Sanitizers

/** A taint-tracking configuration to reason about use of externally controlled strings to make command line commands. */
module ExecTaintedLocalConfig implements DataFlow::ConfigSig {
Expand All @@ -12,9 +13,7 @@ module ExecTaintedLocalConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof ArgumentToExec }

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType
or
node.getType() instanceof BoxedType
node instanceof SimpleTypeSanitizer
or
isSafeCommandArgument(node.asExpr())
}
Expand Down
5 changes: 2 additions & 3 deletions java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.frameworks.Networking
import semmle.code.java.security.HttpsUrls
private import semmle.code.java.security.Sanitizers

/**
* DEPRECATED: Use `HttpsStringToUrlOpenMethodFlow` instead.
Expand Down Expand Up @@ -38,9 +39,7 @@ module HttpStringToUrlOpenMethodFlowConfig implements DataFlow::ConfigSig {
any(HttpUrlsAdditionalTaintStep c).step(node1, node2)
}

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
}
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
}

/**
Expand Down
7 changes: 3 additions & 4 deletions java/ql/lib/semmle/code/java/security/JndiInjectionQuery.qll
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import semmle.code.java.dataflow.FlowSources
import semmle.code.java.frameworks.Jndi
import semmle.code.java.frameworks.SpringLdap
import semmle.code.java.security.JndiInjection
private import semmle.code.java.security.Sanitizers

/**
* DEPRECATED: Use `JndiInjectionFlow` instead.
Expand All @@ -19,8 +20,7 @@ deprecated class JndiInjectionFlowConfig extends TaintTracking::Configuration {
override predicate isSink(DataFlow::Node sink) { sink instanceof JndiInjectionSink }

override predicate isSanitizer(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType or
node instanceof SimpleTypeSanitizer or
node instanceof JndiInjectionSanitizer
}

Expand All @@ -38,8 +38,7 @@ module JndiInjectionFlowConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink instanceof JndiInjectionSink }

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType or
node instanceof SimpleTypeSanitizer or
node instanceof JndiInjectionSanitizer
}

Expand Down
8 changes: 2 additions & 6 deletions java/ql/lib/semmle/code/java/security/LdapInjection.qll
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import semmle.code.java.frameworks.UnboundId
import semmle.code.java.frameworks.SpringLdap
import semmle.code.java.frameworks.ApacheLdap
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.security.Sanitizers

/** A data flow sink for unvalidated user input that is used to construct LDAP queries. */
abstract class LdapInjectionSink extends DataFlow::Node { }
Expand All @@ -33,12 +34,7 @@ private class DefaultLdapInjectionSink extends LdapInjectionSink {
}

/** A sanitizer that clears the taint on (boxed) primitive types. */
private class DefaultLdapSanitizer extends LdapInjectionSanitizer {
DefaultLdapSanitizer() {
this.getType() instanceof PrimitiveType or
this.getType() instanceof BoxedType
}
}
private class DefaultLdapSanitizer extends LdapInjectionSanitizer instanceof SimpleTypeSanitizer { }

/**
* Holds if `n1` to `n2` is a dataflow step that converts between `String` and `LdapName`,
Expand Down
10 changes: 3 additions & 7 deletions java/ql/lib/semmle/code/java/security/LogInjection.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.controlflow.Guards
private import semmle.code.java.security.Sanitizers

/** A data flow sink for unvalidated user input that is used to log messages. */
abstract class LogInjectionSink extends DataFlow::Node { }
Expand All @@ -30,13 +31,8 @@ private class DefaultLogInjectionSink extends LogInjectionSink {
DefaultLogInjectionSink() { sinkNode(this, "log-injection") }
}

private class DefaultLogInjectionSanitizer extends LogInjectionSanitizer {
DefaultLogInjectionSanitizer() {
this.getType() instanceof BoxedType or
this.getType() instanceof PrimitiveType or
this.getType() instanceof NumericType
}
}
private class DefaultLogInjectionSanitizer extends LogInjectionSanitizer instanceof SimpleTypeSanitizer
{ }

private class LineBreaksLogInjectionSanitizer extends LogInjectionSanitizer {
LineBreaksLogInjectionSanitizer() {
Expand Down
5 changes: 2 additions & 3 deletions java/ql/lib/semmle/code/java/security/OgnlInjectionQuery.qll
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java
import semmle.code.java.dataflow.FlowSources
import semmle.code.java.security.OgnlInjection
private import semmle.code.java.security.Sanitizers

/**
* DEPRECATED: Use `OgnlInjectionFlow` instead.
Expand Down Expand Up @@ -33,9 +34,7 @@ module OgnlInjectionFlowConfig implements DataFlow::ConfigSig {

predicate isSink(DataFlow::Node sink) { sink instanceof OgnlInjectionSink }

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
}
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }

predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
any(OgnlInjectionAdditionalTaintStep c).step(node1, node2)
Expand Down
9 changes: 2 additions & 7 deletions java/ql/lib/semmle/code/java/security/RequestForgery.qll
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import semmle.code.java.dataflow.DataFlow
import semmle.code.java.frameworks.Properties
private import semmle.code.java.dataflow.StringPrefixes
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.security.Sanitizers

/**
* A unit class for adding additional taint steps that are specific to server-side request forgery (SSRF) attacks.
Expand Down Expand Up @@ -59,13 +60,7 @@ private class DefaultRequestForgerySink extends RequestForgerySink {
/** A sanitizer for request forgery vulnerabilities. */
abstract class RequestForgerySanitizer extends DataFlow::Node { }

private class PrimitiveSanitizer extends RequestForgerySanitizer {
PrimitiveSanitizer() {
this.getType() instanceof PrimitiveType or
this.getType() instanceof BoxedType or
this.getType() instanceof NumberType
}
}
private class PrimitiveSanitizer extends RequestForgerySanitizer instanceof SimpleTypeSanitizer { }

private class HostnameSanitizingPrefix extends InterestingPrefix {
int offset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.security.Sanitizers
import semmle.code.java.security.ResponseSplitting

/**
Expand All @@ -16,9 +17,7 @@ module ResponseSplittingConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink }

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType
or
node.getType() instanceof BoxedType
node instanceof SimpleTypeSanitizer
or
exists(MethodCall ma, string methodName, CompileTimeConstantExpr target |
node.asExpr() = ma and
Expand Down
15 changes: 15 additions & 0 deletions java/ql/lib/semmle/code/java/security/Sanitizers.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/** Classes to represent sanitizers commonly used in dataflow and taint tracking configurations. */

import java
private import semmle.code.java.dataflow.DataFlow

/**
* A node whose type is a simple type unlikely to carry taint, such as primitives or their boxed counterparts.
*/
class SimpleTypeSanitizer extends DataFlow::Node {
SimpleTypeSanitizer() {
this.getType() instanceof PrimitiveType or
this.getType() instanceof BoxedType or
this.getType() instanceof NumberType
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ private import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.dataflow.TaintTracking
import semmle.code.java.security.SensitiveActions
import semmle.code.java.frameworks.android.Compose
private import semmle.code.java.security.Sanitizers

/** A variable that may hold sensitive information, judging by its name. */
class CredentialExpr extends Expr {
Expand Down Expand Up @@ -55,9 +56,7 @@ module SensitiveLoggerConfig implements DataFlow::ConfigSig {

predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer.asExpr() instanceof LiveLiteral or
sanitizer.getType() instanceof PrimitiveType or
sanitizer.getType() instanceof BoxedType or
sanitizer.getType() instanceof NumberType or
sanitizer instanceof SimpleTypeSanitizer or
sanitizer.getType() instanceof TypeType
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.security.SqlConcatenatedLib
private import semmle.code.java.security.SqlInjectionQuery
private import semmle.code.java.security.Sanitizers

private class UncontrolledStringBuilderSource extends DataFlow::ExprNode {
UncontrolledStringBuilderSource() {
Expand All @@ -22,9 +23,7 @@ module UncontrolledStringBuilderSourceFlowConfig implements DataFlow::ConfigSig

predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType
}
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }
}

/**
Expand Down
7 changes: 2 additions & 5 deletions java/ql/lib/semmle/code/java/security/SqlInjectionQuery.qll
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import java
import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.security.Sanitizers
import semmle.code.java.security.QueryInjection

/**
Expand Down Expand Up @@ -41,11 +42,7 @@ module QueryInjectionFlowConfig implements DataFlow::ConfigSig {

predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType or
node.getType() instanceof NumberType
}
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }

predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
any(AdditionalQueryInjectionTaintStep s).step(node1, node2)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.security.SqlInjectionQuery
private import semmle.code.java.security.Sanitizers

/**
* A taint-tracking configuration for reasoning about local user input that is
Expand All @@ -16,11 +17,7 @@ module LocalUserInputToQueryInjectionFlowConfig implements DataFlow::ConfigSig {

predicate isSink(DataFlow::Node sink) { sink instanceof QueryInjectionSink }

predicate isBarrier(DataFlow::Node node) {
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType or
node.getType() instanceof NumberType
}
predicate isBarrier(DataFlow::Node node) { node instanceof SimpleTypeSanitizer }

predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
any(AdditionalQueryInjectionTaintStep s).step(node1, node2)
Expand Down
9 changes: 3 additions & 6 deletions java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.ExternalFlow
import semmle.code.java.security.PathSanitizer
private import semmle.code.java.security.Sanitizers

/**
* A unit class for adding additional taint steps.
Expand Down Expand Up @@ -57,9 +58,7 @@ module TaintedPathConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "path-injection") }

predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer.getType() instanceof BoxedType or
sanitizer.getType() instanceof PrimitiveType or
sanitizer.getType() instanceof NumberType or
sanitizer instanceof SimpleTypeSanitizer or
sanitizer instanceof PathInjectionSanitizer
}

Expand All @@ -80,9 +79,7 @@ module TaintedPathLocalConfig implements DataFlow::ConfigSig {
predicate isSink(DataFlow::Node sink) { sinkNode(sink, "path-injection") }

predicate isBarrier(DataFlow::Node sanitizer) {
sanitizer.getType() instanceof BoxedType or
sanitizer.getType() instanceof PrimitiveType or
sanitizer.getType() instanceof NumberType or
sanitizer instanceof SimpleTypeSanitizer or
sanitizer instanceof PathInjectionSanitizer
}

Expand Down
10 changes: 3 additions & 7 deletions java/ql/lib/semmle/code/java/security/TemplateInjection.qll
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import java
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.security.Sanitizers

/**
* A source for server-side template injection (SST) vulnerabilities.
Expand Down Expand Up @@ -89,10 +90,5 @@ private class DefaultTemplateInjectionSink extends TemplateInjectionSink {
DefaultTemplateInjectionSink() { sinkNode(this, "template-injection") }
}

private class DefaultTemplateInjectionSanitizer extends TemplateInjectionSanitizer {
DefaultTemplateInjectionSanitizer() {
this.getType() instanceof PrimitiveType or
this.getType() instanceof BoxedType or
this.getType() instanceof NumericType
}
}
private class DefaultTemplateInjectionSanitizer extends TemplateInjectionSanitizer instanceof SimpleTypeSanitizer
{ }
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ private import semmle.code.java.controlflow.Guards
private import semmle.code.java.dataflow.ExternalFlow
private import semmle.code.java.dataflow.FlowSources
private import semmle.code.java.frameworks.owasp.Esapi
private import semmle.code.java.security.Sanitizers

/**
* A source of data that crosses a trust boundary.
Expand Down Expand Up @@ -57,9 +58,7 @@ module TrustBoundaryConfig implements DataFlow::ConfigSig {
predicate isBarrier(DataFlow::Node node) {
node instanceof TrustBoundaryValidationSanitizer or
node.getType() instanceof HttpServletSession or
node.getType() instanceof NumberType or
node.getType() instanceof PrimitiveType or
node.getType() instanceof BoxedType
node instanceof SimpleTypeSanitizer
}

predicate isSink(DataFlow::Node sink) { sink instanceof TrustBoundaryViolationSink }
Expand Down
Loading

0 comments on commit 3c8b093

Please sign in to comment.