Skip to content

Commit cbaede6

Browse files
author
Alvaro Muñoz
committed
Add initial packs for Go
1 parent 7745035 commit cbaede6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+721
-6
lines changed

.github/workflows/build.yml

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,10 @@ jobs:
1212
strategy:
1313
fail-fast: false
1414
matrix:
15-
# language: [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
16-
language: [ 'java' ]
15+
language: [ 'java', 'go' ]
1716

1817
steps:
1918
- uses: actions/checkout@v3
20-
# with:
21-
# submodules: true
2219

2320
# Conditionally run actions based on files modified by PR, feature branch or pushed commits
2421
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50
@@ -66,7 +63,6 @@ jobs:
6663
strategy:
6764
fail-fast: false
6865
matrix:
69-
# language: [ 'csharp', 'java', 'javascript' ]
7066
language: [ 'java' ]
7167

7268
steps:
@@ -88,7 +84,34 @@ jobs:
8884
run: |
8985
gh extension install github/gh-codeql
9086
gh codeql pack install "${{ matrix.language }}/ext/"
91-
gh codeql pack install "${{ matrix.language }}/ext-library-sources/"
9287
gh codeql pack create "${{ matrix.language }}/ext/"
88+
89+
library-sources:
90+
runs-on: ubuntu-latest
91+
92+
strategy:
93+
fail-fast: false
94+
matrix:
95+
language: [ 'java' ]
96+
97+
steps:
98+
- uses: actions/checkout@v3
99+
with:
100+
submodules: true
101+
102+
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50
103+
id: changes
104+
with:
105+
filters: |
106+
src:
107+
- '${{ matrix.language }}/ext-library-sources/**'
108+
109+
- name: Install CodeQL
110+
if: steps.changes.outputs.src == 'true'
111+
env:
112+
GITHUB_TOKEN: ${{ github.token }}
113+
run: |
114+
gh extension install github/gh-codeql
115+
gh codeql pack install "${{ matrix.language }}/ext-library-sources/"
93116
gh codeql pack create "${{ matrix.language }}/ext-library-sources/"
94117

codeql-workspace.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
provide:
22
- java/**/qlpack.yml
3+
- go/**/qlpack.yml

go/ext/codeql-pack.lock.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
lockVersion: 1.0.0
3+
dependencies: {}
4+
compiled: false

go/ext/generated/.gitkeep

Whitespace-only changes.

go/ext/manual/.gitkeep

Whitespace-only changes.

go/ext/qlpack.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
library: true
2+
name: githubsecuritylab/codeql-go-extensions
3+
version: 0.0.1
4+
extensionTargets:
5+
codeql/go-all: '*'
6+
codeql/go-queries: '*'
7+
githubsecuritylab/codeql-go-queries: '*'
8+
dataExtensions:
9+
- manual/*.yml
10+
- generated/*.yml

go/lib/ResearchMode.qll

Whitespace-only changes.

go/lib/applications/.gitkeep

Whitespace-only changes.

go/lib/codeql-pack.lock.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
lockVersion: 1.0.0
3+
dependencies:
4+
codeql/dataflow:
5+
version: 0.0.3
6+
codeql/go-all:
7+
version: 0.6.4
8+
codeql/mad:
9+
version: 0.1.4
10+
codeql/ssa:
11+
version: 0.1.4
12+
codeql/tutorial:
13+
version: 0.1.4
14+
codeql/util:
15+
version: 0.1.4
16+
compiled: false

go/lib/frameworks/.gitkeep

Whitespace-only changes.

go/lib/github/LocalSources.qll

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
private import go
2+
3+
module LocalSources {
4+
private import semmle.go.dataflow.DataFlow
5+
private import semmle.go.dataflow.TaintTracking
6+
private import semmle.go.Scopes
7+
8+
abstract class Range extends DataFlow::Node { }
9+
10+
// ========== Sources ==========
11+
12+
abstract class Sources extends DataFlow::Node { }
13+
14+
// ----------------------------------------------------
15+
// Used for finding Selections or Calls for Go imports
16+
// ----------------------------------------------------
17+
18+
//class UseOfGoImports extends Sources {
19+
//UseOfGoImports () {
20+
//exists ( ValueEntity read,
21+
//DataFlow::Package pkg |
22+
//read.getScope().getEntity(_) = pkg.getScope().getEntity(_)
23+
//and ( this.toString().regexpMatch("selection of.*")
24+
//or this.toString().regexpMatch("call to .*") )
25+
//)
26+
//}
27+
//}
28+
29+
// ----------------------------------------------------
30+
31+
class OsCmd extends LocalSources::Range {
32+
OsCmd() {
33+
exists ( ValueEntity read,
34+
DataFlow::Package pkg |
35+
read.getScope().getEntity(_) = pkg.getScope().getEntity(_)
36+
and this.toString() = "selection of Run"
37+
)
38+
}
39+
}
40+
41+
class OsExec extends LocalSources::Range {
42+
OsExec() {
43+
exists ( ValueEntity read,
44+
DataFlow::Package pkg |
45+
read.getScope().getEntity(_) = pkg.getScope().getEntity(_)
46+
and this.toString() = "selection of Command"
47+
)
48+
}
49+
}
50+
51+
class OsArgs extends LocalSources::Range {
52+
OsArgs() {
53+
exists ( ValueEntity read,
54+
DataFlow::Package pkg |
55+
read.getScope().getEntity(_) = pkg.getScope().getEntity(_)
56+
and this.toString() = "selection of Args"
57+
)
58+
}
59+
}
60+
61+
// Not currently working (need a test case)
62+
//class OsGetenv extends Sources, DataFlow::CallNode {
63+
//OsGetenv() {
64+
//// https://pkg.go.dev/os#Getenv
65+
//this.getTarget().hasQualifiedName(package("os", ""), "Getenv")
66+
//or
67+
//// https://pkg.go.dev/os#Environ
68+
//this.getTarget().hasQualifiedName(package("os", ""), "Environ")
69+
//}
70+
//}
71+
72+
// https://pkg.go.dev/flag
73+
class Flag extends LocalSources::Range {
74+
Flag() {
75+
exists ( ValueEntity read,
76+
DataFlow::Package pkg |
77+
read.getScope().getEntity(_) = pkg.getScope().getEntity(_)
78+
and
79+
( this.toString() = "selection of String"
80+
or this.toString() = "selection of Parse" )
81+
)
82+
}
83+
}
84+
}

go/lib/github/Utils.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import go
2+
import semmle.go.frameworks.stdlib.Fmt
3+
4+
class DynamicStrings extends DataFlow::Node {
5+
DynamicStrings() {
6+
// fmt format string
7+
exists(Fmt::Sprinter formatter |
8+
this = formatter.getACall()
9+
)
10+
or
11+
// binary expression
12+
exists(BinaryExpr expr |
13+
this.asExpr() = expr.getLeftOperand() and
14+
expr.getOperator() = "+"
15+
)
16+
}
17+
}

go/lib/qlpack.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
library: true
2+
name: githubsecuritylab/codeql-go-libs
3+
version: 0.0.1
4+
dependencies:
5+
codeql/go-all: '*'

go/src/CVEs/.gitkeep

Whitespace-only changes.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @name Command built from user-controlled sources
3+
* @description Building a system command from user-controlled sources is vulnerable to insertion of
4+
* malicious code by the user.
5+
* @kind path-problem
6+
* @problem.severity error
7+
* @security-severity 9.8
8+
* @precision high
9+
* @id go/injection
10+
* @tags security
11+
* external/cwe/cwe-078
12+
* audit
13+
*/
14+
15+
import go
16+
import semmle.go.security.CommandInjection
17+
import semmle.go.frameworks.SystemCommandExecutors
18+
19+
/**
20+
* A system-command execution via any argument passed to a command interpreter
21+
*/
22+
class ArgumentInjectionSink extends SystemCommandExecution::Range, DataFlow::CallNode {
23+
ArgumentInjectionSink() { this instanceof SystemCommandExecution }
24+
25+
override DataFlow::Node getCommandName() { result = this.getAnArgument() }
26+
}
27+
28+
module Flow =
29+
DataFlow::MergePathGraph<CommandInjection::Flow::PathNode,
30+
CommandInjection::DoubleDashSanitizingFlow::PathNode, CommandInjection::Flow::PathGraph,
31+
CommandInjection::DoubleDashSanitizingFlow::PathGraph>;
32+
33+
import Flow::PathGraph
34+
35+
from Flow::PathNode source, Flow::PathNode sink
36+
where
37+
CommandInjection::Flow::flowPath(source.asPathNode1(), sink.asPathNode1()) or
38+
CommandInjection::DoubleDashSanitizingFlow::flowPath(source.asPathNode2(), sink.asPathNode2())
39+
select sink.getNode(), source, sink, "This command depends on a $@.", source.getNode(),
40+
"user-provided value"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Audit - SQL Injection using format strings
2+
3+
This query checks for SQL injection vulnerabilities in the code. It looks for the use of format strings in SQL queries. Format strings are a common source of SQL injection vulnerabilities.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @name Audit - SQL Injection using format strings
3+
* @kind path-problem
4+
* @problem.severity warning
5+
* @security-severity 2.5
6+
* @sub-severity low
7+
* @precision very-low
8+
* @id go/audit/sql-injection
9+
* @tags security
10+
* external/cwe/cwe-089
11+
* audit
12+
*/
13+
import go
14+
import semmle.go.security.SqlInjection
15+
import DataFlow::PathGraph
16+
import github.Utils
17+
18+
/**
19+
* A taint-tracking configuration for detecting SQL injection vulnerabilities.
20+
*/
21+
class SqlInjectionAudit extends TaintTracking::Configuration {
22+
SqlInjectionAudit() { this = "SqlInjectionAudit" }
23+
24+
override predicate isSource(DataFlow::Node source) { source instanceof DynamicStrings }
25+
26+
override predicate isSink(DataFlow::Node sink) { sink instanceof SqlInjection::Sink }
27+
28+
override predicate isSanitizer(DataFlow::Node node) { node instanceof SqlInjection::Sanitizer }
29+
}
30+
31+
from SqlInjectionAudit config, DataFlow::PathNode source, DataFlow::PathNode sink
32+
where config.hasFlowPath(source, sink)
33+
select sink.getNode(), source, sink, "This SQL query depends on $@.", source.getNode(),
34+
"a user-provided value"

go/src/audit/explore/Dependencies.ql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import go
2+
import semmle.go.dependencies.Dependencies
3+
4+
from Dependency d, int nimports, string name
5+
where nimports = strictsum(ImportSpec is | is = d.getAnImport() | 1)
6+
and exists(string p, string v | d.info(p, v) and name = p + v)
7+
select name, nimports order by nimports desc

go/src/audit/explore/Files.ql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import go
2+
3+
from File f
4+
where f.getExtension() = "go" and not f.getRelativePath().matches("%/test/%")
5+
select f.getRelativePath()
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* @name Attack Surface
3+
* @description attack surface
4+
* @kind problem
5+
* @precision low
6+
* @id seclab/attack-surface
7+
* @tags audit
8+
*/
9+
10+
import semmle.go.security.FlowSources
11+
12+
from UntrustedFlowSource source
13+
where
14+
not source.getFile().getRelativePath().matches("%/test/%")
15+
select source, "remote", source.getFile().getRelativePath(), source.getStartLine(),
16+
source.getEndLine(), source.getStartColumn(), source.getEndColumn()
17+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @name Backwards Partial Dataflow
3+
* @description Backwards Partial Dataflow
4+
* @kind problem
5+
* @precision low
6+
* @problem.severity error
7+
* @id seclab/backwards-partial-dataflow
8+
* @tags audit
9+
*/
10+
11+
import go
12+
import semmle.go.dataflow.TaintTracking
13+
import PartialFlow::PartialPathGraph
14+
15+
private module MyConfig implements DataFlow::ConfigSig {
16+
predicate isSource(DataFlow::Node source) {
17+
none()
18+
}
19+
20+
predicate isSink(DataFlow::Node sink) {
21+
// Define the sink to run the backwards partial dataflow from. Eg:
22+
// exists(DataFlow::CallNode call |
23+
// call.getTarget().hasQualifiedName(_, "sink") and
24+
// call.getArgument(0) = sink
25+
// )
26+
none()
27+
}
28+
}
29+
30+
private module MyFlow = TaintTracking::Global<MyConfig>; // or DataFlow::Global<..>
31+
int explorationLimit() { result = 10 }
32+
private module PartialFlow = MyFlow::FlowExploration<explorationLimit/0>;
33+
34+
from PartialFlow::PartialPathNode n, int dist
35+
where PartialFlow::partialFlowRev(n, _, dist)
36+
select dist, n
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* @name DataFlow configuration
3+
* @description DataFlow TaintTracking configuration
4+
* @kind path-problem
5+
* @precision low
6+
* @problem.severity error
7+
* @id seclab/dataflow-query
8+
* @tags audit
9+
*/
10+
11+
import go
12+
import semmle.go.dataflow.TaintTracking
13+
import MyFlow::PathGraph
14+
15+
private module MyConfig implements DataFlow::ConfigSig {
16+
predicate isSource(DataFlow::Node source) {
17+
// Define your source nodes here. eg:
18+
// exists(DataFlow::CallNode call |
19+
// call.getTarget().hasQualifiedName(_, "source") and
20+
// call = source
21+
// )
22+
none()
23+
}
24+
25+
predicate isSink(DataFlow::Node sink) {
26+
// Define your sink nodes here. eg:
27+
// exists(DataFlow::CallNode call |
28+
// call.getTarget().hasQualifiedName(_, "sink") and
29+
// call.getArgument(0) = sink
30+
// )
31+
none()
32+
}
33+
}
34+
35+
module MyFlow = TaintTracking::Global<MyConfig>; // or DataFlow::Global<..>
36+
37+
from MyFlow::PathNode source, MyFlow::PathNode sink
38+
where MyFlow::flowPath(source, sink)
39+
select sink.getNode(), source, sink, "Sample TaintTracking query"

0 commit comments

Comments
 (0)