Merge pull request #14124 from alexrford/rb/dataflow-query-refactor

Ruby: Use the new dataflow API for checked in queries
This commit is contained in:
Alex Ford
2023-09-13 14:24:47 +01:00
committed by GitHub
74 changed files with 1056 additions and 369 deletions

View File

@@ -19,22 +19,64 @@ class PostValidation extends DataFlow::FlowState {
PostValidation() { this = "PostValidation" }
}
/**
* A state signifying if a logical validation has been performed or not.
*/
private newtype ValidationState =
// A state signifying that a logical validation has not been performed.
PreValidationState() or
// A state signifying that a logical validation has been performed.
PostValidationState()
/**
* A taint-tracking configuration for detecting "Unicode transformation mishandling" vulnerabilities.
*
* This configuration uses two flow states, `PreValidation` and `PostValidation`,
* to track the requirement that a logical validation has been performed before the Unicode Transformation.
* DEPRECATED: Use `UnicodeBypassValidationFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnicodeBypassValidation" }
private ValidationState convertState(DataFlow::FlowState state) {
state instanceof PreValidation and result = PreValidationState()
or
state instanceof PostValidation and result = PostValidationState()
}
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
source instanceof RemoteFlowSource and state instanceof PreValidation
UnicodeBypassValidationConfig::isSource(source, this.convertState(state))
}
override predicate isAdditionalTaintStep(
DataFlow::Node nodeFrom, DataFlow::FlowState stateFrom, DataFlow::Node nodeTo,
DataFlow::FlowState stateTo
) {
UnicodeBypassValidationConfig::isAdditionalFlowStep(nodeFrom, this.convertState(stateFrom),
nodeTo, this.convertState(stateTo))
}
/* A Unicode Tranformation (Unicode tranformation) is considered a sink when the algorithm used is either NFC or NFKC. */
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
UnicodeBypassValidationConfig::isSink(sink, this.convertState(state))
}
}
/**
* A taint-tracking configuration for detecting "Unicode transformation mishandling" vulnerabilities.
*
* This configuration uses two flow states, `PreValidation` and `PostValidation`,
* to track the requirement that a logical validation has been performed before the Unicode Transformation.
*/
private module UnicodeBypassValidationConfig implements DataFlow::StateConfigSig {
class FlowState = ValidationState;
predicate isSource(DataFlow::Node source, FlowState state) {
source instanceof RemoteFlowSource and state = PreValidationState()
}
predicate isAdditionalFlowStep(
DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
) {
(
exists(Escaping escaping | nodeFrom = escaping.getAnInput() and nodeTo = escaping.getOutput())
@@ -75,12 +117,12 @@ class Configuration extends TaintTracking::Configuration {
nodeTo = cn
)
) and
stateFrom instanceof PreValidation and
stateTo instanceof PostValidation
stateFrom = PreValidationState() and
stateTo = PostValidationState()
}
/* A Unicode Tranformation (Unicode tranformation) is considered a sink when the algorithm used is either NFC or NFKC. */
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) {
predicate isSink(DataFlow::Node sink, FlowState state) {
(
exists(DataFlow::CallNode cn |
cn.getMethodName() = "unicode_normalize" and
@@ -118,6 +160,11 @@ class Configuration extends TaintTracking::Configuration {
sink = cn.getArgument(0)
)
) and
state instanceof PostValidation
state = PostValidationState()
}
}
/**
* Taint-tracking configuration for detecting "Unicode transformation mishandling" vulnerabilities.
*/
module UnicodeBypassValidationFlow = TaintTracking::GlobalWithState<UnicodeBypassValidationConfig>;

View File

@@ -12,8 +12,9 @@ private import codeql.ruby.ApiGraphs
/**
* A taint-tracking configuration for reasoning about zip slip
* vulnerabilities.
* DEPRECATED: Use `ZipSlipFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ZipSlip" }
override predicate isSource(DataFlow::Node source) { source instanceof ZipSlip::Source }
@@ -36,3 +37,30 @@ class Configuration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof ZipSlip::Sanitizer }
}
private module ZipSlipConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ZipSlip::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof ZipSlip::Sink }
/**
* This should actually be
* `and cn = API::getTopLevelMember("Gem").getMember("Package").getMember("TarReader").getMember("Entry").getAMethodCall("full_name")` and similar for other classes
* but I couldn't make it work so there's only check for the method name called on the entry. It is `full_name` for `Gem::Package::TarReader::Entry` and `Zlib`
* and `name` for `Zip::File`
*/
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
exists(DataFlow::CallNode cn |
cn.getReceiver() = nodeFrom and
cn.getMethodName() in ["full_name", "name"] and
cn = nodeTo
)
}
predicate isBarrier(DataFlow::Node node) { node instanceof ZipSlip::Sanitizer }
}
/**
* Taint-tracking for reasoning about zip slip vulnerabilities.
*/
module ZipSlipFlow = TaintTracking::Global<ZipSlipConfig>;

View File

@@ -2,7 +2,7 @@
* Provides a taint-tracking configuration for "Clear-text logging of sensitive information".
*
* Note, for performance reasons: only import this file if
* `CleartextLogging::Configuration` is needed, otherwise
* `CleartextLoggingFlow` is needed, otherwise
* `CleartextLoggingCustomizations` should be imported instead.
*/
@@ -10,25 +10,43 @@ private import codeql.ruby.AST
private import codeql.ruby.DataFlow
private import codeql.ruby.TaintTracking
import CleartextLoggingCustomizations::CleartextLogging
private import CleartextLoggingCustomizations::CleartextLogging as CleartextLogging
private import CleartextLoggingCustomizations::CleartextLogging as CL
/**
* A taint-tracking configuration for detecting "Clear-text logging of sensitive information".
* DEPRECATED: Use `CleartextLoggingFlow` instead
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CleartextLogging" }
override predicate isSource(DataFlow::Node source) { source instanceof CleartextLogging::Source }
override predicate isSource(DataFlow::Node source) { source instanceof CL::Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof CleartextLogging::Sink }
override predicate isSink(DataFlow::Node sink) { sink instanceof CL::Sink }
override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node)
or
node instanceof CleartextLogging::Sanitizer
node instanceof CL::Sanitizer
}
override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
CleartextLogging::isAdditionalTaintStep(nodeFrom, nodeTo)
CL::isAdditionalTaintStep(nodeFrom, nodeTo)
}
}
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof CL::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof CL::Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof CL::Sanitizer }
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
CL::isAdditionalTaintStep(nodeFrom, nodeTo)
}
}
/**
* Taint-tracking for detecting "Clear-text logging of sensitive information".
*/
module CleartextLoggingFlow = TaintTracking::Global<Config>;

View File

@@ -2,32 +2,50 @@
* Provides a taint-tracking configuration for "Clear-text storage of sensitive information".
*
* Note, for performance reasons: only import this file if
* `Configuration` is needed, otherwise `CleartextStorageCustomizations` should be
* imported instead.
* `CleartextStorageFlow` is needed, otherwise
* `CleartextStorageCustomizations` should be imported instead.
*/
private import codeql.ruby.AST
private import codeql.ruby.DataFlow
private import codeql.ruby.TaintTracking
private import CleartextStorageCustomizations::CleartextStorage as CleartextStorage
private import CleartextStorageCustomizations::CleartextStorage as CS
/**
* A taint-tracking configuration for detecting "Clear-text storage of sensitive information".
* DEPRECATED: Use `CleartextStorageFlow` instead
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CleartextStorage" }
override predicate isSource(DataFlow::Node source) { source instanceof CleartextStorage::Source }
override predicate isSource(DataFlow::Node source) { source instanceof CS::Source }
override predicate isSink(DataFlow::Node sink) { sink instanceof CleartextStorage::Sink }
override predicate isSink(DataFlow::Node sink) { sink instanceof CS::Sink }
override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node)
or
node instanceof CleartextStorage::Sanitizer
node instanceof CS::Sanitizer
}
override predicate isAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
CleartextStorage::isAdditionalTaintStep(nodeFrom, nodeTo)
CS::isAdditionalTaintStep(nodeFrom, nodeTo)
}
}
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof CS::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof CS::Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof CS::Sanitizer }
predicate isAdditionalFlowStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
CS::isAdditionalTaintStep(nodeFrom, nodeTo)
}
}
/**
* Taint-tracking for detecting "Clear-text storage of sensitive information".
*/
module CleartextStorageFlow = TaintTracking::Global<Config>;

View File

@@ -13,27 +13,82 @@ private import codeql.ruby.dataflow.BarrierGuards
module CodeInjection {
/** Flow states used to distinguish whether an attacker controls the entire string. */
module FlowState {
/** Flow state used for normal tainted data, where an attacker might only control a substring. */
DataFlow::FlowState substring() { result = "substring" }
/**
* Flow state used for normal tainted data, where an attacker might only control a substring.
* DEPRECATED: Use `Full()`
*/
deprecated DataFlow::FlowState substring() { result = "substring" }
/** Flow state used for data that is entirely controlled by the attacker. */
DataFlow::FlowState full() { result = "full" }
/**
* Flow state used for data that is entirely controlled by the attacker.
* DEPRECATED: Use `Full()`
*/
deprecated DataFlow::FlowState full() { result = "full" }
private newtype TState =
TFull() or
TSubString()
/** A flow state used to distinguish whether an attacker controls the entire string. */
class State extends TState {
/**
* Gets a string representation of this state.
*/
string toString() { result = this.getStringRepresentation() }
/**
* Gets a canonical string representation of this state.
*/
string getStringRepresentation() {
this = TSubString() and result = "substring"
or
this = TFull() and result = "full"
}
}
/**
* A flow state used for normal tainted data, where an attacker might only control a substring.
*/
class SubString extends State, TSubString { }
/**
* A flow state used for data that is entirely controlled by the attacker.
*/
class Full extends State, TFull { }
}
/**
* A data flow source for "Code injection" vulnerabilities.
*/
abstract class Source extends DataFlow::Node {
/**
* Gets a flow state for which this is a source.
* DEPRECATED: Use `getAState()`
*/
deprecated DataFlow::FlowState getAFlowState() {
result = [FlowState::substring(), FlowState::full()]
}
/** Gets a flow state for which this is a source. */
DataFlow::FlowState getAFlowState() { result = [FlowState::substring(), FlowState::full()] }
FlowState::State getAState() {
result instanceof FlowState::SubString or result instanceof FlowState::Full
}
}
/**
* A data flow sink for "Code injection" vulnerabilities.
*/
abstract class Sink extends DataFlow::Node {
/**
* Holds if this sink is safe for an attacker that only controls a substring.
* DEPRECATED: Use `getAState()`
*/
deprecated DataFlow::FlowState getAFlowState() {
result = [FlowState::substring(), FlowState::full()]
}
/** Holds if this sink is safe for an attacker that only controls a substring. */
DataFlow::FlowState getAFlowState() { result = [FlowState::substring(), FlowState::full()] }
FlowState::State getAState() { any() }
}
/**
@@ -43,8 +98,15 @@ module CodeInjection {
/**
* Gets a flow state for which this is a sanitizer.
* Sanitizes all states if the result is empty.
* DEPRECATED: Use `getAState()`
*/
DataFlow::FlowState getAFlowState() { none() }
deprecated DataFlow::FlowState getAFlowState() { none() }
/**
* Gets a flow state for which this is a sanitizer.
* Sanitizes all states if the result is empty.
*/
FlowState::State getAState() { none() }
}
/**
@@ -67,12 +129,17 @@ module CodeInjection {
CodeExecutionAsSink() { this = c.getCode() }
/** Gets a flow state for which this is a sink. */
override DataFlow::FlowState getAFlowState() {
deprecated override DataFlow::FlowState getAFlowState() {
if c.runsArbitraryCode()
then result = [FlowState::substring(), FlowState::full()] // If it runs arbitrary code then it's always vulnerable.
else result = FlowState::full() // If it "just" loads something, then it's only vulnerable if the attacker controls the entire string.
}
override FlowState::State getAState() {
if c.runsArbitraryCode()
then any() // If it runs arbitrary code then it's always vulnerable.
else result instanceof FlowState::Full // If it "just" loads something, then it's only vulnerable if the attacker controls the entire string.
}
}
private import codeql.ruby.AST as Ast
@@ -92,6 +159,8 @@ module CodeInjection {
)
}
override DataFlow::FlowState getAFlowState() { result = FlowState::full() }
deprecated override DataFlow::FlowState getAFlowState() { result = FlowState::full() }
override FlowState::State getAState() { result instanceof FlowState::Full }
}
}

View File

@@ -1,8 +1,9 @@
/**
* Provides a taint-tracking configuration for detecting "Code injection" vulnerabilities.
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `CodeInjectionCustomizations` should be imported instead.
* Note, for performance reasons: only import this file if
* `CodeInjectionFlow` is needed, otherwise
* `CodeInjectionCustomizations` should be imported instead.
*/
import codeql.ruby.DataFlow
@@ -12,8 +13,9 @@ import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for detecting "Code injection" vulnerabilities.
* DEPRECATED: Use `CodeInjectionFlow` instead
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CodeInjection" }
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) {
@@ -40,3 +42,26 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
private module Config implements DataFlow::StateConfigSig {
class FlowState = FlowState::State;
predicate isSource(DataFlow::Node source, FlowState state) { state = source.(Source).getAState() }
predicate isSink(DataFlow::Node sink, FlowState state) { state = sink.(Sink).getAState() }
predicate isBarrier(DataFlow::Node node) {
node instanceof Sanitizer and not exists(node.(Sanitizer).getAState())
or
node instanceof StringConstCompareBarrier
or
node instanceof StringConstArrayInclusionCallBarrier
}
predicate isBarrier(DataFlow::Node node, FlowState state) { node.(Sanitizer).getAState() = state }
}
/**
* Taint-tracking for detecting "Code injection" vulnerabilities.
*/
module CodeInjectionFlow = TaintTracking::GlobalWithState<Config>;

View File

@@ -3,7 +3,7 @@
* command-injection vulnerabilities (CWE-078).
*
* Note, for performance reasons: only import this file if
* `CommandInjection::Configuration` is needed, otherwise
* `CommandInjectionFlow` is needed, otherwise
* `CommandInjectionCustomizations` should be imported instead.
*/
@@ -15,8 +15,9 @@ import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for reasoning about command-injection vulnerabilities.
* DEPRECATED: Use `CommandInjectionFlow` instead
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "CommandInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -29,3 +30,20 @@ class Configuration extends TaintTracking::Configuration {
node instanceof StringConstArrayInclusionCallBarrier
}
}
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) {
node instanceof Sanitizer or
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier
}
}
/**
* Taint-tracking for reasoning about command-injection vulnerabilities.
*/
module CommandInjectionFlow = TaintTracking::Global<Config>;

View File

@@ -2,7 +2,7 @@
* Provides a taint tracking configuration for reasoning about bypass of sensitive action guards.
*
* Note, for performance reasons: only import this file if
* `ConditionalBypass::Configuration` is needed, otherwise
* `ConditionalBypassFlow` is needed, otherwise
* `ConditionalBypassCustomizations` should be imported instead.
*/
@@ -13,8 +13,9 @@ import ConditionalBypassCustomizations::ConditionalBypass
/**
* A taint tracking configuration for bypass of sensitive action guards.
* DEPRECATED: Use `ConditionalBypassFlow` instead
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ConditionalBypass" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -26,3 +27,16 @@ class Configuration extends TaintTracking::Configuration {
node instanceof Sanitizer
}
}
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* Taint-tracking for bypass of sensitive action guards.
*/
module ConditionalBypassFlow = TaintTracking::Global<Config>;

View File

@@ -19,19 +19,42 @@ module HardcodedDataInterpretedAsCode {
* Flow states used to distinguish value-preserving flow from taint flow.
*/
module FlowState {
/** Flow state used to track value-preserving flow. */
DataFlow::FlowState data() { result = "data" }
/**
* Flow state used to track value-preserving flow.
* DEPRECATED: Use `Data()`
*/
deprecated DataFlow::FlowState data() { result = "data" }
/** Flow state used to tainted data (non-value preserving flow). */
DataFlow::FlowState taint() { result = "taint" }
/**
* Flow state used to tainted data (non-value preserving flow).
* DEPRECATED: Use `Taint()`
*/
deprecated DataFlow::FlowState taint() { result = "taint" }
/**
* Flow states used to distinguish value-preserving flow from taint flow.
*/
newtype State =
/** Flow state used to track value-preserving flow. */
Data() or
/** Flow state used to tainted data (non-value preserving flow). */
Taint()
}
/**
* A data flow source for hard-coded data.
*/
abstract class Source extends DataFlow::Node {
/** Gets a flow label for which this is a source. */
DataFlow::FlowState getLabel() { result = FlowState::data() }
/**
* Gets a flow label for which this is a source.
* DEPRECATED: Use `getALabel()`
*/
deprecated DataFlow::FlowState getLabel() { result = FlowState::data() }
/**
* Gets a flow label for which this is a source.
*/
FlowState::State getALabel() { result = FlowState::Data() }
}
/**
@@ -41,13 +64,26 @@ module HardcodedDataInterpretedAsCode {
/** Gets a description of what kind of sink this is. */
abstract string getKind();
/** Gets a flow label for which this is a sink. */
DataFlow::FlowState getLabel() {
/**
* Gets a flow label for which this is a sink.
* DEPRECATED: Use `getALabel()`
*/
deprecated DataFlow::FlowState getLabel() {
// We want to ignore value-flow and only consider taint-flow, since the
// source is just a hex string, and evaluating that directly will just
// cause a syntax error.
result = FlowState::taint()
}
/**
* Gets a flow label for which this is a sink.
*/
FlowState::State getALabel() {
// We want to ignore value-flow and only consider taint-flow, since the
// source is just a hex string, and evaluating that directly will just
// cause a syntax error.
result = FlowState::Taint()
}
}
/** A sanitizer for hard-coded data. */

View File

@@ -3,7 +3,7 @@
* being interpreted as code.
*
* Note, for performance reasons: only import this file if
* `HardcodedDataInterpretedAsCode::Configuration` is needed, otherwise
* `HardcodedDataInterpretedAsCodeFlow` is needed, otherwise
* `HardcodedDataInterpretedAsCodeCustomizations` should be imported instead.
*/
@@ -16,11 +16,9 @@ import HardcodedDataInterpretedAsCodeCustomizations::HardcodedDataInterpretedAsC
* A taint-tracking configuration for reasoning about hard-coded data
* being interpreted as code.
*
* We extend `DataFlow::Configuration` rather than
* `TaintTracking::Configuration`, so that we can set the flow state to
* `"taint"` on a taint step.
* DEPRECATED: Use `HardcodedDataInterpretedAsCodeFlow` instead
*/
class Configuration extends DataFlow::Configuration {
deprecated class Configuration extends DataFlow::Configuration {
Configuration() { this = "HardcodedDataInterpretedAsCode" }
override predicate isSource(DataFlow::Node source, DataFlow::FlowState label) {
@@ -46,3 +44,34 @@ class Configuration extends DataFlow::Configuration {
stateTo = FlowState::taint()
}
}
private module Config implements DataFlow::StateConfigSig {
class FlowState = FlowState::State;
predicate isSource(DataFlow::Node source, FlowState label) { source.(Source).getALabel() = label }
predicate isSink(DataFlow::Node sink, FlowState label) { sink.(Sink).getALabel() = label }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate isAdditionalFlowStep(
DataFlow::Node nodeFrom, FlowState stateFrom, DataFlow::Node nodeTo, FlowState stateTo
) {
defaultAdditionalTaintStep(nodeFrom, nodeTo) and
// This is a taint step, so the flow state becomes `taint`.
(
stateFrom = FlowState::Taint()
or
stateFrom = FlowState::Data()
) and
stateTo = FlowState::Taint()
}
}
/**
* Taint-tracking for reasoning about hard-coded data being interpreted as code.
* We implement `DataFlow::GlobalWithState` rather than
* `TaintTracking::GlobalWithState`, so that we can set the flow state to
* `Taint()` on a taint step.
*/
module HardcodedDataInterpretedAsCodeFlow = DataFlow::GlobalWithState<Config>;

View File

@@ -21,8 +21,14 @@ module InsecureDownload {
abstract class Source extends DataFlow::Node {
/**
* Gets a flow-label for this source.
* DEPRECATED: Use `getAFlowLabel()`
*/
abstract DataFlow::FlowState getALabel();
abstract deprecated DataFlow::FlowState getALabel();
/**
* Gets a flow-label for this source.
*/
abstract Label::State getAFlowLabel();
}
/**
@@ -36,8 +42,14 @@ module InsecureDownload {
/**
* Gets a flow-label where this sink is vulnerable.
* DEPRECATED: Use `getAFlowLabel()`
*/
abstract DataFlow::FlowState getALabel();
abstract deprecated DataFlow::FlowState getALabel();
/**
* Gets a flow-label where this sink is vulnerable.
*/
abstract Label::State getAFlowLabel();
}
/**
@@ -51,24 +63,38 @@ module InsecureDownload {
module Label {
/**
* A flow-label for a URL that is downloaded over an insecure connection.
* DEPRECATED: Use `InsecureState()`
*/
class Insecure extends DataFlow::FlowState {
deprecated class Insecure extends DataFlow::FlowState {
Insecure() { this = "insecure" }
}
/**
* A flow-label for a URL that is sensitive.
* DEPRECATED: Use `SensitiveState()`
*/
class Sensitive extends DataFlow::FlowState {
deprecated class Sensitive extends DataFlow::FlowState {
Sensitive() { this = "sensitive" }
}
/**
* A flow-label for file URLs that are both sensitive and downloaded over an insecure connection.
* DEPRECATED: Use `SensitiveInsecureState()`
*/
class SensitiveInsecure extends DataFlow::FlowState {
deprecated class SensitiveInsecure extends DataFlow::FlowState {
SensitiveInsecure() { this = "sensitiveInsecure" }
}
/**
* Flow-labels for reasoning about download of sensitive file through insecure connection.
*/
newtype State =
/** A flow-label for a URL that is downloaded over an insecure connection. */
InsecureState() or
/** A flow-label for a URL that is sensitive. */
SensitiveState() or
/** A flow-label for file URLs that are both sensitive and downloaded over an insecure connection. */
SensitiveInsecureState()
}
/**
@@ -88,12 +114,19 @@ module InsecureDownload {
* seen as a source for downloads of sensitive files through an insecure connection.
*/
class InsecureFileUrl extends Source, InsecureUrl {
override DataFlow::FlowState getALabel() {
deprecated override DataFlow::FlowState getALabel() {
result instanceof Label::Insecure
or
hasUnsafeExtension(str) and
result instanceof Label::SensitiveInsecure
}
override Label::State getAFlowLabel() {
result = Label::InsecureState()
or
hasUnsafeExtension(str) and
result = Label::SensitiveInsecureState()
}
}
/**
@@ -103,7 +136,9 @@ module InsecureDownload {
class SensitiveFileName extends Source {
SensitiveFileName() { hasUnsafeExtension(this.asExpr().getConstantValue().getString()) }
override DataFlow::FlowState getALabel() { result instanceof Label::Sensitive }
deprecated override DataFlow::FlowState getALabel() { result instanceof Label::Sensitive }
override Label::State getAFlowLabel() { result = Label::SensitiveState() }
}
/**
@@ -145,11 +180,17 @@ module InsecureDownload {
override DataFlow::Node getDownloadCall() { result = req }
override DataFlow::FlowState getALabel() {
deprecated override DataFlow::FlowState getALabel() {
result instanceof Label::SensitiveInsecure
or
any(req.getAUrlPart()) instanceof InsecureUrl and result instanceof Label::Sensitive
}
override Label::State getAFlowLabel() {
result = Label::SensitiveInsecureState()
or
any(req.getAUrlPart()) instanceof InsecureUrl and result = Label::SensitiveState()
}
}
/**
@@ -191,7 +232,9 @@ module InsecureDownload {
)
}
override DataFlow::FlowState getALabel() { result instanceof Label::Insecure }
deprecated override DataFlow::FlowState getALabel() { result instanceof Label::Insecure }
override Label::State getAFlowLabel() { result = Label::InsecureState() }
override DataFlow::Node getDownloadCall() { result = request }
}

View File

@@ -2,7 +2,7 @@
* Provides a dataflow configuration for reasoning about the download of sensitive file through insecure connection.
*
* Note, for performance reasons: only import this file if
* `InsecureDownload::Configuration` is needed, otherwise
* `InsecureDownloadFlow` is needed, otherwise
* `InsecureDownloadCustomizations` should be imported instead.
*/
@@ -12,6 +12,8 @@ import InsecureDownloadCustomizations::InsecureDownload
/**
* A taint tracking configuration for download of sensitive file through insecure connection.
*
* DEPRECATED: Use `InsecureDownloadFlow`.
*/
deprecated class Configuration extends DataFlow::Configuration {
Configuration() { this = "InsecureDownload" }
@@ -30,21 +32,25 @@ deprecated class Configuration extends DataFlow::Configuration {
}
}
/**
* A taint tracking configuration for download of sensitive file through insecure connection.
*/
module Config implements DataFlow::StateConfigSig {
class FlowState = string;
private module InsecureDownloadConfig implements DataFlow::StateConfigSig {
class FlowState = Label::State;
predicate isSource(DataFlow::Node source, DataFlow::FlowState label) {
source.(Source).getALabel() = label
predicate isSource(DataFlow::Node source, FlowState label) {
source.(Source).getAFlowLabel() = label
}
predicate isSink(DataFlow::Node sink, DataFlow::FlowState label) {
sink.(Sink).getALabel() = label
}
predicate isSink(DataFlow::Node sink, FlowState label) { sink.(Sink).getAFlowLabel() = label }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
module Flow = DataFlow::GlobalWithState<Config>;
/**
* Taint-tracking for download of sensitive file through insecure connection.
*/
module InsecureDownloadFlow = DataFlow::GlobalWithState<InsecureDownloadConfig>;
/** DEPRECATED: Use `InsecureDownloadConfig` */
deprecated module Config = InsecureDownloadConfig;
/** DEPRECATED: Use `InsecureDownloadFlow` */
deprecated module Flow = InsecureDownloadFlow;

View File

@@ -4,10 +4,12 @@
private import codeql.ruby.AST
private import codeql.ruby.DataFlow
private import codeql.ruby.AST
private import codeql.ruby.ApiGraphs
private import codeql.ruby.dataflow.BarrierGuards
private import codeql.ruby.dataflow.RemoteFlowSources
private import codeql.ruby.frameworks.core.Kernel::Kernel
private import codeql.ruby.frameworks.Files
private import codeql.ruby.TaintTracking
/** A call to a method that might access a file or start a process. */
class AmbiguousPathCall extends DataFlow::CallNode {
@@ -72,3 +74,20 @@ abstract class Sanitizer extends DataFlow::Node { }
private class FileJoinSanitizer extends Sanitizer {
FileJoinSanitizer() { this = any(File::FileJoinSummary s).getParameter("1..") }
}
private module KernelOpenConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSink(DataFlow::Node sink) { sink = any(AmbiguousPathCall r).getPathArgument() }
predicate isBarrier(DataFlow::Node node) {
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier or
node instanceof Sanitizer
}
}
/**
* Taint-tracking for detecting insecure uses of `Kernel.open` and similar sinks.
*/
module KernelOpenFlow = TaintTracking::Global<KernelOpenConfig>;

View File

@@ -5,25 +5,30 @@
private import codeql.ruby.DataFlow
private import codeql.ruby.TaintTracking
private import LdapInjectionCustomizations::LdapInjection as LI
/** Provides a taint-tracking configuration for detecting LDAP Injections vulnerabilities. */
module LdapInjection {
/**
* Provides a taint-tracking configuration for detecting LDAP Injections vulnerabilities.
* DEPRECATED: Use `LdapInjectionFlow` instead
*/
deprecated module LdapInjection {
import LdapInjectionCustomizations::LdapInjection
/**
* A taint-tracking configuration for detecting LDAP Injections vulnerabilities.
*/
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
LdapInjection::isAdditionalFlowStep(node1, node2)
}
}
import TaintTracking::Global<Config>
import TaintTracking::Global<LdapInjectionConfig>
}
private module LdapInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof LI::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof LI::Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof LI::Sanitizer }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
LI::isAdditionalFlowStep(node1, node2)
}
}
/**
* Taint-tracking for detecting LDAP Injections vulnerabilities.
*/
module LdapInjectionFlow = TaintTracking::Global<LdapInjectionConfig>;

View File

@@ -26,8 +26,9 @@ abstract class Sanitizer extends DataFlow::Node { }
/**
* A taint-tracking configuration for untrusted user input used in log entries.
* DEPRECATED: Use `LogInjectionFlow`
*/
class LogInjectionConfiguration extends TaintTracking::Configuration {
deprecated class LogInjectionConfiguration extends TaintTracking::Configuration {
LogInjectionConfiguration() { this = "LogInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -74,3 +75,16 @@ class InspectSanitizer extends Sanitizer {
class HtmlEscapingAsSanitizer extends Sanitizer {
HtmlEscapingAsSanitizer() { this = any(HtmlEscaping esc).getOutput() }
}
private module LogInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* Taint-tracking for untrusted user input used in log entries.
*/
module LogInjectionFlow = TaintTracking::Global<LogInjectionConfig>;

View File

@@ -3,7 +3,7 @@
* path injection vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `PathInjection::Configuration` is needed, otherwise
* `PathInjectionFlow` is needed, otherwise
* `PathInjectionCustomizations` should be imported instead.
*/
@@ -15,8 +15,9 @@ private import codeql.ruby.TaintTracking
/**
* A taint-tracking configuration for reasoning about path injection
* vulnerabilities.
* DEPRECATED: Use `PathInjectionFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "PathInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof PathInjection::Source }
@@ -31,3 +32,18 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof PathInjection::SanitizerGuard
}
}
private module PathInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof PathInjection::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof PathInjection::Sink }
predicate isBarrier(DataFlow::Node node) {
node instanceof Path::PathSanitization or node instanceof PathInjection::Sanitizer
}
}
/**
* Taint-tracking for detecting path injection vulnerabilities.
*/
module PathInjectionFlow = TaintTracking::Global<PathInjectionConfig>;

View File

@@ -2,8 +2,8 @@
* Provides a taint-tracking configuration for detecting "reflected server-side cross-site scripting" vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `ReflectedXSS::Configuration` is needed, otherwise
* `XSS::ReflectedXSS` should be imported instead.
* `ReflectedXssFlow` is needed, otherwise
* `XSS::ReflectedXss` should be imported instead.
*/
private import codeql.ruby.AST
@@ -12,14 +12,16 @@ import codeql.ruby.TaintTracking
/**
* Provides a taint-tracking configuration for detecting "reflected server-side cross-site scripting" vulnerabilities.
* DEPRECATED: Use `ReflectedXssFlow`
*/
module ReflectedXss {
deprecated module ReflectedXss {
import XSS::ReflectedXss
/**
* A taint-tracking configuration for detecting "reflected server-side cross-site scripting" vulnerabilities.
* DEPRECATED: Use `ReflectedXssFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ReflectedXSS" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,3 +39,22 @@ module ReflectedXss {
}
}
}
private module ReflectedXssConfig implements DataFlow::ConfigSig {
private import XSS::ReflectedXss as RX
predicate isSource(DataFlow::Node source) { source instanceof RX::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof RX::Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof RX::Sanitizer }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
RX::isAdditionalXssTaintStep(node1, node2)
}
}
/**
* Taint-tracking for detecting "reflected server-side cross-site scripting" vulnerabilities.
*/
module ReflectedXssFlow = TaintTracking::Global<ReflectedXssConfig>;

View File

@@ -2,9 +2,9 @@
* Provides a taint-tracking configuration for detecting flow of query string
* data to sensitive actions in GET query request handlers.
*
* Note, for performance reasons: only import this file if `Configuration` is
* needed, otherwise `SensitiveGetQueryCustomizations` should be imported
* instead.
* Note, for performance reasons: only import this file if
* `SensitiveGetQueryFlow` is needed, otherwise
* `SensitiveGetQueryCustomizations` should be imported instead.
*/
private import ruby
@@ -13,15 +13,16 @@ private import codeql.ruby.TaintTracking
/**
* Provides a taint-tracking configuration for detecting flow of query string
* data to sensitive actions in GET query request handlers.
* DEPRECATED: Use `SensitiveGetQueryFlow`
*/
module SensitiveGetQuery {
deprecated module SensitiveGetQuery {
import SensitiveGetQueryCustomizations::SensitiveGetQuery
/**
* A taint-tracking configuration for reasoning about use of sensitive data
* from a GET request query string.
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "SensitiveGetQuery" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -29,3 +30,17 @@ module SensitiveGetQuery {
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
}
}
private module SensitiveGetQueryConfig implements DataFlow::ConfigSig {
import SensitiveGetQueryCustomizations::SensitiveGetQuery
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
}
/**
* Taint-tracking for reasoning about use of sensitive data from a
* GET request query string.
*/
module SensitiveGetQueryFlow = TaintTracking::Global<SensitiveGetQueryConfig>;

View File

@@ -2,8 +2,9 @@
* Provides a taint-tracking configuration for detecting
* "Server side request forgery" vulnerabilities.
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `ServerSideRequestForgeryCustomizations` should be imported instead.
* Note, for performance reasons: only import this file if
* `ServerSideRequestForgeryFlow` is needed, otherwise
* `ServerSideRequestForgeryCustomizations` should be imported instead.
*/
import codeql.ruby.DataFlow
@@ -14,8 +15,9 @@ import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for detecting
* "Server side request forgery" vulnerabilities.
* DEPRECATED: Use `ServerSideRequestForgeryFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "ServerSideRequestForgery" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -32,3 +34,20 @@ class Configuration extends TaintTracking::Configuration {
guard instanceof SanitizerGuard
}
}
private module ServerSideRequestForgeryConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) {
node instanceof Sanitizer or
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier
}
}
/**
* Taint-tracking for detecting "Server side request forgery" vulnerabilities.
*/
module ServerSideRequestForgeryFlow = TaintTracking::Global<ServerSideRequestForgeryConfig>;

View File

@@ -9,8 +9,9 @@ import SqlInjectionCustomizations::SqlInjection
/**
* A taint-tracking configuration for detecting SQL injection vulnerabilities.
* DEPRECATED: Use `SqlInjectionFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "SqlInjectionConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -19,3 +20,16 @@ class Configuration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
private module SqlInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* Taint-tracking for detecting SQL injection vulnerabilities.
*/
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;

View File

@@ -13,8 +13,9 @@ private import StackTraceExposureCustomizations::StackTraceExposure
/**
* A taint-tracking configuration for detecting "stack trace exposure" vulnerabilities.
* DEPRECATED: Use `StackTraceExposureFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "StackTraceExposure" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -23,3 +24,16 @@ class Configuration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
private module StackTraceExposureConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* Taint-tracking for detecting "stack trace exposure" vulnerabilities.
*/
module StackTraceExposureFlow = TaintTracking::Global<StackTraceExposureConfig>;

View File

@@ -3,16 +3,19 @@
* cross-site scripting vulnerabilities.
*
* Note, for performance reasons: only import this file if
* `StoredXSS::Configuration` is needed, otherwise
* `XSS::StoredXSS` should be imported instead.
* `StoredXssFlow` is needed, otherwise
* `XSS::StoredXss` should be imported instead.
*/
import codeql.ruby.AST
import codeql.ruby.DataFlow
import codeql.ruby.TaintTracking
/** Provides a taint-tracking configuration for cross-site scripting vulnerabilities. */
module StoredXss {
/**
* Provides a taint-tracking configuration for cross-site scripting vulnerabilities.
* DEPRECATED: Use StoredXssFlow
*/
deprecated module StoredXss {
import XSS::StoredXss
/**
@@ -41,20 +44,24 @@ module StoredXss {
}
}
/**
* A taint-tracking configuration for reasoning about Stored XSS.
*/
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalXssTaintStep(node1, node2)
}
}
import TaintTracking::Global<Config>
import TaintTracking::Global<StoredXssConfig>
}
private module StoredXssConfig implements DataFlow::ConfigSig {
private import XSS::StoredXss
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
isAdditionalXssTaintStep(node1, node2)
}
}
/**
* Taint-tracking for reasoning about Stored XSS.
*/
module StoredXssFlow = TaintTracking::Global<StoredXssConfig>;

View File

@@ -9,8 +9,9 @@ import TemplateInjectionCustomizations::TemplateInjection
/**
* A taint-tracking configuration for detecting Server Side Template Injections vulnerabilities.
* DEPRECATED: Use `TemplateInjectionFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "TemplateInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -19,3 +20,16 @@ class Configuration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
private module TemplateInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* Taint-tracking for detecting Server Side Template Injections vulnerabilities.
*/
module TemplateInjectionFlow = TaintTracking::Global<TemplateInjectionConfig>;

View File

@@ -2,8 +2,9 @@
* Provides a taint-tracking configuration for reasoning about code
* constructed from library input vulnerabilities.
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `UnsafeCodeConstructionCustomizations` should be imported instead.
* Note, for performance reasons: only import this file if
* `UnsafeCodeConstructionFlow` is needed, otherwise
* `UnsafeCodeConstructionCustomizations` should be imported instead.
*/
import codeql.ruby.DataFlow
@@ -13,8 +14,9 @@ private import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for detecting code constructed from library input vulnerabilities.
* DEPRECATED: Use `UnsafeCodeConstructionFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeShellCommandConstruction" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -37,3 +39,28 @@ class Configuration extends TaintTracking::Configuration {
set.isElementOfTypeOrUnknown("int")
}
}
private module UnsafeCodeConstructionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) {
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier
}
// override to require the path doesn't have unmatched return steps
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet set) {
// allow implicit reads of array elements
isSink(node) and
set.isElementOfTypeOrUnknown("int")
}
}
/**
* Taint-tracking for detecting code constructed from library input vulnerabilities.
*/
module UnsafeCodeConstructionFlow = TaintTracking::Global<UnsafeCodeConstructionConfig>;

View File

@@ -2,7 +2,7 @@
* Provides a taint-tracking configuration for reasoning about unsafe deserialization.
*
* Note, for performance reasons: only import this file if
* `UnsafeDeserialization::Configuration` is needed, otherwise
* `UnsafeDeserializationFlow` is needed, otherwise
* `UnsafeDeserializationCustomizations` should be imported instead.
*/
@@ -13,8 +13,9 @@ import UnsafeDeserializationCustomizations
/**
* A taint-tracking configuration for reasoning about unsafe deserialization.
* DEPRECATED: Use `UnsafeDeserializationFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeDeserialization" }
override predicate isSource(DataFlow::Node source) {
@@ -28,3 +29,16 @@ class Configuration extends TaintTracking::Configuration {
node instanceof UnsafeDeserialization::Sanitizer
}
}
private module UnsafeDeserializationConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof UnsafeDeserialization::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserialization::Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof UnsafeDeserialization::Sanitizer }
}
/**
* Taint-tracking for reasoning about unsafe deserialization.
*/
module UnsafeCodeConstructionFlow = TaintTracking::Global<UnsafeDeserializationConfig>;

View File

@@ -2,8 +2,9 @@
* Provides a taint-tracking configuration for reasoning about HTML
* constructed from library input vulnerabilities.
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `UnsafeHtmlConstructionCustomizations` should be imported instead.
* Note, for performance reasons: only import this file if
* `UnsafeHtmlConstructionFlow` is needed, otherwise
* `UnsafeHtmlConstructionCustomizations` should be imported instead.
*/
import codeql.ruby.DataFlow
@@ -13,8 +14,9 @@ private import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for detecting unsafe HTML construction.
* DEPRECATED: Use `UnsafeHtmlConstructionFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeHtmlConstruction" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -31,3 +33,22 @@ class Configuration extends TaintTracking::Configuration {
result instanceof DataFlow::FeatureHasSourceCallContext
}
}
private module UnsafeHtmlConstructionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) {
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier
}
// override to require the path doesn't have unmatched return steps
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
}
/**
* Taint-tracking for detecting unsafe HTML construction.
*/
module UnsafeHtmlConstructionFlow = TaintTracking::Global<UnsafeHtmlConstructionConfig>;

View File

@@ -2,8 +2,9 @@
* Provides a taint tracking configuration for reasoning about shell command
* constructed from library input vulnerabilities
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `UnsafeShellCommandConstructionCustomizations` should be imported instead.
* Note, for performance reasons: only import this file if
* `UnsafeShellCommandConstructionFlow` is needed, otherwise
* `UnsafeShellCommandConstructionCustomizations` should be imported instead.
*/
import codeql.ruby.DataFlow
@@ -14,8 +15,9 @@ private import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for detecting shell command constructed from library input vulnerabilities.
* DEPRECATED: Use `UnsafeShellCommandConstructionFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UnsafeShellCommandConstruction" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -39,3 +41,30 @@ class Configuration extends TaintTracking::Configuration {
set.isElementOfTypeOrUnknown("int")
}
}
private module UnsafeShellCommandConstructionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) {
node instanceof CommandInjection::Sanitizer or // using all sanitizers from `rb/command-injection`
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier
}
// override to require the path doesn't have unmatched return steps
DataFlow::FlowFeature getAFeature() { result instanceof DataFlow::FeatureHasSourceCallContext }
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet set) {
// allow implicit reads of array elements
isSink(node) and
set.isElementOfTypeOrUnknown("int")
}
}
/**
* Taint-tracking for detecting shell command constructed from library input vulnerabilities.
*/
module UnsafeShellCommandConstructionFlow =
TaintTracking::Global<UnsafeShellCommandConstructionConfig>;

View File

@@ -1,8 +1,9 @@
/**
* Provides a taint-tracking configuration for detecting "URL redirection" vulnerabilities.
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `UrlRedirectCustomizations` should be imported instead.
* Note, for performance reasons: only import this file if
* `UrlRedirectConfig` is needed, otherwise
* `UrlRedirectCustomizations` should be imported instead.
*/
private import codeql.ruby.AST
@@ -13,8 +14,9 @@ import UrlRedirectCustomizations::UrlRedirect
/**
* A taint-tracking configuration for detecting "URL redirection" vulnerabilities.
* DEPRECATED: Use `UrlRedirectFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "UrlRedirect" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -31,3 +33,20 @@ class Configuration extends TaintTracking::Configuration {
UrlRedirect::isAdditionalTaintStep(node1, node2)
}
}
private module UrlRedirectConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
UrlRedirect::isAdditionalTaintStep(node1, node2)
}
}
/**
* Taint-tracking for detecting "URL redirection" vulnerabilities.
*/
module UrlRedirectFlow = TaintTracking::Global<UrlRedirectConfig>;

View File

@@ -10,18 +10,23 @@ private import codeql.ruby.DataFlow
private import codeql.ruby.TaintTracking
import XpathInjectionCustomizations::XpathInjection
/** Provides a taint-tracking configuration for detecting "Xpath Injection" vulnerabilities. */
module XpathInjection {
/**
* A taint-tracking configuration for detecting "Xpath Injection" vulnerabilities.
*/
private module Config implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
import TaintTracking::Global<Config>
/**
* Provides a taint-tracking configuration for detecting "Xpath Injection" vulnerabilities.
* DEPRECATED: Use `XpathInjectionFlow`
*/
deprecated module XpathInjection {
import TaintTracking::Global<XpathInjectionConfig>
}
private module XpathInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* Taint-tracking for detecting "Xpath Injection" vulnerabilities.
*/
module XpathInjectionFlow = TaintTracking::Global<XpathInjectionConfig>;

View File

@@ -3,7 +3,7 @@
* missing full-anchored regular expressions.
*
* Note, for performance reasons: only import this file if
* `MissingFullAnchor::Configuration` is needed, otherwise
* `MissingFullAnchorFlow` is needed, otherwise
* `MissingFullAnchorCustomizations` should be imported instead.
*/
@@ -14,8 +14,9 @@ import MissingFullAnchorCustomizations::MissingFullAnchor
/**
* A taint tracking configuration for reasoning about
* missing full-anchored regular expressions.
* DEPRECATED: Use `MissingFullAnchorFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "MissingFullAnchor" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -24,3 +25,16 @@ class Configuration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof Sanitizer }
}
private module MissingFullAnchorConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* Taint-tracking for reasoning about missing full-anchored regular expressions.
*/
module MissingFullAnchorFlow = TaintTracking::Global<MissingFullAnchorConfig>;

View File

@@ -2,9 +2,9 @@
* Provides a taint tracking configuration for reasoning about polynomial
* regular expression denial-of-service attacks.
*
* Note, for performance reasons: only import this file if `Configuration` is
* needed. Otherwise, `PolynomialReDoSCustomizations` should be imported
* instead.
* Note, for performance reasons: only import this file if
* `PolynomialReDoSFlow` is needed. Otherwise,
* `PolynomialReDoSCustomizations` should be imported instead.
*/
private import codeql.ruby.DataFlow
@@ -13,15 +13,17 @@ private import codeql.ruby.TaintTracking
/**
* Provides a taint-tracking configuration for detecting polynomial regular
* expression denial of service vulnerabilities.
* DEPRECATED: Use `PolynomialReDoSFlow`
*/
module PolynomialReDoS {
deprecated module PolynomialReDoS {
import PolynomialReDoSCustomizations::PolynomialReDoS
/**
* A taint-tracking configuration for detecting polynomial regular expression
* denial of service vulnerabilities.
* DEPRECATED: Use `PolynomialReDoSFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "PolynomialReDoS" }
override predicate isSource(DataFlow::Node source) { source instanceof Source }
@@ -35,3 +37,19 @@ module PolynomialReDoS {
}
}
}
private module PolynomialReDoSConfig implements DataFlow::ConfigSig {
private import PolynomialReDoSCustomizations::PolynomialReDoS
predicate isSource(DataFlow::Node source) { source instanceof Source }
predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof Sanitizer }
}
/**
* Taint-tracking for detecting polynomial regular
* expression denial of service vulnerabilities.
*/
module PolynomialReDoSFlow = TaintTracking::Global<PolynomialReDoSConfig>;

View File

@@ -1,8 +1,9 @@
/**
* Provides a taint-tracking configuration for detecting regexp injection vulnerabilities.
*
* Note, for performance reasons: only import this file if `Configuration` is needed,
* otherwise `RegExpInjectionCustomizations` should be imported instead.
* Note, for performance reasons: only import this file if
* `RegExpInjectionFlow` is needed, otherwise
* `RegExpInjectionCustomizations` should be imported instead.
*/
import codeql.ruby.DataFlow
@@ -12,8 +13,9 @@ import codeql.ruby.dataflow.BarrierGuards
/**
* A taint-tracking configuration for detecting regexp injection vulnerabilities.
* DEPRECATED: Use `RegExpInjectionFlow`
*/
class Configuration extends TaintTracking::Configuration {
deprecated class Configuration extends TaintTracking::Configuration {
Configuration() { this = "RegExpInjection" }
override predicate isSource(DataFlow::Node source) { source instanceof RegExpInjection::Source }
@@ -26,3 +28,16 @@ class Configuration extends TaintTracking::Configuration {
override predicate isSanitizer(DataFlow::Node node) { node instanceof RegExpInjection::Sanitizer }
}
private module RegExpInjectionConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof RegExpInjection::Source }
predicate isSink(DataFlow::Node sink) { sink instanceof RegExpInjection::Sink }
predicate isBarrier(DataFlow::Node node) { node instanceof RegExpInjection::Sanitizer }
}
/**
* Taint-tracking for detecting regexp injection vulnerabilities.
*/
module RegExpInjectionFlow = TaintTracking::Global<RegExpInjectionConfig>;

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* Built-in Ruby queries now use the new DataFlow API.

View File

@@ -12,11 +12,10 @@
* external/cwe/cwe-022
*/
import ruby
import codeql.ruby.experimental.ZipSlipQuery
import DataFlow::PathGraph
import ZipSlipFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from ZipSlipFlow::PathNode source, ZipSlipFlow::PathNode sink
where ZipSlipFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This file extraction depends on a $@.", source.getNode(),
"potentially untrusted source"

View File

@@ -12,12 +12,11 @@
* external/cwe/cwe-180
*/
import ruby
import codeql.ruby.experimental.UnicodeBypassValidationQuery
import DataFlow::PathGraph
import UnicodeBypassValidationFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from UnicodeBypassValidationFlow::PathNode source, UnicodeBypassValidationFlow::PathNode sink
where UnicodeBypassValidationFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"This $@ processes unsafely $@ and any logical validation in-between could be bypassed using special Unicode characters.",
sink.getNode(), "Unicode transformation (Unicode normalization)", source.getNode(),

View File

@@ -17,7 +17,7 @@ import codeql.ruby.DataFlow
import codeql.ruby.dataflow.internal.DataFlowPublic
import codeql.ruby.security.ConditionalBypassQuery
import codeql.ruby.security.SensitiveActions
import DataFlow::PathGraph
import ConditionalBypassFlow::PathGraph
/**
* Holds if the value of `nd` flows into `guard`.
@@ -69,15 +69,18 @@ class SensitiveActionGuardComparisonOperand extends Sink {
* control if `action` should be executed or not.
*/
predicate isTaintedGuardForSensitiveAction(
DataFlow::PathNode sink, DataFlow::PathNode source, SensitiveAction action
ConditionalBypassFlow::PathNode sink, ConditionalBypassFlow::PathNode source,
SensitiveAction action
) {
action = sink.getNode().(Sink).getAction() and
// exclude the intermediary sink
not sink.getNode() instanceof SensitiveActionGuardComparisonOperand and
exists(Configuration cfg | cfg.hasFlowPath(source, sink))
ConditionalBypassFlow::flowPath(source, sink)
}
from DataFlow::PathNode source, DataFlow::PathNode sink, SensitiveAction action
from
ConditionalBypassFlow::PathNode source, ConditionalBypassFlow::PathNode sink,
SensitiveAction action
where isTaintedGuardForSensitiveAction(sink, source, action)
select sink.getNode(), source, sink, "This condition guards a sensitive $@, but a $@ controls it.",
action, "action", source.getNode(), "user-provided value"

View File

@@ -16,7 +16,6 @@ import codeql.ruby.ApiGraphs
import codeql.ruby.DataFlow
import codeql.ruby.dataflow.RemoteFlowSources
import codeql.ruby.TaintTracking
import DataFlow::PathGraph
class DecompressionApiUse extends DataFlow::Node {
private DataFlow::CallNode call;
@@ -34,18 +33,20 @@ class DecompressionApiUse extends DataFlow::Node {
DataFlow::CallNode getCall() { result = call }
}
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "DecompressionApiUse" }
private module DecompressionApiConfig implements DataFlow::ConfigSig {
// this predicate will be used to constrain our query to find instances where only remote user-controlled data flows to the sink
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
// our Decompression APIs defined above will be the sinks we use for this query
override predicate isSink(DataFlow::Node sink) { sink instanceof DecompressionApiUse }
predicate isSink(DataFlow::Node sink) { sink instanceof DecompressionApiUse }
}
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
private module DecompressionApiFlow = TaintTracking::Global<DecompressionApiConfig>;
import DecompressionApiFlow::PathGraph
from DecompressionApiFlow::PathNode source, DecompressionApiFlow::PathNode sink
where DecompressionApiFlow::flowPath(source, sink)
select sink.getNode().(DecompressionApiUse), source, sink,
"This call to $@ is unsafe because user-controlled data is used to set the object being decompressed, which could lead to a denial of service attack or malicious code extracted from an unknown source.",
sink.getNode().(DecompressionApiUse).getCall(),

View File

@@ -13,9 +13,9 @@
import codeql.ruby.DataFlow
import codeql.ruby.security.LdapInjectionQuery
import LdapInjection::PathGraph
import LdapInjectionFlow::PathGraph
from LdapInjection::PathNode source, LdapInjection::PathNode sink
where LdapInjection::flowPath(source, sink)
from LdapInjectionFlow::PathNode source, LdapInjectionFlow::PathNode sink
where LdapInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This LDAP query depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -15,7 +15,6 @@ import codeql.ruby.DataFlow
import codeql.ruby.controlflow.CfgNodes
import codeql.ruby.frameworks.ActionController
import codeql.ruby.TaintTracking
import DataFlow::PathGraph
// any `request` calls in an action method
class Request extends DataFlow::CallNode {
@@ -73,10 +72,8 @@ class RequestGet extends DataFlow::CallNode {
}
}
class HttpVerbConfig extends TaintTracking::Configuration {
HttpVerbConfig() { this = "HttpVerbConfig" }
override predicate isSource(DataFlow::Node source) {
private module HttpVerbConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source instanceof RequestMethod or
source instanceof RequestRequestMethod or
source instanceof RequestEnvMethod or
@@ -85,13 +82,17 @@ class HttpVerbConfig extends TaintTracking::Configuration {
source instanceof RequestGet
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(ExprNodes::ConditionalExprCfgNode c | c.getCondition() = sink.asExpr()) or
exists(ExprNodes::CaseExprCfgNode c | c.getValue() = sink.asExpr())
}
}
from HttpVerbConfig config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
private module HttpVerbFlow = TaintTracking::Global<HttpVerbConfig>;
import HttpVerbFlow::PathGraph
from HttpVerbFlow::PathNode source, HttpVerbFlow::PathNode sink
where HttpVerbFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"Manually checking HTTP verbs is an indication that multiple requests are routed to the same controller action. This could lead to bypassing necessary authorization methods and other protections, like CSRF protection. Prefer using different controller actions for each HTTP method and relying Rails routing to handle mapping resources and verbs to specific methods."

View File

@@ -13,9 +13,9 @@
import codeql.ruby.DataFlow
import codeql.ruby.security.TemplateInjectionQuery
import DataFlow::PathGraph
import TemplateInjectionFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from TemplateInjectionFlow::PathNode source, TemplateInjectionFlow::PathNode sink
where TemplateInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This template depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -15,7 +15,6 @@ import codeql.ruby.Concepts
import codeql.ruby.DataFlow
import codeql.ruby.TaintTracking
import codeql.ruby.frameworks.ActionController
import DataFlow::PathGraph
/**
* Gets a call to `request` in an ActionController controller class.
@@ -42,16 +41,18 @@ class WeakParams extends DataFlow::CallNode {
* A Taint tracking config where the source is a weak params access in a controller and the sink
* is a method call of a model class
*/
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "WeakParamsConfiguration" }
override predicate isSource(DataFlow::Node node) { node instanceof WeakParams }
private module WeakParamsConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node instanceof WeakParams }
// the sink is an instance of a Model class that receives a method call
override predicate isSink(DataFlow::Node node) { node = any(PersistentWriteAccess a).getValue() }
predicate isSink(DataFlow::Node node) { node = any(PersistentWriteAccess a).getValue() }
}
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
private module WeakParamsFlow = TaintTracking::Global<WeakParamsConfig>;
import WeakParamsFlow::PathGraph
from WeakParamsFlow::PathNode source, WeakParamsFlow::PathNode sink
where WeakParamsFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"By exposing all keys in request parameters or by blindy accessing them, unintended parameters could be used and lead to mass-assignment or have other unexpected side-effects. It is safer to follow the 'strong parameters' pattern in Rails, which is outlined here: https://api.rubyonrails.org/classes/ActionController/StrongParameters.html"

View File

@@ -13,9 +13,9 @@
import codeql.ruby.DataFlow
import codeql.ruby.security.XpathInjectionQuery
import XpathInjection::PathGraph
import XpathInjectionFlow::PathGraph
from XpathInjection::PathNode source, XpathInjection::PathNode sink
where XpathInjection::flowPath(source, sink)
from XpathInjectionFlow::PathNode source, XpathInjectionFlow::PathNode sink
where XpathInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "XPath expression depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -12,17 +12,17 @@ import internal.TaintMetrics
import codeql.ruby.DataFlow
import codeql.ruby.TaintTracking
class BasicTaintConfiguration extends TaintTracking::Configuration {
BasicTaintConfiguration() { this = "BasicTaintConfiguration" }
private module BasicTaintConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node node) { node = relevantTaintSource(_) }
override predicate isSource(DataFlow::Node node) { node = relevantTaintSource(_) }
override predicate isSink(DataFlow::Node node) {
predicate isSink(DataFlow::Node node) {
// To reduce noise from synthetic nodes, only count nodes that have an associated expression.
exists(node.asExpr().getExpr())
}
}
private module BasicTaintFlow = TaintTracking::Global<BasicTaintConfig>;
from DataFlow::Node node
where any(BasicTaintConfiguration cfg).hasFlow(_, node)
where BasicTaintFlow::flow(_, node)
select node, "Tainted node"

View File

@@ -12,10 +12,10 @@
*/
import codeql.ruby.security.regexp.MissingFullAnchorQuery
import DataFlow::PathGraph
import MissingFullAnchorFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where config.hasFlowPath(source, sink) and sink.getNode() = sinkNode
from MissingFullAnchorFlow::PathNode source, MissingFullAnchorFlow::PathNode sink, Sink sinkNode
where MissingFullAnchorFlow::flowPath(source, sink) and sink.getNode() = sinkNode
select sink, source, sink, "This value depends on $@, and is $@ against a $@.", source.getNode(),
source.getNode().(Source).describe(), sinkNode.getCallNode(), "checked", sinkNode.getRegex(),
"badly anchored regular expression"

View File

@@ -17,9 +17,9 @@
import ruby
import codeql.ruby.security.PathInjectionQuery
import DataFlow::PathGraph
import PathInjectionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from PathInjectionFlow::PathNode source, PathInjectionFlow::PathNode sink
where PathInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This path depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -15,11 +15,11 @@
import codeql.ruby.AST
import codeql.ruby.security.CommandInjectionQuery
import DataFlow::PathGraph
import CommandInjectionFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, Source sourceNode
from CommandInjectionFlow::PathNode source, CommandInjectionFlow::PathNode sink, Source sourceNode
where
config.hasFlowPath(source, sink) and
CommandInjectionFlow::flowPath(source, sink) and
sourceNode = source.getNode()
select sink.getNode(), source, sink, "This command depends on a $@.", sourceNode,
sourceNode.getSourceType()

View File

@@ -16,33 +16,14 @@
*/
import codeql.ruby.DataFlow
import codeql.ruby.TaintTracking
import codeql.ruby.dataflow.RemoteFlowSources
import codeql.ruby.dataflow.BarrierGuards
import DataFlow::PathGraph
import codeql.ruby.security.KernelOpenQuery
class Configuration extends TaintTracking::Configuration {
Configuration() { this = "KernelOpen" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
sink = any(AmbiguousPathCall r).getPathArgument()
}
override predicate isSanitizer(DataFlow::Node node) {
node instanceof StringConstCompareBarrier or
node instanceof StringConstArrayInclusionCallBarrier or
node instanceof Sanitizer
}
}
import KernelOpenFlow::PathGraph
from
Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink,
DataFlow::Node sourceNode, DataFlow::CallNode call
KernelOpenFlow::PathNode source, KernelOpenFlow::PathNode sink, DataFlow::Node sourceNode,
DataFlow::CallNode call
where
config.hasFlowPath(source, sink) and
KernelOpenFlow::flowPath(source, sink) and
sourceNode = source.getNode() and
call.getArgument(0) = sink.getNode()
select sink.getNode(), source, sink,

View File

@@ -15,11 +15,13 @@
*/
import codeql.ruby.security.UnsafeShellCommandConstructionQuery
import DataFlow::PathGraph
import UnsafeShellCommandConstructionFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
from
UnsafeShellCommandConstructionFlow::PathNode source,
UnsafeShellCommandConstructionFlow::PathNode sink, Sink sinkNode
where
config.hasFlowPath(source, sink) and
UnsafeShellCommandConstructionFlow::flowPath(source, sink) and
sinkNode = sink.getNode()
select sinkNode.getStringConstruction(), source, sink,
"This " + sinkNode.describe() + " which depends on $@ is later used in a $@.", source.getNode(),

View File

@@ -15,9 +15,9 @@
import codeql.ruby.AST
import codeql.ruby.security.ReflectedXSSQuery
import DataFlow::PathGraph
import ReflectedXssFlow::PathGraph
from ReflectedXss::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from ReflectedXssFlow::PathNode source, ReflectedXssFlow::PathNode sink
where ReflectedXssFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Cross-site scripting vulnerability due to a $@.",
source.getNode(), "user-provided value"

View File

@@ -14,9 +14,9 @@
import codeql.ruby.AST
import codeql.ruby.security.StoredXSSQuery
import StoredXss::PathGraph
import StoredXssFlow::PathGraph
from StoredXss::PathNode source, StoredXss::PathNode sink
where StoredXss::flowPath(source, sink)
from StoredXssFlow::PathNode source, StoredXssFlow::PathNode sink
where StoredXssFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Stored cross-site scripting vulnerability due to $@.",
source.getNode(), "stored value"

View File

@@ -13,10 +13,12 @@
*/
import codeql.ruby.security.UnsafeHtmlConstructionQuery
import DataFlow::PathGraph
import UnsafeHtmlConstructionFlow::PathGraph
from DataFlow::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where cfg.hasFlowPath(source, sink) and sink.getNode() = sinkNode
from
UnsafeHtmlConstructionFlow::PathNode source, UnsafeHtmlConstructionFlow::PathNode sink,
Sink sinkNode
where UnsafeHtmlConstructionFlow::flowPath(source, sink) and sink.getNode() = sinkNode
select sinkNode, source, sink,
"This " + sinkNode.getSinkType() + " which depends on $@ might later allow $@.", source.getNode(),
"library input", sinkNode.getXssSink(), "cross-site scripting"

View File

@@ -13,9 +13,9 @@
import codeql.ruby.DataFlow
import codeql.ruby.security.SqlInjectionQuery
import DataFlow::PathGraph
import SqlInjectionFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from SqlInjectionFlow::PathNode source, SqlInjectionFlow::PathNode sink
where SqlInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This SQL query depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -14,21 +14,22 @@
* external/cwe/cwe-116
*/
import codeql.ruby.AST
import codeql.ruby.security.CodeInjectionQuery
import DataFlow::PathGraph
private import codeql.ruby.AST
private import codeql.ruby.security.CodeInjectionQuery
import CodeInjectionFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink, Source sourceNode
from CodeInjectionFlow::PathNode source, CodeInjectionFlow::PathNode sink, Source sourceNode
where
config.hasFlowPath(source, sink) and
CodeInjectionFlow::flowPath(source, sink) and
sourceNode = source.getNode() and
// removing duplications of the same path, but different flow-labels.
sink =
min(DataFlow::PathNode otherSink |
config.hasFlowPath(any(DataFlow::PathNode s | s.getNode() = sourceNode), otherSink) and
min(CodeInjectionFlow::PathNode otherSink |
CodeInjectionFlow::flowPath(any(CodeInjectionFlow::PathNode s | s.getNode() = sourceNode),
otherSink) and
otherSink.getNode() = sink.getNode()
|
otherSink order by otherSink.getState()
otherSink order by otherSink.getState().getStringRepresentation()
)
select sink.getNode(), source, sink, "This code execution depends on a $@.", sourceNode,
"user-provided value"

View File

@@ -14,10 +14,12 @@
*/
import codeql.ruby.security.UnsafeCodeConstructionQuery
import DataFlow::PathGraph
import UnsafeCodeConstructionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, Sink sinkNode
where cfg.hasFlowPath(source, sink) and sinkNode = sink.getNode()
from
UnsafeCodeConstructionFlow::PathNode source, UnsafeCodeConstructionFlow::PathNode sink,
Sink sinkNode
where UnsafeCodeConstructionFlow::flowPath(source, sink) and sinkNode = sink.getNode()
select sink.getNode(), source, sink,
"This " + sinkNode.getSinkType() + " which depends on $@ is later $@.", source.getNode(),
"library input", sinkNode.getCodeSink(), "interpreted as code"

View File

@@ -12,10 +12,10 @@
*/
import codeql.ruby.AST
import DataFlow::PathGraph
import codeql.ruby.security.LogInjectionQuery
import LogInjectionFlow::PathGraph
from LogInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from LogInjectionFlow::PathNode source, LogInjectionFlow::PathNode sink
where LogInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Log entry depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -13,18 +13,18 @@
* external/cwe/cwe-400
*/
import DataFlow::PathGraph
import codeql.ruby.DataFlow
import codeql.ruby.security.regexp.PolynomialReDoSCustomizations::PolynomialReDoS as PR
import codeql.ruby.security.regexp.PolynomialReDoSQuery
import PolynomialReDoSFlow::PathGraph
from
PolynomialReDoS::Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink,
PolynomialReDoS::Sink sinkNode, PolynomialReDoS::PolynomialBackTrackingTerm regexp
PolynomialReDoSFlow::PathNode source, PolynomialReDoSFlow::PathNode sink, PR::Sink sinkNode,
PR::PolynomialBackTrackingTerm regexp
where
config.hasFlowPath(source, sink) and
PolynomialReDoSFlow::flowPath(source, sink) and
sinkNode = sink.getNode() and
regexp = sinkNode.getRegExp()
select sinkNode.getHighlight(), source, sink,
"This $@ that depends on a $@ may run slow on strings " + regexp.getPrefixMessage() +
"with many repetitions of '" + regexp.getPumpString() + "'.", regexp, "regular expression",
source.getNode(), source.getNode().(PolynomialReDoS::Source).describe()
source.getNode(), source.getNode().(PR::Source).describe()

View File

@@ -15,12 +15,10 @@
* external/cwe/cwe-400
*/
import codeql.ruby.AST
import DataFlow::PathGraph
import codeql.ruby.DataFlow
import codeql.ruby.security.regexp.RegExpInjectionQuery
import RegExpInjectionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from RegExpInjectionFlow::PathNode source, RegExpInjectionFlow::PathNode sink
where RegExpInjectionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This regular expression depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -15,9 +15,9 @@
import codeql.ruby.DataFlow
import codeql.ruby.security.StackTraceExposureQuery
import DataFlow::PathGraph
import StackTraceExposureFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from StackTraceExposureFlow::PathNode source, StackTraceExposureFlow::PathNode sink
where StackTraceExposureFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "$@ can be exposed to an external user.", source.getNode(),
"Error information"

View File

@@ -15,10 +15,9 @@
import codeql.ruby.AST
import codeql.ruby.security.CleartextLoggingQuery
import codeql.ruby.DataFlow
import DataFlow::PathGraph
import CleartextLoggingFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from CleartextLoggingFlow::PathNode source, CleartextLoggingFlow::PathNode sink
where CleartextLoggingFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This logs sensitive data returned by $@ as clear text.",
source.getNode(), source.getNode().(Source).describe()

View File

@@ -16,10 +16,9 @@
import codeql.ruby.AST
import codeql.ruby.security.CleartextStorageQuery
import codeql.ruby.security.CleartextStorageCustomizations::CleartextStorage
import codeql.ruby.DataFlow
import DataFlow::PathGraph
import CleartextStorageFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from CleartextStorageFlow::PathNode source, CleartextStorageFlow::PathNode sink
where CleartextStorageFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "This stores sensitive data returned by $@ as clear text.",
source.getNode(), source.getNode().(Source).describe()

View File

@@ -13,9 +13,9 @@
import ruby
import codeql.ruby.security.UnsafeDeserializationQuery
import DataFlow::PathGraph
import UnsafeCodeConstructionFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from UnsafeCodeConstructionFlow::PathNode source, UnsafeCodeConstructionFlow::PathNode sink
where UnsafeCodeConstructionFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Unsafe deserialization depends on a $@.", source.getNode(),
source.getNode().(UnsafeDeserialization::Source).describe()

View File

@@ -12,12 +12,13 @@
* external/cwe/cwe-506
*/
import codeql.ruby.security.HardcodedDataInterpretedAsCodeQuery
import codeql.ruby.DataFlow
import DataFlow::PathGraph
private import codeql.ruby.security.HardcodedDataInterpretedAsCodeQuery
import HardcodedDataInterpretedAsCodeFlow::PathGraph
from Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
from
HardcodedDataInterpretedAsCodeFlow::PathNode source,
HardcodedDataInterpretedAsCodeFlow::PathNode sink
where HardcodedDataInterpretedAsCodeFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"$@ is interpreted as " + sink.getNode().(Sink).getKind() + ".", source.getNode(),
"Hard-coded data"

View File

@@ -13,9 +13,10 @@
import ruby
import codeql.ruby.security.SensitiveGetQueryQuery
import codeql.ruby.security.SensitiveGetQueryCustomizations::SensitiveGetQuery
import codeql.ruby.security.SensitiveActions
from DataFlow::Node source, DataFlow::Node sink, SensitiveGetQuery::Configuration config
where config.hasFlow(source, sink)
select source, "$@ for GET requests uses query parameter as sensitive data.",
source.(SensitiveGetQuery::Source).getHandler(), "Route handler"
from Source source, DataFlow::Node sink
where SensitiveGetQueryFlow::flow(source, sink)
select source, "$@ for GET requests uses query parameter as sensitive data.", source.getHandler(),
"Route handler"

View File

@@ -12,11 +12,10 @@
* @precision high
*/
import codeql.ruby.AST
import codeql.ruby.security.UrlRedirectQuery
import codeql.ruby.DataFlow::DataFlow::PathGraph
import UrlRedirectFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from UrlRedirectFlow::PathNode source, UrlRedirectFlow::PathNode sink
where UrlRedirectFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "Untrusted URL redirection depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -13,12 +13,10 @@
* external/cwe/cwe-827
*/
import codeql.ruby.AST
import codeql.ruby.dataflow.RemoteFlowSources
import codeql.ruby.TaintTracking
import codeql.ruby.Concepts
import codeql.ruby.DataFlow
import DataFlow::PathGraph
class UnsafeXxeSink extends DataFlow::ExprNode {
UnsafeXxeSink() {
@@ -29,16 +27,18 @@ class UnsafeXxeSink extends DataFlow::ExprNode {
}
}
class XxeConfig extends TaintTracking::Configuration {
XxeConfig() { this = "XXE.ql::XxeConfig" }
private module XxeConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeXxeSink }
predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeXxeSink }
}
from DataFlow::PathNode source, DataFlow::PathNode sink, XxeConfig conf
where conf.hasFlowPath(source, sink)
private module XxeFlow = TaintTracking::Global<XxeConfig>;
import XxeFlow::PathGraph
from XxeFlow::PathNode source, XxeFlow::PathNode sink
where XxeFlow::flowPath(source, sink)
select sink.getNode(), source, sink,
"XML parsing depends on a $@ without guarding against external entity expansion.",
source.getNode(), "user-provided value"

View File

@@ -13,7 +13,6 @@
import codeql.ruby.AST
import codeql.ruby.Concepts
import codeql.ruby.DataFlow
import DataFlow::PathGraph
import codeql.ruby.ApiGraphs
bindingset[p]
@@ -47,22 +46,25 @@ class PermissivePermissionsExpr extends Expr {
}
}
class PermissivePermissionsConfig extends DataFlow::Configuration {
PermissivePermissionsConfig() { this = "PermissivePermissionsConfig" }
override predicate isSource(DataFlow::Node source) {
private module PermissivePermissionsConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) {
source.asExpr().getExpr() instanceof PermissivePermissionsExpr
}
override predicate isSink(DataFlow::Node sink) {
predicate isSink(DataFlow::Node sink) {
exists(FileSystemPermissionModification mod | mod.getAPermissionNode() = sink)
}
}
private module PermissivePermissionsFlow = DataFlow::Global<PermissivePermissionsConfig>;
import PermissivePermissionsFlow::PathGraph
from
DataFlow::PathNode source, DataFlow::PathNode sink, PermissivePermissionsConfig conf,
PermissivePermissionsFlow::PathNode source, PermissivePermissionsFlow::PathNode sink,
FileSystemPermissionModification mod
where conf.hasFlowPath(source, sink) and mod.getAPermissionNode() = sink.getNode()
where
PermissivePermissionsFlow::flowPath(source, sink) and mod.getAPermissionNode() = sink.getNode()
select source.getNode(), source, sink,
"This overly permissive mask used in $@ allows read or write access to others.", mod,
mod.toString()

View File

@@ -14,7 +14,6 @@
import codeql.ruby.AST
import codeql.ruby.DataFlow
import DataFlow::PathGraph
import codeql.ruby.TaintTracking
import codeql.ruby.controlflow.CfgNodes
@@ -132,14 +131,12 @@ class CredentialSink extends DataFlow::Node {
CredentialSink() { isCredentialSink(this) }
}
class HardcodedCredentialsConfiguration extends DataFlow::Configuration {
HardcodedCredentialsConfiguration() { this = "HardcodedCredentialsConfiguration" }
private module HardcodedCredentialsConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof HardcodedValueSource }
override predicate isSource(DataFlow::Node source) { source instanceof HardcodedValueSource }
predicate isSink(DataFlow::Node sink) { sink instanceof CredentialSink }
override predicate isSink(DataFlow::Node sink) { sink instanceof CredentialSink }
override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
exists(ExprNodes::BinaryOperationCfgNode binop |
(
binop.getLeftOperand() = node1.asExpr() or
@@ -152,7 +149,11 @@ class HardcodedCredentialsConfiguration extends DataFlow::Configuration {
}
}
from DataFlow::PathNode source, DataFlow::PathNode sink, HardcodedCredentialsConfiguration conf
where conf.hasFlowPath(source, sink)
private module HardcodedCredentialsFlow = DataFlow::Global<HardcodedCredentialsConfig>;
import HardcodedCredentialsFlow::PathGraph
from HardcodedCredentialsFlow::PathNode source, HardcodedCredentialsFlow::PathNode sink
where HardcodedCredentialsFlow::flowPath(source, sink)
select source.getNode(), source, sink, "This hardcoded value is $@.", sink.getNode(),
"used as credentials"

View File

@@ -11,12 +11,10 @@
* external/cwe/cwe-829
*/
import codeql.ruby.AST
import codeql.ruby.DataFlow
import codeql.ruby.security.InsecureDownloadQuery
import Flow::PathGraph
import InsecureDownloadFlow::PathGraph
from Flow::PathNode source, Flow::PathNode sink
where Flow::flowPath(source, sink)
from InsecureDownloadFlow::PathNode source, InsecureDownloadFlow::PathNode sink
where InsecureDownloadFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "$@ of sensitive file from $@.",
sink.getNode().(Sink).getDownloadCall(), "Download", source.getNode(), "HTTP source"

View File

@@ -13,9 +13,9 @@
import codeql.ruby.AST
import codeql.ruby.DataFlow
import codeql.ruby.security.ServerSideRequestForgeryQuery
import DataFlow::PathGraph
import ServerSideRequestForgeryFlow::PathGraph
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
from ServerSideRequestForgeryFlow::PathNode source, ServerSideRequestForgeryFlow::PathNode sink
where ServerSideRequestForgeryFlow::flowPath(source, sink)
select sink.getNode(), source, sink, "The URL of this request depends on a $@.", source.getNode(),
"user-provided value"

View File

@@ -2,43 +2,55 @@ edges
| zip_slip.rb:8:5:8:11 | tarfile | zip_slip.rb:9:5:9:11 | tarfile |
| zip_slip.rb:8:15:8:54 | call to new | zip_slip.rb:8:5:8:11 | tarfile |
| zip_slip.rb:9:5:9:11 | tarfile | zip_slip.rb:9:22:9:26 | entry |
| zip_slip.rb:9:22:9:26 | entry | zip_slip.rb:10:19:10:33 | call to full_name |
| zip_slip.rb:9:22:9:26 | entry | zip_slip.rb:10:19:10:23 | entry |
| zip_slip.rb:10:19:10:23 | entry | zip_slip.rb:10:19:10:33 | call to full_name |
| zip_slip.rb:20:50:20:56 | tarfile | zip_slip.rb:21:7:21:13 | tarfile |
| zip_slip.rb:21:7:21:13 | tarfile | zip_slip.rb:21:30:21:34 | entry |
| zip_slip.rb:21:30:21:34 | entry | zip_slip.rb:22:21:22:35 | call to full_name |
| zip_slip.rb:21:30:21:34 | entry | zip_slip.rb:22:21:22:25 | entry |
| zip_slip.rb:22:21:22:25 | entry | zip_slip.rb:22:21:22:35 | call to full_name |
| zip_slip.rb:46:5:46:24 | call to open | zip_slip.rb:46:35:46:39 | entry |
| zip_slip.rb:46:35:46:39 | entry | zip_slip.rb:47:17:47:26 | call to name |
| zip_slip.rb:46:35:46:39 | entry | zip_slip.rb:47:17:47:21 | entry |
| zip_slip.rb:47:17:47:21 | entry | zip_slip.rb:47:17:47:26 | call to name |
| zip_slip.rb:56:30:56:37 | zip_file | zip_slip.rb:57:7:57:14 | zip_file |
| zip_slip.rb:57:7:57:14 | zip_file | zip_slip.rb:57:25:57:29 | entry |
| zip_slip.rb:57:25:57:29 | entry | zip_slip.rb:58:19:58:28 | call to name |
| zip_slip.rb:57:25:57:29 | entry | zip_slip.rb:58:19:58:23 | entry |
| zip_slip.rb:58:19:58:23 | entry | zip_slip.rb:58:19:58:28 | call to name |
| zip_slip.rb:90:5:90:8 | gzip | zip_slip.rb:91:11:91:14 | gzip |
| zip_slip.rb:90:12:90:54 | call to open | zip_slip.rb:90:5:90:8 | gzip |
| zip_slip.rb:91:11:91:14 | gzip | zip_slip.rb:97:42:97:56 | compressed_file |
| zip_slip.rb:97:42:97:56 | compressed_file | zip_slip.rb:98:7:98:21 | compressed_file |
| zip_slip.rb:98:7:98:21 | compressed_file | zip_slip.rb:98:32:98:36 | entry |
| zip_slip.rb:98:32:98:36 | entry | zip_slip.rb:99:9:99:18 | entry_path |
| zip_slip.rb:98:32:98:36 | entry | zip_slip.rb:99:22:99:26 | entry |
| zip_slip.rb:99:9:99:18 | entry_path | zip_slip.rb:100:21:100:30 | entry_path |
| zip_slip.rb:99:22:99:26 | entry | zip_slip.rb:99:22:99:36 | call to full_name |
| zip_slip.rb:99:22:99:36 | call to full_name | zip_slip.rb:99:9:99:18 | entry_path |
| zip_slip.rb:123:7:123:8 | gz | zip_slip.rb:124:7:124:8 | gz |
| zip_slip.rb:123:12:123:34 | call to new | zip_slip.rb:123:7:123:8 | gz |
| zip_slip.rb:124:7:124:8 | gz | zip_slip.rb:124:19:124:23 | entry |
| zip_slip.rb:124:19:124:23 | entry | zip_slip.rb:125:9:125:18 | entry_path |
| zip_slip.rb:124:19:124:23 | entry | zip_slip.rb:125:22:125:26 | entry |
| zip_slip.rb:125:9:125:18 | entry_path | zip_slip.rb:126:21:126:30 | entry_path |
| zip_slip.rb:125:22:125:26 | entry | zip_slip.rb:125:22:125:36 | call to full_name |
| zip_slip.rb:125:22:125:36 | call to full_name | zip_slip.rb:125:9:125:18 | entry_path |
nodes
| zip_slip.rb:8:5:8:11 | tarfile | semmle.label | tarfile |
| zip_slip.rb:8:15:8:54 | call to new | semmle.label | call to new |
| zip_slip.rb:9:5:9:11 | tarfile | semmle.label | tarfile |
| zip_slip.rb:9:22:9:26 | entry | semmle.label | entry |
| zip_slip.rb:10:19:10:23 | entry | semmle.label | entry |
| zip_slip.rb:10:19:10:33 | call to full_name | semmle.label | call to full_name |
| zip_slip.rb:20:50:20:56 | tarfile | semmle.label | tarfile |
| zip_slip.rb:21:7:21:13 | tarfile | semmle.label | tarfile |
| zip_slip.rb:21:30:21:34 | entry | semmle.label | entry |
| zip_slip.rb:22:21:22:25 | entry | semmle.label | entry |
| zip_slip.rb:22:21:22:35 | call to full_name | semmle.label | call to full_name |
| zip_slip.rb:46:5:46:24 | call to open | semmle.label | call to open |
| zip_slip.rb:46:35:46:39 | entry | semmle.label | entry |
| zip_slip.rb:47:17:47:21 | entry | semmle.label | entry |
| zip_slip.rb:47:17:47:26 | call to name | semmle.label | call to name |
| zip_slip.rb:56:30:56:37 | zip_file | semmle.label | zip_file |
| zip_slip.rb:57:7:57:14 | zip_file | semmle.label | zip_file |
| zip_slip.rb:57:25:57:29 | entry | semmle.label | entry |
| zip_slip.rb:58:19:58:23 | entry | semmle.label | entry |
| zip_slip.rb:58:19:58:28 | call to name | semmle.label | call to name |
| zip_slip.rb:90:5:90:8 | gzip | semmle.label | gzip |
| zip_slip.rb:90:12:90:54 | call to open | semmle.label | call to open |
@@ -47,12 +59,16 @@ nodes
| zip_slip.rb:98:7:98:21 | compressed_file | semmle.label | compressed_file |
| zip_slip.rb:98:32:98:36 | entry | semmle.label | entry |
| zip_slip.rb:99:9:99:18 | entry_path | semmle.label | entry_path |
| zip_slip.rb:99:22:99:26 | entry | semmle.label | entry |
| zip_slip.rb:99:22:99:36 | call to full_name | semmle.label | call to full_name |
| zip_slip.rb:100:21:100:30 | entry_path | semmle.label | entry_path |
| zip_slip.rb:123:7:123:8 | gz | semmle.label | gz |
| zip_slip.rb:123:12:123:34 | call to new | semmle.label | call to new |
| zip_slip.rb:124:7:124:8 | gz | semmle.label | gz |
| zip_slip.rb:124:19:124:23 | entry | semmle.label | entry |
| zip_slip.rb:125:9:125:18 | entry_path | semmle.label | entry_path |
| zip_slip.rb:125:22:125:26 | entry | semmle.label | entry |
| zip_slip.rb:125:22:125:36 | call to full_name | semmle.label | call to full_name |
| zip_slip.rb:126:21:126:30 | entry_path | semmle.label | entry_path |
subpaths
#select

View File

@@ -9,9 +9,9 @@ edges
| app/controllers/foo/bars_controller.rb:17:21:17:26 | call to params | app/controllers/foo/bars_controller.rb:17:21:17:36 | ...[...] |
| app/controllers/foo/bars_controller.rb:17:21:17:36 | ...[...] | app/views/foo/bars/show.html.erb:2:18:2:30 | @user_website |
| app/controllers/foo/bars_controller.rb:18:5:18:6 | dt | app/controllers/foo/bars_controller.rb:19:22:19:23 | dt |
| app/controllers/foo/bars_controller.rb:18:5:18:6 | dt | app/controllers/foo/bars_controller.rb:26:53:26:54 | dt |
| app/controllers/foo/bars_controller.rb:18:10:18:15 | call to params | app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] |
| app/controllers/foo/bars_controller.rb:18:10:18:22 | ...[...] | app/controllers/foo/bars_controller.rb:18:5:18:6 | dt |
| app/controllers/foo/bars_controller.rb:19:22:19:23 | dt | app/controllers/foo/bars_controller.rb:26:53:26:54 | dt |
| app/controllers/foo/bars_controller.rb:19:22:19:23 | dt | app/views/foo/bars/show.html.erb:40:3:40:16 | @instance_text |
| app/controllers/foo/bars_controller.rb:24:39:24:44 | call to params | app/controllers/foo/bars_controller.rb:24:39:24:59 | ...[...] |
| app/controllers/foo/bars_controller.rb:24:39:24:59 | ...[...] | app/controllers/foo/bars_controller.rb:24:39:24:59 | ... = ... |

View File

@@ -10,7 +10,8 @@ edges
| UrlRedirect.rb:63:38:63:43 | call to params | UrlRedirect.rb:63:38:63:49 | ...[...] |
| UrlRedirect.rb:68:38:68:43 | call to params | UrlRedirect.rb:68:38:68:49 | ...[...] |
| UrlRedirect.rb:73:25:73:30 | call to params | UrlRedirect.rb:73:25:73:36 | ...[...] |
| UrlRedirect.rb:93:21:93:32 | input_params | UrlRedirect.rb:94:5:94:29 | call to permit |
| UrlRedirect.rb:93:21:93:32 | input_params | UrlRedirect.rb:94:5:94:16 | input_params |
| UrlRedirect.rb:94:5:94:16 | input_params | UrlRedirect.rb:94:5:94:29 | call to permit |
nodes
| UrlRedirect.rb:4:17:4:22 | call to params | semmle.label | call to params |
| UrlRedirect.rb:9:17:9:22 | call to params | semmle.label | call to params |
@@ -33,6 +34,7 @@ nodes
| UrlRedirect.rb:73:25:73:30 | call to params | semmle.label | call to params |
| UrlRedirect.rb:73:25:73:36 | ...[...] | semmle.label | ...[...] |
| UrlRedirect.rb:93:21:93:32 | input_params | semmle.label | input_params |
| UrlRedirect.rb:94:5:94:16 | input_params | semmle.label | input_params |
| UrlRedirect.rb:94:5:94:29 | call to permit | semmle.label | call to permit |
subpaths
| UrlRedirect.rb:24:31:24:36 | call to params | UrlRedirect.rb:93:21:93:32 | input_params | UrlRedirect.rb:94:5:94:29 | call to permit | UrlRedirect.rb:24:17:24:37 | call to filter_params |

View File

@@ -3,11 +3,14 @@ edges
| HardcodedCredentials.rb:15:30:15:75 | "WLC17dLQ9P8YlQvqm77qplOMm5pd1..." | HardcodedCredentials.rb:1:33:1:36 | cert |
| HardcodedCredentials.rb:18:19:18:72 | ... + ... | HardcodedCredentials.rb:1:23:1:30 | password |
| HardcodedCredentials.rb:18:27:18:72 | "ogH6qSYWGdbR/2WOGYa7eZ/tObL+G..." | HardcodedCredentials.rb:18:19:18:72 | ... + ... |
| HardcodedCredentials.rb:20:1:20:7 | pw_left | HardcodedCredentials.rb:22:1:22:2 | pw |
| HardcodedCredentials.rb:20:1:20:7 | pw_left | HardcodedCredentials.rb:22:6:22:12 | pw_left |
| HardcodedCredentials.rb:20:11:20:76 | "3jOe7sXKX6Tx52qHWUVqh2t9LNsE+..." | HardcodedCredentials.rb:20:1:20:7 | pw_left |
| HardcodedCredentials.rb:21:1:21:8 | pw_right | HardcodedCredentials.rb:22:1:22:2 | pw |
| HardcodedCredentials.rb:21:1:21:8 | pw_right | HardcodedCredentials.rb:22:16:22:23 | pw_right |
| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" | HardcodedCredentials.rb:21:1:21:8 | pw_right |
| HardcodedCredentials.rb:22:1:22:2 | pw | HardcodedCredentials.rb:23:19:23:20 | pw |
| HardcodedCredentials.rb:22:6:22:12 | pw_left | HardcodedCredentials.rb:22:6:22:23 | ... + ... |
| HardcodedCredentials.rb:22:6:22:23 | ... + ... | HardcodedCredentials.rb:22:1:22:2 | pw |
| HardcodedCredentials.rb:22:16:22:23 | pw_right | HardcodedCredentials.rb:22:6:22:23 | ... + ... |
| HardcodedCredentials.rb:23:19:23:20 | pw | HardcodedCredentials.rb:1:23:1:30 | password |
| HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." | HardcodedCredentials.rb:31:18:31:23 | passwd |
| HardcodedCredentials.rb:43:29:43:43 | "user@test.com" | HardcodedCredentials.rb:43:18:43:25 | username |
@@ -27,6 +30,9 @@ nodes
| HardcodedCredentials.rb:21:1:21:8 | pw_right | semmle.label | pw_right |
| HardcodedCredentials.rb:21:12:21:37 | "4fQuzXef4f2yow8KWvIJTA==" | semmle.label | "4fQuzXef4f2yow8KWvIJTA==" |
| HardcodedCredentials.rb:22:1:22:2 | pw | semmle.label | pw |
| HardcodedCredentials.rb:22:6:22:12 | pw_left | semmle.label | pw_left |
| HardcodedCredentials.rb:22:6:22:23 | ... + ... | semmle.label | ... + ... |
| HardcodedCredentials.rb:22:16:22:23 | pw_right | semmle.label | pw_right |
| HardcodedCredentials.rb:23:19:23:20 | pw | semmle.label | pw |
| HardcodedCredentials.rb:31:18:31:23 | passwd | semmle.label | passwd |
| HardcodedCredentials.rb:38:40:38:85 | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." | semmle.label | "kdW/xVhiv6y1fQQNevDpUaq+2rfPK..." |

View File

@@ -1,7 +1,5 @@
import codeql.ruby.AST
import codeql.ruby.DataFlow
import codeql.ruby.security.InsecureDownloadQuery
import Flow::PathGraph
import InsecureDownloadFlow::PathGraph
import TestUtilities.InlineExpectationsTest
import TestUtilities.InlineFlowTestUtil
@@ -10,7 +8,7 @@ module FlowTest implements TestSig {
predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "BAD" and
exists(DataFlow::Node src, DataFlow::Node sink | Flow::flow(src, sink) |
exists(DataFlow::Node src, DataFlow::Node sink | InsecureDownloadFlow::flow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
if exists(getSourceArgString(src)) then value = getSourceArgString(src) else value = ""
@@ -20,6 +18,6 @@ module FlowTest implements TestSig {
import MakeTest<FlowTest>
from Flow::PathNode source, Flow::PathNode sink
where Flow::flowPath(source, sink)
from InsecureDownloadFlow::PathNode source, InsecureDownloadFlow::PathNode sink
where InsecureDownloadFlow::flowPath(source, sink)
select sink, source, sink, "$@", source, source.toString()