mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #20622 from owen-mc/docs/fix-dataflow-examples
Docs: add path query example to data flow docs
This commit is contained in:
@@ -314,7 +314,7 @@ Exercise 2: Write a query that finds all hard-coded strings used to create a ``h
|
|||||||
|
|
||||||
Exercise 3: Write a class that represents flow sources from ``getenv``. (`Answer <#exercise-3>`__)
|
Exercise 3: Write a class that represents flow sources from ``getenv``. (`Answer <#exercise-3>`__)
|
||||||
|
|
||||||
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from ``getenv`` to ``gethostbyname``. (`Answer <#exercise-4>`__)
|
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from ``getenv`` to ``gethostbyname``. (`Answer <#exercise-4>`__ `Answer as a path query <#path-query-example>`__)
|
||||||
|
|
||||||
Answers
|
Answers
|
||||||
-------
|
-------
|
||||||
@@ -411,6 +411,48 @@ Exercise 4
|
|||||||
GetenvToGethostbynameFlow::flow(source, sink)
|
GetenvToGethostbynameFlow::flow(source, sink)
|
||||||
select getenv, fc
|
select getenv, fc
|
||||||
|
|
||||||
|
Path query example
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Here is the answer to exercise 4 above, converted into a path query:
|
||||||
|
|
||||||
|
.. code-block:: ql
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id getenv-to-gethostbyname
|
||||||
|
*/
|
||||||
|
|
||||||
|
import cpp
|
||||||
|
import semmle.code.cpp.dataflow.new.DataFlow
|
||||||
|
|
||||||
|
class GetenvSource extends DataFlow::Node {
|
||||||
|
GetenvSource() { this.asIndirectExpr(1).(FunctionCall).getTarget().hasGlobalName("getenv") }
|
||||||
|
}
|
||||||
|
|
||||||
|
module GetenvToGethostbynameConfiguration implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) { source instanceof GetenvSource }
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
exists(FunctionCall fc |
|
||||||
|
sink.asIndirectExpr(1) = fc.getArgument(0) and
|
||||||
|
fc.getTarget().hasName("gethostbyname")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module GetenvToGethostbynameFlow = DataFlow::Global<GetenvToGethostbynameConfiguration>;
|
||||||
|
|
||||||
|
import GetenvToGethostbynameFlow::PathGraph
|
||||||
|
|
||||||
|
from GetenvToGethostbynameFlow::PathNode source, GetenvToGethostbynameFlow::PathNode sink
|
||||||
|
where GetenvToGethostbynameFlow::flowPath(source, sink)
|
||||||
|
select sink.getNode(), source, sink, "This file access uses data from $@.",
|
||||||
|
source, "user-controllable input."
|
||||||
|
|
||||||
|
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ Exercise 2: Find all hard-coded strings passed to ``System.Uri``, using global d
|
|||||||
|
|
||||||
Exercise 3: Define a class that represents flow sources from ``System.Environment.GetEnvironmentVariable``. (`Answer <#exercise-3>`__)
|
Exercise 3: Define a class that represents flow sources from ``System.Environment.GetEnvironmentVariable``. (`Answer <#exercise-3>`__)
|
||||||
|
|
||||||
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from ``System.Environment.GetEnvironmentVariable`` to ``System.Uri``. (`Answer <#exercise-4>`__)
|
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from ``System.Environment.GetEnvironmentVariable`` to ``System.Uri``. (`Answer <#exercise-4>`__ `Answer as a path query <#path-query-example>`__)
|
||||||
|
|
||||||
Extending library data flow
|
Extending library data flow
|
||||||
---------------------------
|
---------------------------
|
||||||
@@ -537,6 +537,48 @@ This can be adapted from the ``SystemUriFlow`` class:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Path query example
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Here is the answer to exercise 4 above, converted into a path query:
|
||||||
|
|
||||||
|
.. code-block:: ql
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id getenv-to-gethostbyname
|
||||||
|
*/
|
||||||
|
|
||||||
|
import csharp
|
||||||
|
|
||||||
|
class EnvironmentVariableFlowSource extends DataFlow::ExprNode {
|
||||||
|
EnvironmentVariableFlowSource() {
|
||||||
|
this.getExpr().(MethodCall).getTarget().hasQualifiedName("System.Environment.GetEnvironmentVariable")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module EnvironmentToUriConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node src) {
|
||||||
|
src instanceof EnvironmentVariableFlowSource
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
exists(Call c | c.getTarget().(Constructor).getDeclaringType().hasQualifiedName("System.Uri")
|
||||||
|
and sink.asExpr()=c.getArgument(0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module EnvironmentToUriFlow = DataFlow::Global<EnvironmentToUriConfig>;
|
||||||
|
|
||||||
|
import EnvironmentToUriFlow::PathGraph
|
||||||
|
|
||||||
|
from EnvironmentToUriFlow::PathNode src, EnvironmentToUriFlow::PathNode sink
|
||||||
|
where EnvironmentToUriFlow::flowPath(src, sink)
|
||||||
|
select src.getNode(), src, sink, "This environment variable constructs a 'System.Uri' $@.", sink, "here"
|
||||||
|
|
||||||
|
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ The resulting module has an identical signature to the one obtained from ``DataF
|
|||||||
Flow sources
|
Flow sources
|
||||||
~~~~~~~~~~~~
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
The data flow library contains some predefined flow sources. The class ``RemoteFlowSource`` (defined in ``semmle.code.java.dataflow.FlowSources``) represents data flow sources that may be controlled by a remote user, which is useful for finding security problems.
|
The data flow library contains some predefined flow sources. The class ``RemoteFlowSource`` represents data flow sources that may be controlled by a remote user, which is useful for finding security problems.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
~~~~~~~~
|
~~~~~~~~
|
||||||
@@ -252,7 +252,7 @@ Exercise 2: Write a query that finds all hard-coded strings used to create a ``u
|
|||||||
|
|
||||||
Exercise 3: Write a class that represents flow sources from ``os.Getenv(..)``. (`Answer <#exercise-3>`__)
|
Exercise 3: Write a class that represents flow sources from ``os.Getenv(..)``. (`Answer <#exercise-3>`__)
|
||||||
|
|
||||||
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from ``os.Getenv`` to ``url.URL``. (`Answer <#exercise-4>`__)
|
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from ``os.Getenv`` to ``url.URL``. (`Answer <#exercise-4>`__ `Answer as a path query <#path-query-example>`__)
|
||||||
|
|
||||||
Answers
|
Answers
|
||||||
-------
|
-------
|
||||||
@@ -312,7 +312,7 @@ Exercise 3
|
|||||||
|
|
||||||
import go
|
import go
|
||||||
|
|
||||||
class GetenvSource extends CallExpr {
|
class GetenvSource extends DataFlow::CallNode {
|
||||||
GetenvSource() {
|
GetenvSource() {
|
||||||
exists(Function m | m = this.getTarget() |
|
exists(Function m | m = this.getTarget() |
|
||||||
m.hasQualifiedName("os", "Getenv")
|
m.hasQualifiedName("os", "Getenv")
|
||||||
@@ -327,7 +327,7 @@ Exercise 4
|
|||||||
|
|
||||||
import go
|
import go
|
||||||
|
|
||||||
class GetenvSource extends CallExpr {
|
class GetenvSource extends DataFlow::CallNode {
|
||||||
GetenvSource() {
|
GetenvSource() {
|
||||||
exists(Function m | m = this.getTarget() |
|
exists(Function m | m = this.getTarget() |
|
||||||
m.hasQualifiedName("os", "Getenv")
|
m.hasQualifiedName("os", "Getenv")
|
||||||
@@ -350,7 +350,6 @@ Exercise 4
|
|||||||
sink.asExpr() = call.getArgument(0)
|
sink.asExpr() = call.getArgument(0)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module GetenvToURLFlow = DataFlow::Global<GetenvToURLConfig>;
|
module GetenvToURLFlow = DataFlow::Global<GetenvToURLConfig>;
|
||||||
@@ -359,6 +358,56 @@ Exercise 4
|
|||||||
where GetenvToURLFlow::flow(src, sink)
|
where GetenvToURLFlow::flow(src, sink)
|
||||||
select src, "This environment variable constructs a URL $@.", sink, "here"
|
select src, "This environment variable constructs a URL $@.", sink, "here"
|
||||||
|
|
||||||
|
Path query example
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Here is the answer to exercise 4 above, converted into a path query:
|
||||||
|
|
||||||
|
.. code-block:: ql
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id getenv-to-url
|
||||||
|
*/
|
||||||
|
|
||||||
|
import go
|
||||||
|
|
||||||
|
class GetenvSource extends DataFlow::CallNode {
|
||||||
|
GetenvSource() {
|
||||||
|
exists(Function m | m = this.getTarget() |
|
||||||
|
m.hasQualifiedName("os", "Getenv")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module GetenvToURLConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
source instanceof GetenvSource
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
exists(Function urlParse, CallExpr call |
|
||||||
|
(
|
||||||
|
urlParse.hasQualifiedName("url", "Parse") or
|
||||||
|
urlParse.hasQualifiedName("url", "ParseRequestURI")
|
||||||
|
) and
|
||||||
|
call.getTarget() = urlParse and
|
||||||
|
sink.asExpr() = call.getArgument(0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module GetenvToURLFlow = DataFlow::Global<GetenvToURLConfig>;
|
||||||
|
|
||||||
|
import GetenvToURLFlow::PathGraph
|
||||||
|
|
||||||
|
from GetenvToURLFlow::PathNode src, GetenvToURLFlow::PathNode sink
|
||||||
|
where GetenvToURLFlow::flowPath(src, sink)
|
||||||
|
select src.getNode(), src, sink, "This environment variable constructs a URL $@.", sink, "here"
|
||||||
|
|
||||||
|
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ Exercise 2: Write a query that finds all hard-coded strings used to create a ``j
|
|||||||
|
|
||||||
Exercise 3: Write a class that represents flow sources from ``java.lang.System.getenv(..)``. (`Answer <#exercise-3>`__)
|
Exercise 3: Write a class that represents flow sources from ``java.lang.System.getenv(..)``. (`Answer <#exercise-3>`__)
|
||||||
|
|
||||||
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from ``getenv`` to ``java.net.URL``. (`Answer <#exercise-4>`__)
|
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from ``getenv`` to ``java.net.URL``. (`Answer <#exercise-4>`__ `Answer as a path query <#path-query-example>`__)
|
||||||
|
|
||||||
Answers
|
Answers
|
||||||
-------
|
-------
|
||||||
@@ -361,6 +361,54 @@ Exercise 4
|
|||||||
where GetenvToURLFlow::flow(src, sink)
|
where GetenvToURLFlow::flow(src, sink)
|
||||||
select src, "This environment variable constructs a URL $@.", sink, "here"
|
select src, "This environment variable constructs a URL $@.", sink, "here"
|
||||||
|
|
||||||
|
Path query example
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Here is the answer to exercise 4 above, converted into a path query:
|
||||||
|
|
||||||
|
.. code-block:: ql
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id getenv-to-url
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
import semmle.code.java.dataflow.DataFlow
|
||||||
|
|
||||||
|
class GetenvSource extends DataFlow::ExprNode {
|
||||||
|
GetenvSource() {
|
||||||
|
exists(Method m | m = this.asExpr().(MethodCall).getMethod() |
|
||||||
|
m.hasName("getenv") and
|
||||||
|
m.getDeclaringType() instanceof TypeSystem
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module GetenvToURLConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
source instanceof GetenvSource
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
exists(Call call |
|
||||||
|
sink.asExpr() = call.getArgument(0) and
|
||||||
|
call.getCallee().(Constructor).getDeclaringType().hasQualifiedName("java.net", "URL")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module GetenvToURLFlow = DataFlow::Global<GetenvToURLConfig>;
|
||||||
|
|
||||||
|
import GetenvToURLFlow::PathGraph
|
||||||
|
|
||||||
|
from GetenvToURLFlow::PathNode src, GetenvToURLFlow::PathNode sink
|
||||||
|
where GetenvToURLFlow::flowPath(src, sink)
|
||||||
|
select src.getNode(), src, sink, "This environment variable constructs a URL $@.", sink, "here"
|
||||||
|
|
||||||
|
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|||||||
@@ -456,7 +456,7 @@ Exercise 3: Write a class which represents flow sources from the array elements
|
|||||||
Hint: array indices are properties with numeric names; you can use regular expression matching to check this. (`Answer <#exercise-3>`__)
|
Hint: array indices are properties with numeric names; you can use regular expression matching to check this. (`Answer <#exercise-3>`__)
|
||||||
|
|
||||||
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from array elements of the result of a call to the ``tagName`` argument to the
|
Exercise 4: Using the answers from 2 and 3, write a query which finds all global data flow paths from array elements of the result of a call to the ``tagName`` argument to the
|
||||||
``createElement`` function. (`Answer <#exercise-4>`__)
|
``createElement`` function. (`Answer <#exercise-4>`__ `Answer as a path query <#path-query-example>`__)
|
||||||
|
|
||||||
Answers
|
Answers
|
||||||
-------
|
-------
|
||||||
@@ -541,6 +541,48 @@ Exercise 4
|
|||||||
where HardCodedTagNameFlow::flow(source, sink)
|
where HardCodedTagNameFlow::flow(source, sink)
|
||||||
select source, sink
|
select source, sink
|
||||||
|
|
||||||
|
Path query example
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Here is the answer to exercise 4 above, converted into a path query:
|
||||||
|
|
||||||
|
.. code-block:: ql
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id hard-coded-tag-name
|
||||||
|
*/
|
||||||
|
|
||||||
|
import javascript
|
||||||
|
|
||||||
|
class ArrayEntryCallResult extends DataFlow::Node {
|
||||||
|
ArrayEntryCallResult() {
|
||||||
|
exists(DataFlow::CallNode call, string index |
|
||||||
|
this = call.getAPropertyRead(index) and
|
||||||
|
index.regexpMatch("\\d+")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module HardCodedTagNameConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) { source instanceof ArrayEntryCallResult }
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
sink = DataFlow::globalVarRef("document").getAMethodCall("createElement").getArgument(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module HardCodedTagNameFlow = DataFlow::Global<HardCodedTagNameConfig>;
|
||||||
|
|
||||||
|
import HardCodedTagNameFlow::PathGraph
|
||||||
|
|
||||||
|
from HardCodedTagNameFlow::PathNode source, HardCodedTagNameFlow::PathNode sink
|
||||||
|
where HardCodedTagNameFlow::flowPath(source, sink)
|
||||||
|
select sink.getNode(), source, sink, "Hard-coded tag name $@.", source, "here"
|
||||||
|
|
||||||
|
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|||||||
@@ -354,11 +354,50 @@ This data flow configuration tracks data flow from environment variables to open
|
|||||||
select fileOpen, "This call to 'os.open' uses data from $@.",
|
select fileOpen, "This call to 'os.open' uses data from $@.",
|
||||||
environment, "call to 'os.getenv'"
|
environment, "call to 'os.getenv'"
|
||||||
|
|
||||||
|
Path query example
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Here is the network input example above, converted into a path query:
|
||||||
|
|
||||||
|
.. code-block:: ql
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id file-system-access-from-remote-input
|
||||||
|
*/
|
||||||
|
|
||||||
|
import python
|
||||||
|
import semmle.python.dataflow.new.DataFlow
|
||||||
|
import semmle.python.dataflow.new.TaintTracking
|
||||||
|
import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
|
import semmle.python.Concepts
|
||||||
|
|
||||||
|
module RemoteToFileConfiguration implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) {
|
||||||
|
source instanceof RemoteFlowSource
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
sink = any(FileSystemAccess fa).getAPathArgument()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module RemoteToFileFlow = TaintTracking::Global<RemoteToFileConfiguration>;
|
||||||
|
|
||||||
|
import RemoteToFileFlow::PathGraph
|
||||||
|
|
||||||
|
from RemoteToFileFlow::PathNode input, RemoteToFileFlow::PathNode fileAccess
|
||||||
|
where RemoteToFileFlow::flowPath(input, fileAccess)
|
||||||
|
select fileAccess.getNode(), input, fileAccess, "This file access uses data from $@.",
|
||||||
|
input, "user-controllable input."
|
||||||
|
|
||||||
|
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
- `Exploring data flow with path queries <https://docs.github.com/en/code-security/codeql-for-vs-code/getting-started-with-codeql-for-vs-code/exploring-data-flow-with-path-queries>`__ in the GitHub documentation.
|
- `Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__.
|
||||||
|
|
||||||
|
|
||||||
.. include:: ../reusables/python-further-reading.rst
|
.. include:: ../reusables/python-further-reading.rst
|
||||||
|
|||||||
@@ -372,6 +372,43 @@ The following global data-flow query finds calls to ``File.open`` where the file
|
|||||||
select fileOpen, "This call to 'File.open' uses data from $@.", environment,
|
select fileOpen, "This call to 'File.open' uses data from $@.", environment,
|
||||||
"an environment variable"
|
"an environment variable"
|
||||||
|
|
||||||
|
Path query example
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Here is the taint-tracking example above, converted into a path query:
|
||||||
|
|
||||||
|
.. code-block:: ql
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id file-system-access-from-remote-input
|
||||||
|
*/
|
||||||
|
|
||||||
|
import codeql.ruby.DataFlow
|
||||||
|
import codeql.ruby.TaintTracking
|
||||||
|
import codeql.ruby.Concepts
|
||||||
|
import codeql.ruby.dataflow.RemoteFlowSources
|
||||||
|
|
||||||
|
module RemoteToFileConfiguration implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node sink) {
|
||||||
|
sink = any(FileSystemAccess fa).getAPathArgument()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module RemoteToFileFlow = TaintTracking::Global<RemoteToFileConfiguration>;
|
||||||
|
|
||||||
|
import RemoteToFileFlow::PathGraph
|
||||||
|
|
||||||
|
from RemoteToFileFlow::PathNode input, RemoteToFileFlow::PathNode fileAccess
|
||||||
|
where RemoteToFileFlow::flowPath(input, fileAccess)
|
||||||
|
select fileAccess.getNode(), input, fileAccess, "This file access uses data from $@.",
|
||||||
|
input, "user-controllable input."
|
||||||
|
|
||||||
|
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|||||||
@@ -231,6 +231,46 @@ The following global taint-tracking query finds places where a string literal is
|
|||||||
where ConstantPasswordFlow::flow(sourceNode, sinkNode)
|
where ConstantPasswordFlow::flow(sourceNode, sinkNode)
|
||||||
select sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
|
select sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
|
||||||
|
|
||||||
|
Path query example
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Here is the taint-tracking example above, converted into a path query:
|
||||||
|
|
||||||
|
.. code-block:: ql
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id constant-password
|
||||||
|
*/
|
||||||
|
|
||||||
|
import rust
|
||||||
|
import codeql.rust.dataflow.DataFlow
|
||||||
|
import codeql.rust.dataflow.TaintTracking
|
||||||
|
|
||||||
|
module ConstantPasswordConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node node) { node.asExpr().getExpr() instanceof StringLiteralExpr }
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node node) {
|
||||||
|
// any argument going to a parameter called `password`
|
||||||
|
exists(Function f, CallExpr call, int index |
|
||||||
|
call.getArg(index) = node.asExpr().getExpr() and
|
||||||
|
call.getStaticTarget() = f and
|
||||||
|
f.getParam(index).getPat().(IdentPat).getName().getText() = "password"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module ConstantPasswordFlow = TaintTracking::Global<ConstantPasswordConfig>;
|
||||||
|
|
||||||
|
import ConstantPasswordFlow::PathGraph
|
||||||
|
|
||||||
|
from ConstantPasswordFlow::PathNode sourceNode, ConstantPasswordFlow::PathNode sinkNode
|
||||||
|
where ConstantPasswordFlow::flowPath(sourceNode, sinkNode)
|
||||||
|
select sinkNode.getNode(), sourceNode, sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString()
|
||||||
|
|
||||||
|
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
|
||||||
|
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
---------------
|
---------------
|
||||||
|
|||||||
@@ -278,6 +278,45 @@ The following global taint-tracking query finds places where a value from a remo
|
|||||||
where SqlInjectionFlow::flow(sourceNode, sinkNode)
|
where SqlInjectionFlow::flow(sourceNode, sinkNode)
|
||||||
select sinkNode, "This query depends on a $@.", sourceNode, "user-provided value"
|
select sinkNode, "This query depends on a $@.", sourceNode, "user-provided value"
|
||||||
|
|
||||||
|
Path query example
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Here is the string literal example above, converted into a path query:
|
||||||
|
|
||||||
|
.. code-block:: ql
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @kind path-problem
|
||||||
|
* @problem.severity warning
|
||||||
|
* @id sql-injection
|
||||||
|
*/
|
||||||
|
|
||||||
|
import swift
|
||||||
|
import codeql.swift.dataflow.DataFlow
|
||||||
|
import codeql.swift.dataflow.TaintTracking
|
||||||
|
import codeql.swift.dataflow.FlowSources
|
||||||
|
|
||||||
|
module SqlInjectionConfig implements DataFlow::ConfigSig {
|
||||||
|
predicate isSource(DataFlow::Node node) { node instanceof FlowSource }
|
||||||
|
|
||||||
|
predicate isSink(DataFlow::Node node) {
|
||||||
|
exists(CallExpr call |
|
||||||
|
call.getStaticTarget().(Method).hasQualifiedName("Connection", "execute(_:)") and
|
||||||
|
call.getArgument(0).getExpr() = node.asExpr()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module SqlInjectionFlow = TaintTracking::Global<SqlInjectionConfig>;
|
||||||
|
|
||||||
|
import SqlInjectionFlow::PathGraph
|
||||||
|
|
||||||
|
from SqlInjectionFlow::PathNode sourceNode, SqlInjectionFlow::PathNode sinkNode
|
||||||
|
where SqlInjectionFlow::flowPath(sourceNode, sinkNode)
|
||||||
|
select sinkNode.getNode(), sourceNode, sinkNode, "This query depends on a $@.", sourceNode, "user-provided value"
|
||||||
|
|
||||||
|
For more information, see "`Creating path queries <https://codeql.github.com/docs/writing-codeql-queries/creating-path-queries/>`__".
|
||||||
|
|
||||||
Further reading
|
Further reading
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user