From fe02d67e778fa3c165d88176c744959b326e57e8 Mon Sep 17 00:00:00 2001 From: Mathew Payne Date: Thu, 27 Jun 2024 10:42:30 +0100 Subject: [PATCH 1/6] feat: Create Debugging Pack and add Queries --- python/debugging/README.md | 17 ++++++ python/debugging/basics/Sinks.ql | 22 +++++++ python/debugging/basics/Sources.ql | 29 +++++++++ python/debugging/codeql-pack.lock.yml | 24 ++++++++ .../debugging/diagnostics/SinksDatabases.ql | 16 +++++ python/debugging/diagnostics/SourcesLocal.ql | 18 ++++++ .../debugging/diagnostics/SourcesRemotes.ql | 16 +++++ .../partials/PartialPathsFromSink.ql | 59 +++++++++++++++++++ .../partials/PartialPathsFromSource.ql | 50 ++++++++++++++++ python/debugging/qlpack.yml | 8 +++ python/debugging/suites/default.qls | 12 ++++ 11 files changed, 271 insertions(+) create mode 100644 python/debugging/README.md create mode 100644 python/debugging/basics/Sinks.ql create mode 100644 python/debugging/basics/Sources.ql create mode 100644 python/debugging/codeql-pack.lock.yml create mode 100644 python/debugging/diagnostics/SinksDatabases.ql create mode 100644 python/debugging/diagnostics/SourcesLocal.ql create mode 100644 python/debugging/diagnostics/SourcesRemotes.ql create mode 100644 python/debugging/partials/PartialPathsFromSink.ql create mode 100644 python/debugging/partials/PartialPathsFromSource.ql create mode 100644 python/debugging/qlpack.yml create mode 100644 python/debugging/suites/default.qls diff --git a/python/debugging/README.md b/python/debugging/README.md new file mode 100644 index 00000000..51d0cef0 --- /dev/null +++ b/python/debugging/README.md @@ -0,0 +1,17 @@ +# Python - Debugging + +This Pack is a collection of Python debugging tips and tricks. + +## Basics + +- [`Sources.ql`](./basics/Sources.ql) + - List of the sources in the Application +- [`Sinks.ql`](./basics/Sinks.ql) + - List of the sinks in the Application + +## Partials + +- [`PartialPathsFromSource.ql`](./partials/PartialPathsFromSource.ql) + - List of partial paths from a sources to nodes in the Application +- [`PartialPathsFromSink.ql`](./partials/PartialPathsFromSink.ql) + - List of partial paths from a sink to nodes in the Application diff --git a/python/debugging/basics/Sinks.ql b/python/debugging/basics/Sinks.ql new file mode 100644 index 00000000..56adf3c7 --- /dev/null +++ b/python/debugging/basics/Sinks.ql @@ -0,0 +1,22 @@ +/** + * @name Sinks + * @kind problem + * @problem.severity warning + * @security-severity 1.0 + * @sub-severity low + * @precision low + * @id py/debugging/sinks + * @tags debugging + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.RemoteFlowSources +// Helpers +private import ghsl.Helpers + +from DataFlow::Node sinks +where + dangerousSinks(sinks) and + sinks.getScope().inSource() +select sinks, "sink" diff --git a/python/debugging/basics/Sources.ql b/python/debugging/basics/Sources.ql new file mode 100644 index 00000000..bdab8111 --- /dev/null +++ b/python/debugging/basics/Sources.ql @@ -0,0 +1,29 @@ +/** + * @name Sources + * @kind problem + * @problem.severity warning + * @security-severity 1.0 + * @sub-severity low + * @precision low + * @id py/debugging/sources + * @tags debugging + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.RemoteFlowSources +// Helpers +private import ghsl.Helpers +private import ghsl.LocalSources + +class Sources extends DataFlow::Node { + Sources() { + this instanceof RemoteFlowSource + or + this instanceof LocalSources::Range + } +} + +from Sources sources +where sources.getScope().inSource() +select sources, "source" diff --git a/python/debugging/codeql-pack.lock.yml b/python/debugging/codeql-pack.lock.yml new file mode 100644 index 00000000..a73e38a6 --- /dev/null +++ b/python/debugging/codeql-pack.lock.yml @@ -0,0 +1,24 @@ +--- +lockVersion: 1.0.0 +dependencies: + codeql/dataflow: + version: 1.0.1 + codeql/mad: + version: 1.0.1 + codeql/python-all: + version: 1.0.1 + codeql/regex: + version: 1.0.1 + codeql/ssa: + version: 1.0.1 + codeql/tutorial: + version: 1.0.1 + codeql/typetracking: + version: 1.0.1 + codeql/util: + version: 1.0.1 + codeql/xml: + version: 1.0.1 + codeql/yaml: + version: 1.0.1 +compiled: false diff --git a/python/debugging/diagnostics/SinksDatabases.ql b/python/debugging/diagnostics/SinksDatabases.ql new file mode 100644 index 00000000..d2f1326b --- /dev/null +++ b/python/debugging/diagnostics/SinksDatabases.ql @@ -0,0 +1,16 @@ +/** + * @name Database Sinks Diagnostic + * @id ghsl/diagnostics/database-sinks + * @description List all database sinks + * @kind diagnostic + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.security.dataflow.SqlInjectionCustomizations + +from SqlInjection::Sink s, Expr n +where + s.getScope().inSource() and + n = s.asExpr() +select n, "" diff --git a/python/debugging/diagnostics/SourcesLocal.ql b/python/debugging/diagnostics/SourcesLocal.ql new file mode 100644 index 00000000..77610d5c --- /dev/null +++ b/python/debugging/diagnostics/SourcesLocal.ql @@ -0,0 +1,18 @@ +/** + * @name Local Sources Diagnostic + * @id ghsl/diagnostics/local-sources + * @description List all local sources + * @kind diagnostic + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.RemoteFlowSources +// Helpers +import ghsl.LocalSources + +from LocalSources::Range s, Expr n +where + s.getScope().inSource() and + n = s.asExpr() +select n, "" diff --git a/python/debugging/diagnostics/SourcesRemotes.ql b/python/debugging/diagnostics/SourcesRemotes.ql new file mode 100644 index 00000000..6f1ec090 --- /dev/null +++ b/python/debugging/diagnostics/SourcesRemotes.ql @@ -0,0 +1,16 @@ +/** + * @name Remote Sources Diagnostic + * @id ghsl/diagnostics/remote-sources + * @description List all remote sources + * @kind diagnostic + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.RemoteFlowSources + +from RemoteFlowSource s, Expr n +where + s.getScope().inSource() and + n = s.asExpr() +select n, "" diff --git a/python/debugging/partials/PartialPathsFromSink.ql b/python/debugging/partials/PartialPathsFromSink.ql new file mode 100644 index 00000000..45d86df0 --- /dev/null +++ b/python/debugging/partials/PartialPathsFromSink.ql @@ -0,0 +1,59 @@ +/** + * @name Partial Path Query from Sink + * @kind path-problem + * @problem.severity warning + * @security-severity 1.0 + * @sub-severity low + * @precision low + * @id py/debugging/partial-path-from-sink + * @tags debugging + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.Concepts +import semmle.python.dataflow.new.RemoteFlowSources +import semmle.python.dataflow.new.BarrierGuards +import semmle.python.ApiGraphs +// Helpers +private import ghsl.Helpers + +// Manual Sinks +class ManualSinks extends DataFlow::Node { + ManualSinks() { this = API::moduleImport("any").getMember("any").getACall() } +} + +/** + * Partial Graph module interface + */ +module RemoteFlowsConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { any() } + + predicate isSink(DataFlow::Node sink) { + // List of dangerous sinks (SQL Injection, Command Injection, etc.) + dangerousSinks(sink) + or + // List of manually added sinks (above) + sink instanceof ManualSinks + } +} + +// Set the limit of the exloration depth +int explorationLimit() { result = 10 } + +module RemoteFlows = DataFlow::Global; + +module RemoteFlowsPartial = RemoteFlows::FlowExplorationRev; + +import RemoteFlowsPartial::PartialPathGraph + +from RemoteFlowsPartial::PartialPathNode source, RemoteFlowsPartial::PartialPathNode sink +where RemoteFlowsPartial::partialFlow(source, sink, _) +/// Filter by location +// and findByLocation(source.getNode(), "app.py", 20) +// +/// Filter by Function Parameters +// and functionParameters(source.getNode()) +// +select sink.getNode(), source, sink, "Partial Graph $@.", source.getNode(), "user-provided value" diff --git a/python/debugging/partials/PartialPathsFromSource.ql b/python/debugging/partials/PartialPathsFromSource.ql new file mode 100644 index 00000000..cae333a4 --- /dev/null +++ b/python/debugging/partials/PartialPathsFromSource.ql @@ -0,0 +1,50 @@ +/** + * @name Partial Path Query from Source + * @kind path-problem + * @problem.severity warning + * @security-severity 1.0 + * @sub-severity low + * @precision low + * @id py/debugging/partial-path-from-source + * @tags debugging + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.Concepts +import semmle.python.dataflow.new.RemoteFlowSources +import semmle.python.dataflow.new.BarrierGuards +import semmle.python.ApiGraphs +// Helpers +private import ghsl.Helpers +private import ghsl.LocalSources + +// Partial Graph +module RemoteFlowsConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source instanceof RemoteFlowSource + or + // Local Sources + source instanceof LocalSources::Range + } + + predicate isSink(DataFlow::Node sink) { any() } +} + +int explorationLimit() { result = 10 } + +module RemoteFlows = DataFlow::Global; + +module RemoteFlowsPartial = RemoteFlows::FlowExplorationFwd; + +import RemoteFlowsPartial::PartialPathGraph + +from RemoteFlowsPartial::PartialPathNode source, RemoteFlowsPartial::PartialPathNode sink +where RemoteFlowsPartial::partialFlow(source, sink, _) +/// Filter by location +// and findByLocation(source.getNode(), "app.py", 50) +/// Filter by Function Parameters +// and functionParameters(sink.getNode()) +// +select sink.getNode(), source, sink, "Partial Graph $@.", source.getNode(), "user-provided value" diff --git a/python/debugging/qlpack.yml b/python/debugging/qlpack.yml new file mode 100644 index 00000000..e5685212 --- /dev/null +++ b/python/debugging/qlpack.yml @@ -0,0 +1,8 @@ +library: false +name: githubsecuritylab/codeql-python-debugging +version: 0.1.0 +suites: suites +defaultSuiteFile: suites/default.qls +dependencies: + codeql/python-all: '^1.0.0' + githubsecuritylab/codeql-python-libs: "${workspace}" diff --git a/python/debugging/suites/default.qls b/python/debugging/suites/default.qls new file mode 100644 index 00000000..0e908a09 --- /dev/null +++ b/python/debugging/suites/default.qls @@ -0,0 +1,12 @@ +- description: "GitHub's Community Packs Python Debugging Suite" + +# Field query pack with some audit queries +- queries: "." + from: githubsecuritylab/codeql-python-queries + +- include: + kind: + - problem + - path-problem + - metric + - diagnostic From 77ebe016a50a382578678101b2206a07ccd58006 Mon Sep 17 00:00:00 2001 From: Mathew Payne <2772944+GeekMasher@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:17:50 +0100 Subject: [PATCH 2/6] Update python/debugging/basics/Sinks.ql MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alvaro Muñoz --- python/debugging/basics/Sinks.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/python/debugging/basics/Sinks.ql b/python/debugging/basics/Sinks.ql index 56adf3c7..309bd11b 100644 --- a/python/debugging/basics/Sinks.ql +++ b/python/debugging/basics/Sinks.ql @@ -11,7 +11,6 @@ import python import semmle.python.dataflow.new.DataFlow -import semmle.python.dataflow.new.RemoteFlowSources // Helpers private import ghsl.Helpers From b26e567f95d3c392168ccaf1d1575b71c8e59424 Mon Sep 17 00:00:00 2001 From: Mathew Payne <2772944+GeekMasher@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:17:56 +0100 Subject: [PATCH 3/6] Update python/debugging/diagnostics/SourcesLocal.ql MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alvaro Muñoz --- python/debugging/diagnostics/SourcesLocal.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/python/debugging/diagnostics/SourcesLocal.ql b/python/debugging/diagnostics/SourcesLocal.ql index 77610d5c..304c0e17 100644 --- a/python/debugging/diagnostics/SourcesLocal.ql +++ b/python/debugging/diagnostics/SourcesLocal.ql @@ -7,7 +7,6 @@ import python import semmle.python.dataflow.new.DataFlow -import semmle.python.dataflow.new.RemoteFlowSources // Helpers import ghsl.LocalSources From ec180d8a79f2843f039c447018d96c6ab94aa7c9 Mon Sep 17 00:00:00 2001 From: Mathew Payne <2772944+GeekMasher@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:18:03 +0100 Subject: [PATCH 4/6] Update python/debugging/suites/default.qls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alvaro Muñoz --- python/debugging/suites/default.qls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/debugging/suites/default.qls b/python/debugging/suites/default.qls index 0e908a09..2d3a722e 100644 --- a/python/debugging/suites/default.qls +++ b/python/debugging/suites/default.qls @@ -2,7 +2,7 @@ # Field query pack with some audit queries - queries: "." - from: githubsecuritylab/codeql-python-queries + from: githubsecuritylab/codeql-python-debugging - include: kind: From 5b798eed7ea5b2a16fba61e964d7f73952da5310 Mon Sep 17 00:00:00 2001 From: Mathew Payne <2772944+GeekMasher@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:18:11 +0100 Subject: [PATCH 5/6] Update python/debugging/partials/PartialPathsFromSource.ql MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alvaro Muñoz --- python/debugging/partials/PartialPathsFromSource.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/debugging/partials/PartialPathsFromSource.ql b/python/debugging/partials/PartialPathsFromSource.ql index cae333a4..2bdb6c7f 100644 --- a/python/debugging/partials/PartialPathsFromSource.ql +++ b/python/debugging/partials/PartialPathsFromSource.ql @@ -29,7 +29,7 @@ module RemoteFlowsConfig implements DataFlow::ConfigSig { source instanceof LocalSources::Range } - predicate isSink(DataFlow::Node sink) { any() } + predicate isSink(DataFlow::Node sink) { none() } } int explorationLimit() { result = 10 } From 9c77ef9e6b02947a52a9848d5bc505f691a1c790 Mon Sep 17 00:00:00 2001 From: Mathew Payne <2772944+GeekMasher@users.noreply.github.com> Date: Thu, 27 Jun 2024 13:18:42 +0100 Subject: [PATCH 6/6] Update python/debugging/partials/PartialPathsFromSink.ql MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alvaro Muñoz --- python/debugging/partials/PartialPathsFromSink.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/debugging/partials/PartialPathsFromSink.ql b/python/debugging/partials/PartialPathsFromSink.ql index 45d86df0..08ffc9cd 100644 --- a/python/debugging/partials/PartialPathsFromSink.ql +++ b/python/debugging/partials/PartialPathsFromSink.ql @@ -28,7 +28,7 @@ class ManualSinks extends DataFlow::Node { * Partial Graph module interface */ module RemoteFlowsConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { any() } + predicate isSource(DataFlow::Node source) { none() } predicate isSink(DataFlow::Node sink) { // List of dangerous sinks (SQL Injection, Command Injection, etc.)