Skip to content
This repository was archived by the owner on Apr 4, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/config-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name: "GitHub Field CodeQL Local Threat Model Configuration"
disable-default-queries: true

queries:
# Go local queries
- uses: advanced-security/codeql-queries/go/suites/codeql-go-local.qls@main

# Java local queries
- uses: advanced-security/codeql-queries/java/suites/codeql-java-local.qls@main

Expand Down
45 changes: 45 additions & 0 deletions go/CWE-078/CodeInjectionLocal.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* @name Command built from user-controlled sources
* @description Building a system command from user-controlled sources is vulnerable to insertion of
* malicious code by the user.
* @kind path-problem
* @problem.severity warning
* @security-severity 4.0
* @precision low
* @id go/command-injection
* @tags security
* external/cwe/cwe-078
* local
*/

import go
import semmle.go.security.CommandInjection
import DataFlow::PathGraph
import semmle.go.security.CommandInjectionCustomizations::CommandInjection
import github.LocalSources

class CommandInjectionLocalConfiguration extends TaintTracking::Configuration {
CommandInjectionLocalConfiguration() { this = "CommandInjection" }

// Local sources of input
override predicate isSource(DataFlow::Node source) { source instanceof LocalSources::Sources }

override predicate isSink(DataFlow::Node sink) {
exists(Sink s | sink = s | not s.doubleDashIsSanitizing())
}

override predicate isSanitizer(DataFlow::Node node) {
super.isSanitizer(node) or
node instanceof Sanitizer
}

override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
guard instanceof SanitizerGuard
}
}

// TODO: DoubleDashSanitizingConfiguration?
from CommandInjectionLocalConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink.getNode(), source, sink, "This command depends on $@.", source.getNode(),
"a user-provided value"
32 changes: 32 additions & 0 deletions go/CWE-078/examples/CommandInjection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package main

import (
"flag"
"fmt"
"log"
"os"
"os/exec"
)

func runPing(ip *string) {
cmdString := fmt.Sprintf("ping %v", *ip)
fmt.Printf("Command :: %s\n", cmdString)
cmd := exec.Command(cmdString)
err := cmd.Run()
if err != nil {
log.Fatal(err)
}
}

func main() {
ip := flag.String("ip", "8.8.8.8", "IP Address to contact")
flag.Parse()

log.Printf(" Flag >> %s\n", *ip)
runPing(ip)

ip2 := os.Args[0]
log.Printf(" Argv >> %s", ip2)
runPing(&ip2)

}
27 changes: 27 additions & 0 deletions go/github/LocalSources.qll
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import go

// ========== Sources ==========
module LocalSources {
abstract class Sources extends DataFlow::Node { }

// https://pkg.go.dev/os#Args
// class OsArgs extends Sources {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to support os.Args as this is the main use case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@securingdev Can you help fix this issue?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to take a crack at it @GeekMasher - can we connect at some point tomorrow so that I know what you're looking for (and why this section of code was in, and then commented out)?

// OsArgs() {
// exists(ValueEntity value | value.hasQualifiedName(package("os", ""), "Args") and this = value)
// }
// }
class OsGetenv extends Sources, DataFlow::CallNode {
OsGetenv() {
// https://pkg.go.dev/os#Getenv
this.getTarget().hasQualifiedName(package("os", ""), "Getenv")
or
// https://pkg.go.dev/os#Environ
this.getTarget().hasQualifiedName(package("os", ""), "Environ")
}
}

// https://pkg.go.dev/flag
class Flag extends Sources, DataFlow::CallNode {
Flag() { this.getTarget().hasQualifiedName(package("flag", ""), "String") }
}
}
11 changes: 11 additions & 0 deletions go/suites/codeql-go-local.qls
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# See https://help.semmle.com/codeql/codeql-cli/procedures/query-suites.html#filtering-the-queries-in-a-query-suite
# for additional ways to exclude queries

- description: "GitHub's Field Team CodeQL GoLang extended Suite"

- qlpack: github-queries-go
- include:
tags contain: local

- import: codeql-suites/go-security-extended.qls
from: codeql-go