diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst index e04cdac3deb3..4216c1b379c2 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-cpp.rst @@ -411,6 +411,48 @@ Exercise 4 GetenvToGethostbynameFlow::flow(source, sink) 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; + + 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 `__". + Further reading --------------- diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst index 7e60956a5a98..08905fa4d159 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-csharp.rst @@ -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; + + 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 `__". + Further reading --------------- diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-go.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-go.rst index 537a2308203f..ffb75e03e8ec 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-go.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-go.rst @@ -224,7 +224,7 @@ The resulting module has an identical signature to the one obtained from ``DataF 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 ~~~~~~~~ @@ -312,7 +312,7 @@ Exercise 3 import go - class GetenvSource extends CallExpr { + class GetenvSource extends DataFlow::CallNode { GetenvSource() { exists(Function m | m = this.getTarget() | m.hasQualifiedName("os", "Getenv") @@ -327,7 +327,7 @@ Exercise 4 import go - class GetenvSource extends CallExpr { + class GetenvSource extends DataFlow::CallNode { GetenvSource() { exists(Function m | m = this.getTarget() | m.hasQualifiedName("os", "Getenv") @@ -350,7 +350,6 @@ Exercise 4 sink.asExpr() = call.getArgument(0) ) } - } } module GetenvToURLFlow = DataFlow::Global; @@ -359,6 +358,56 @@ Exercise 4 where GetenvToURLFlow::flow(src, sink) 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; + + 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 `__". + Further reading --------------- diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-java.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-java.rst index bade378d3a07..c526a60cbeb8 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-java.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-java.rst @@ -361,6 +361,54 @@ Exercise 4 where GetenvToURLFlow::flow(src, sink) 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; + + 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 `__". + Further reading --------------- diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst index d6e6621e5789..be1a255433fb 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-javascript-and-typescript.rst @@ -541,6 +541,48 @@ Exercise 4 where HardCodedTagNameFlow::flow(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; + + 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 `__". + Further reading --------------- diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-python.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-python.rst index 4bce178d41f8..5befd235f81c 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-python.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-python.rst @@ -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 $@.", environment, "call to 'os.getenv'" +Path Query Example +~~~~~~~~~~~~~~~~~~ + +Here is the first 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; + + 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 `__". Further reading --------------- -- `Exploring data flow with path queries `__ in the GitHub documentation. +- `Creating path queries `__ in the GitHub documentation. .. include:: ../reusables/python-further-reading.rst diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-ruby.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-ruby.rst index 53d6dfa2d1cf..c472e0a7b1e7 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-ruby.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-ruby.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, "an environment variable" +Path Query Example +~~~~~~~~~~~~~~~~~~ + +Here is the first 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; + + 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 `__". + Further reading --------------- diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-rust.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-rust.rst index 8aed9fc93266..f8f05a116744 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-rust.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-rust.rst @@ -231,6 +231,46 @@ The following global taint-tracking query finds places where a string literal is where ConstantPasswordFlow::flow(sourceNode, sinkNode) select sinkNode, "The value $@ is used as a constant password.", sourceNode, sourceNode.toString() +Path Query Example +~~~~~~~~~~~~~~~~~~ + +Here is the first 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; + + 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 `__". + Further reading --------------- diff --git a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-swift.rst b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-swift.rst index b41c82ca7efe..bf60fa9b8845 100644 --- a/docs/codeql/codeql-language-guides/analyzing-data-flow-in-swift.rst +++ b/docs/codeql/codeql-language-guides/analyzing-data-flow-in-swift.rst @@ -278,6 +278,45 @@ The following global taint-tracking query finds places where a value from a remo where SqlInjectionFlow::flow(sourceNode, sinkNode) select sinkNode, "This query depends on a $@.", sourceNode, "user-provided value" +Path Query Example +~~~~~~~~~~~~~~~~~~ + +Here is the first 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; + + 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 `__". + Further reading ---------------