Skip to content

Commit 7c32f33

Browse files
author
Alvaro Muñoz
authored
Merge pull request #3 from GitHubSecurityLab/go_packs
Combine GoLang QLPacks
2 parents f48dda8 + e369591 commit 7c32f33

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

+749
-9
lines changed

.github/workflows/build.yml

Lines changed: 33 additions & 9 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
@@ -75,7 +72,6 @@ jobs:
7572
strategy:
7673
fail-fast: false
7774
matrix:
78-
# language: [ 'csharp', 'java', 'javascript' ]
7975
language: [ 'java' ]
8076

8177
steps:
@@ -104,8 +100,36 @@ jobs:
104100
env:
105101
GITHUB_TOKEN: ${{ github.token }}
106102
run: |
107-
codeql pack install "${{ matrix.language }}/ext/"
108-
codeql pack install "${{ matrix.language }}/ext-library-sources/"
109-
codeql pack create "${{ matrix.language }}/ext/"
110-
codeql pack create "${{ matrix.language }}/ext-library-sources/"
103+
gh extension install github/gh-codeql
104+
gh codeql pack install "${{ matrix.language }}/ext/"
105+
gh codeql pack create "${{ matrix.language }}/ext/"
106+
107+
library-sources:
108+
runs-on: ubuntu-latest
109+
110+
strategy:
111+
fail-fast: false
112+
matrix:
113+
language: [ 'java' ]
114+
115+
steps:
116+
- uses: actions/checkout@v3
117+
with:
118+
submodules: true
119+
120+
- uses: dorny/paths-filter@4512585405083f25c027a35db413c2b3b9006d50
121+
id: changes
122+
with:
123+
filters: |
124+
src:
125+
- '${{ matrix.language }}/ext-library-sources/**'
126+
127+
- name: Install CodeQL
128+
if: steps.changes.outputs.src == 'true'
129+
env:
130+
GITHUB_TOKEN: ${{ github.token }}
131+
run: |
132+
gh extension install github/gh-codeql
133+
gh codeql pack install "${{ matrix.language }}/ext-library-sources/"
134+
gh codeql pack create "${{ matrix.language }}/ext-library-sources/"
111135

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: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* @name External dependencies
3+
* @description Count the number of dependencies that a Java project has on external packages.
4+
* @kind treemap
5+
* @id githubsecuritylab/external-dependencies
6+
* @metricType externalDependency
7+
* @tags audit
8+
*/
9+
10+
import go
11+
import semmle.go.dependencies.Dependencies
12+
13+
from Dependency d, int nimports, string name
14+
where
15+
nimports = strictsum(ImportSpec is | is = d.getAnImport() | 1) and
16+
exists(string p, string v | d.info(p, v) and name = p + v)
17+
select name, nimports order by nimports desc

go/src/audit/explore/Files.ql

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

0 commit comments

Comments
 (0)