mirror of
https://github.com/github/codeql.git
synced 2026-04-28 10:15:14 +02:00
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:
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -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>;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Built-in Ruby queries now use the new DataFlow API.
|
||||
@@ -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"
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 | ... = ... |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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..." |
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user