Go: Threat model tests

This commit is contained in:
Ed Minnix
2024-06-06 22:58:58 -04:00
parent 7f19f449eb
commit 53dd269f9f
23 changed files with 362 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
private import go
private import semmle.go.security.FlowSources
private import semmle.go.dataflow.ExternalFlow
private import semmle.go.dataflow.DataFlow
private module ThreatModelConfig implements DataFlow::ConfigSig {
predicate isSource(DataFlow::Node source) { source instanceof ThreatModelFlowSource }
predicate isSink(DataFlow::Node sink) {
sink = any(DataFlow::CallNode c | c.getTarget().getName() = "sink").getAnArgument()
}
}
module ThreatModelFlow = TaintTracking::Global<ThreatModelConfig>;

View File

@@ -0,0 +1,5 @@
module semmle.go.dataflow.ThreatModels
go 1.22.3
require github.com/nonexistent/sources v0.0.0-20240601000000-0000000000000

View File

@@ -0,0 +1,38 @@
package main
import (
"github.com/nonexistent/sources"
"net/http"
)
func Environment() {
home := sources.ReadEnvironment("HOME")
sink("SELECT * FROM " + home)
}
func Cli() {
arg := sources.GetCliArg("arg")
sink("SELECT * FROM " + arg)
}
func Custom() {
query := sources.GetCustom("query")
sink("SELECT * FROM " + query)
}
func StoredSqlInjection() {
query := sources.ExecuteQuery("SELECT * FROM queries LIMIT 1")
sink(query)
}
func Handler(w http.ResponseWriter, r *http.Request) {
query := r.URL.Query().Get("query")
sink("SELECT * FROM " + query)
}
func sink(s string) {
}

View File

@@ -0,0 +1,12 @@
edges
| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | MaD:735 |
| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:742 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:32:11:32:15 | selection of URL | semmle.label | selection of URL |
| test.go:32:11:32:23 | call to Query | semmle.label | call to Query |
| test.go:32:11:32:36 | call to Get | semmle.label | call to Get |
| test.go:34:7:34:30 | ...+... | semmle.label | ...+... |
subpaths
#select
| test.go:32:11:32:15 | selection of URL | test.go:34:7:34:30 | ...+... |

View File

@@ -0,0 +1,15 @@
extensions:
- addsTo:
pack: codeql/threat-models
extensible: threatModelConfiguration
data: []
- addsTo:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/nonexistent/sources", "", False, "ExecuteQuery", "", "", "ReturnValue", "database", "manual"]
- ["github.com/nonexistent/sources", "", False, "ReadEnvironment", "", "", "ReturnValue", "environment", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCustom", "", "", "ReturnValue", "custom", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCliArg", "", "", "ReturnValue", "commandargs", "manual"]

View File

@@ -0,0 +1,10 @@
/**
* This is a dataflow test using the "default" threat model.
*/
import Test
import ThreatModelFlow::PathGraph
from ThreatModelFlow::PathNode source, ThreatModelFlow::PathNode sink
where ThreatModelFlow::flowPath(source, sink)
select source, sink

View File

@@ -0,0 +1,16 @@
edges
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query | provenance | Src:MaD:1 |
| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | MaD:735 |
| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:742 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:27:11:27:63 | call to ExecuteQuery | semmle.label | call to ExecuteQuery |
| test.go:28:7:28:11 | query | semmle.label | query |
| test.go:32:11:32:15 | selection of URL | semmle.label | selection of URL |
| test.go:32:11:32:23 | call to Query | semmle.label | call to Query |
| test.go:32:11:32:36 | call to Get | semmle.label | call to Get |
| test.go:34:7:34:30 | ...+... | semmle.label | ...+... |
subpaths
#select
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query |
| test.go:32:11:32:15 | selection of URL | test.go:34:7:34:30 | ...+... |

View File

@@ -0,0 +1,16 @@
extensions:
- addsTo:
pack: codeql/threat-models
extensible: threatModelConfiguration
data:
- ["database", true, 0]
- addsTo:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/nonexistent/sources", "", False, "ExecuteQuery", "", "", "ReturnValue", "database", "manual"]
- ["github.com/nonexistent/sources", "", False, "ReadEnvironment", "", "", "ReturnValue", "environment", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCustom", "", "", "ReturnValue", "custom", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCliArg", "", "", "ReturnValue", "commandargs", "manual"]

View File

@@ -0,0 +1,11 @@
/**
* This is a dataflow test using the "default" threat model with the
* addition of "database".
*/
import Test
import ThreatModelFlow::PathGraph
from ThreatModelFlow::PathNode source, ThreatModelFlow::PathNode sink
where ThreatModelFlow::flowPath(source, sink)
select source, sink

View File

@@ -0,0 +1,24 @@
edges
| test.go:9:10:9:40 | call to ReadEnvironment | test.go:11:7:11:29 | ...+... | provenance | Src:MaD:2 |
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... | provenance | Src:MaD:4 |
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query | provenance | Src:MaD:1 |
| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | MaD:735 |
| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:742 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:9:10:9:40 | call to ReadEnvironment | semmle.label | call to ReadEnvironment |
| test.go:11:7:11:29 | ...+... | semmle.label | ...+... |
| test.go:15:9:15:32 | call to GetCliArg | semmle.label | call to GetCliArg |
| test.go:17:7:17:28 | ...+... | semmle.label | ...+... |
| test.go:27:11:27:63 | call to ExecuteQuery | semmle.label | call to ExecuteQuery |
| test.go:28:7:28:11 | query | semmle.label | query |
| test.go:32:11:32:15 | selection of URL | semmle.label | selection of URL |
| test.go:32:11:32:23 | call to Query | semmle.label | call to Query |
| test.go:32:11:32:36 | call to Get | semmle.label | call to Get |
| test.go:34:7:34:30 | ...+... | semmle.label | ...+... |
subpaths
#select
| test.go:9:10:9:40 | call to ReadEnvironment | test.go:11:7:11:29 | ...+... |
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... |
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query |
| test.go:32:11:32:15 | selection of URL | test.go:34:7:34:30 | ...+... |

View File

@@ -0,0 +1,17 @@
extensions:
- addsTo:
pack: codeql/threat-models
extensible: threatModelConfiguration
data:
- ["local", true, 0]
- addsTo:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/nonexistent/sources", "", False, "ExecuteQuery", "", "", "ReturnValue", "database", "manual"]
- ["github.com/nonexistent/sources", "", False, "ReadEnvironment", "", "", "ReturnValue", "environment", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCustom", "", "", "ReturnValue", "custom", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCliArg", "", "", "ReturnValue", "commandargs", "manual"]

View File

@@ -0,0 +1,11 @@
/**
* This is a dataflow test using the "default" threat model with the
* addition of the threat model group "local".
*/
import Test
import ThreatModelFlow::PathGraph
from ThreatModelFlow::PathNode source, ThreatModelFlow::PathNode sink
where ThreatModelFlow::flowPath(source, sink)
select source, sink

View File

@@ -0,0 +1,28 @@
edges
| test.go:9:10:9:40 | call to ReadEnvironment | test.go:11:7:11:29 | ...+... | provenance | Src:MaD:2 |
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... | provenance | Src:MaD:4 |
| test.go:21:11:21:36 | call to GetCustom | test.go:23:7:23:30 | ...+... | provenance | Src:MaD:3 |
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query | provenance | Src:MaD:1 |
| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | MaD:735 |
| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:742 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:9:10:9:40 | call to ReadEnvironment | semmle.label | call to ReadEnvironment |
| test.go:11:7:11:29 | ...+... | semmle.label | ...+... |
| test.go:15:9:15:32 | call to GetCliArg | semmle.label | call to GetCliArg |
| test.go:17:7:17:28 | ...+... | semmle.label | ...+... |
| test.go:21:11:21:36 | call to GetCustom | semmle.label | call to GetCustom |
| test.go:23:7:23:30 | ...+... | semmle.label | ...+... |
| test.go:27:11:27:63 | call to ExecuteQuery | semmle.label | call to ExecuteQuery |
| test.go:28:7:28:11 | query | semmle.label | query |
| test.go:32:11:32:15 | selection of URL | semmle.label | selection of URL |
| test.go:32:11:32:23 | call to Query | semmle.label | call to Query |
| test.go:32:11:32:36 | call to Get | semmle.label | call to Get |
| test.go:34:7:34:30 | ...+... | semmle.label | ...+... |
subpaths
#select
| test.go:9:10:9:40 | call to ReadEnvironment | test.go:11:7:11:29 | ...+... |
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... |
| test.go:21:11:21:36 | call to GetCustom | test.go:23:7:23:30 | ...+... |
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query |
| test.go:32:11:32:15 | selection of URL | test.go:34:7:34:30 | ...+... |

View File

@@ -0,0 +1,17 @@
extensions:
- addsTo:
pack: codeql/threat-models
extensible: threatModelConfiguration
data:
- ["all", true, 0]
- addsTo:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/nonexistent/sources", "", False, "ExecuteQuery", "", "", "ReturnValue", "database", "manual"]
- ["github.com/nonexistent/sources", "", False, "ReadEnvironment", "", "", "ReturnValue", "environment", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCustom", "", "", "ReturnValue", "custom", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCliArg", "", "", "ReturnValue", "commandargs", "manual"]

View File

@@ -0,0 +1,10 @@
/**
* This is a dataflow test using "all" threat models.
*/
import Test
import ThreatModelFlow::PathGraph
from ThreatModelFlow::PathNode source, ThreatModelFlow::PathNode sink
where ThreatModelFlow::flowPath(source, sink)
select source, sink

View File

@@ -0,0 +1,20 @@
edges
| test.go:9:10:9:40 | call to ReadEnvironment | test.go:11:7:11:29 | ...+... | provenance | Src:MaD:3 |
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... | provenance | Src:MaD:5 |
| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | MaD:735 |
| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:742 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:9:10:9:40 | call to ReadEnvironment | semmle.label | call to ReadEnvironment |
| test.go:11:7:11:29 | ...+... | semmle.label | ...+... |
| test.go:15:9:15:32 | call to GetCliArg | semmle.label | call to GetCliArg |
| test.go:17:7:17:28 | ...+... | semmle.label | ...+... |
| test.go:32:11:32:15 | selection of URL | semmle.label | selection of URL |
| test.go:32:11:32:23 | call to Query | semmle.label | call to Query |
| test.go:32:11:32:36 | call to Get | semmle.label | call to Get |
| test.go:34:7:34:30 | ...+... | semmle.label | ...+... |
subpaths
#select
| test.go:9:10:9:40 | call to ReadEnvironment | test.go:11:7:11:29 | ...+... |
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... |
| test.go:32:11:32:15 | selection of URL | test.go:34:7:34:30 | ...+... |

View File

@@ -0,0 +1,18 @@
extensions:
- addsTo:
pack: codeql/threat-models
extensible: threatModelConfiguration
data:
- ["environment", true, 0]
- ["commandargs", true, 0]
- addsTo:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/nonexistent/sources", "", False, "ExecuteQuery", "", "", "ReturnValue", "database", "manual"]
- ["github.com/nonexistent/sources", "", False, "ReadEnvironment", "", "", "ReturnValue", "environment", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCustom", "", "", "ReturnValue", "custom", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCliArg", "", "", "ReturnValue", "commandargs", "manual"]

View File

@@ -0,0 +1,11 @@
/**
* This is a dataflow test using the "default" threat model with the
* addition of "environment" and "commandargs".
*/
import Test
import ThreatModelFlow::PathGraph
from ThreatModelFlow::PathNode source, ThreatModelFlow::PathNode sink
where ThreatModelFlow::flowPath(source, sink)
select source, sink

View File

@@ -0,0 +1,20 @@
edges
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... | provenance | Src:MaD:5 |
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query | provenance | Src:MaD:2 |
| test.go:32:11:32:15 | selection of URL | test.go:32:11:32:23 | call to Query | provenance | MaD:735 |
| test.go:32:11:32:23 | call to Query | test.go:32:11:32:36 | call to Get | provenance | MaD:742 |
| test.go:32:11:32:36 | call to Get | test.go:34:7:34:30 | ...+... | provenance | |
nodes
| test.go:15:9:15:32 | call to GetCliArg | semmle.label | call to GetCliArg |
| test.go:17:7:17:28 | ...+... | semmle.label | ...+... |
| test.go:27:11:27:63 | call to ExecuteQuery | semmle.label | call to ExecuteQuery |
| test.go:28:7:28:11 | query | semmle.label | query |
| test.go:32:11:32:15 | selection of URL | semmle.label | selection of URL |
| test.go:32:11:32:23 | call to Query | semmle.label | call to Query |
| test.go:32:11:32:36 | call to Get | semmle.label | call to Get |
| test.go:34:7:34:30 | ...+... | semmle.label | ...+... |
subpaths
#select
| test.go:15:9:15:32 | call to GetCliArg | test.go:17:7:17:28 | ...+... |
| test.go:27:11:27:63 | call to ExecuteQuery | test.go:28:7:28:11 | query |
| test.go:32:11:32:15 | selection of URL | test.go:34:7:34:30 | ...+... |

View File

@@ -0,0 +1,17 @@
extensions:
- addsTo:
pack: codeql/threat-models
extensible: threatModelConfiguration
data:
- ["local", true, 0]
- ["environment", false, 1]
- addsTo:
pack: codeql/go-all
extensible: sourceModel
data:
- ["github.com/nonexistent/sources", "", False, "ExecuteQuery", "", "", "ReturnValue", "database", "manual"]
- ["github.com/nonexistent/sources", "", False, "ReadEnvironment", "", "", "ReturnValue", "environment", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCustom", "", "", "ReturnValue", "custom", "manual"]
- ["github.com/nonexistent/sources", "", False, "GetCliArg", "", "", "ReturnValue", "commandargs", "manual"]

View File

@@ -0,0 +1,12 @@
/**
* This is a dataflow test using the "default" threat model with the
* addition of the threat model group "local", but without the
* "environment" threat model.
*/
import Test
import ThreatModelFlow::PathGraph
from ThreatModelFlow::PathNode source, ThreatModelFlow::PathNode sink
where ThreatModelFlow::flowPath(source, sink)
select source, sink

View File

@@ -0,0 +1,17 @@
package sources
func ExecuteQuery(query string) string {
return ""
}
func ReadEnvironment(env string) string {
return ""
}
func GetCustom(s string) string {
return ""
}
func GetCliArg(s string) string {
return ""
}

View File

@@ -0,0 +1,3 @@
# github.com/nonexistent/sources v0.0.0-20240601000000-0000000000000
## explicit
github.com/nonexistent/sources