taint

package module
v0.0.0-...-ca0546c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 19, 2024 License: MPL-2.0 Imports: 4 Imported by: 0

README

taint

Implements static taint analysis for Go programs.

Taint analysis is a technique for identifying the flow of sensitive data through a program. It can be used to identify potential security vulnerabilities, such as SQL injection or cross-site scripting (XSS) attacks, by understanding how this data is used and transformed as it flows through the code.

A "source" is a point in the program where sensitive data originates, typically from user input, such as data entered into a form on a web page, or data loaded from an external source. A "sink" is a point in the program where sensitive data is used or transmitted to exploit the program.

Example

This code generates a function call graph rooted at a program's main function and then runs taint analysis on it. If the program uses database/sql, the taint analysis will determine if the program is vulnerable to SQL injection such that any of the given sources reach the given sinks.

cg, _ := callgraph.New(mainFn, buildSSA.SrcFuncs...)

sources := taint.NewSources(
	"*net/http.Request",
)

sinks := taint.NewSinks(
	"(*database/sql.DB).Query",
	"(*database/sql.DB).QueryContext",
	"(*database/sql.DB).QueryRow",
	"(*database/sql.DB).QueryRowContext",
	"(*database/sql.Tx).Query",
	"(*database/sql.Tx).QueryContext",
	"(*database/sql.Tx).QueryRow",
	"(*database/sql.Tx).QueryRowContext",
)

results, _ := taint.Check(cg, sources, sinks)

for _, result := range results {
	// We found a query edge that is tainted by user input, is it
	// doing this safely? We expect this to be safely done by
	// providing a prepared statement as a constant in the query
	// (first argument after context).
	queryEdge := result.Path[len(result.Path)-1]

	// Get the query arguments, skipping the first element, pointer to the DB.
	queryArgs := queryEdge.Site.Common().Args[1:]

	// Skip the context argument, if using a *Context query variant.
	if strings.HasPrefix(queryEdge.Site.Value().Call.Value.String(), "Context") {
		queryArgs = queryArgs[1:]
	}

	// Get the query function parameter.
	query := queryArgs[0]

	// Ensure it is a constant (prepared statement), otherwise report
	// potential SQL injection.
	if _, isConst := query.(*ssa.Const); !isConst {
		pass.Reportf(result.SinkValue.Pos(), "potential sql injection")
	}
}
taint

The taint CLI is a an interactive tool to find potential security vulnerabilities. Can be used to find potential SQL injections, log injections, and cross-site scripting (XSS) vulnerabilities, among other types of vulnerabilities.

$ go install github.com/picatz/taint/cmd/taint@latest

demo

sqli

The sqli analyzer finds potential SQL injections.

$ go install github.com/picatz/taint/cmd/sqli@latest
$ cd sql/injection/testdata/src/example
$ cat main.go
package main

import (
        "database/sql"
        "net/http"
)

func business(db *sql.DB, q string) {
        db.Query(q) // potential sql injection
}

func run() {
        db, _ := sql.Open("sqlite3", ":memory:")

        mux := http.NewServeMux()

        mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
                business(db, r.URL.Query().Get("sql-query"))
        })

        http.ListenAndServe(":8080", mux)
}

func main() {
        run()
}
$ sqli main.go
./sql/injection/testdata/src/example/main.go:9:10: potential sql injection
logi

The logi analyzer finds potential log injections.

$ go install github.com/picatz/taint/cmd/logi@latest
$ cd log/injection/testdata/src/a
$ cat main.go
package main

import (
        "log"
        "net/http"
)

func main() {
        http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
                log.Println(r.URL.Query().Get("input"))
        })

        http.ListenAndServe(":8080", nil)
}
$ logi main.go
./log/injection/testdata/src/example/main.go:10:14: potential log injection
xss

The xss analyzer finds potential cross-site scripting (XSS) vulnerabilities.

$ go install github.com/picatz/taint/cmd/xss@latest
$ cd xss/testdata/src/a
$ cat main.go
package main

import (
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte(r.URL.Query().Get("input"))) // want "potential XSS"
	})

	http.ListenAndServe(":8080", nil)
}
$ xss main.go
./xss/testdata/src/example/main.go:9:8: potential XSS

Documentation

Overview

Package taint enables "taint checking", a static analysis technique for identifying attacker-controlled "sources" used in dangerous contexts "sinks".

A classic example of this is identifying SQL injections, where user controlled inputs, typically from an HTTP request, finds their way into a SQL query without using a prepared statement.

Index

Constants

This section is empty.

Variables

View Source
var ErrStopWalk = fmt.Errorf("taint: stop walk")

Functions

func WalkSSA

func WalkSSA(v ssa.Value, visit func(v ssa.Value) error) error

WalkSSA walks the SSA IR recursively with a visitor function that can be used to inspect each node in the graph. The visitor function should return an error if it wants to stop the walk.

Types

type Result

type Result struct {
	// Path is the specific path within a callgraph
	// where the source founds its way into a sink.
	Path callgraphutil.Path

	// Source type information.
	SourceType string
	// Source SSA value.
	SourceValue ssa.Value

	// Sink information.
	SinkType string
	// Sink SSA value.
	SinkValue ssa.Value
}

Result is an individual finding from a taint check.

It contains the path within the callgraph where the source found its way into the sink, along with the source and sink type information and SSA values.

type Results

type Results []Result

Results is a collection of unique findings from a taint check.

func Check

func Check(cg *callgraph.Graph, sources Sources, sinks Sinks) Results

Check is the primary function users of this package will use.

It returns a list of results from the callgraph, where any of the given sources found their way into any of the given sinks.

Sources is a list of functions that return user-controlled values, such as HTTP request parameters. Sinks is a list of potentially dangerous functions that should not be called with user-controlled values.

Diagram
             ╭───────────────────────────────────────────────────────────────╮
             │                          ╭────────┬──────────────╮            │
             │                          ▼        │              │            │
╭───────╮    │ ╭───────────╮    ╭───────────────╮│   ╭──────────┴──────────╮ │
│ Check ├──▶ │ │ checkPath ├──▶ │ checkSSAValue ├┴─▶ │ checkSSAInstruction │ │
╰───────╯    │ ╰───────────╯    ╰───────────────╯    ╰─────────────────────╯ │
             ╰──────────────────────────────┬────────────────────────────────╯
                                            │
                                            ▼
                                       ╭─────────╮
                                       │ Results │
                                       ╰─────────╯

This is a recursive algorithm that will traverse the callgraph to identify if any of the given sources were used to obtain the initial SSA value (v). We handle this value, depending on its type, where we "peel back" its references and relevant SSA instructions to determine if any of the given sinks were involved in the creation of the initial value.

type Sinks

type Sinks = stringSet

Sinks are the types that are considered "sinks" that tainted data in the program may flow into.

func NewSinks

func NewSinks(sinkTypes ...string) Sinks

NewSinks returns a new Sinks set with the given sink types.

type Sources

type Sources = stringSet

Sources are the types that are considered "sources" of tainted data in the program.

func NewSources

func NewSources(sourceTypes ...string) Sources

NewSources returns a new Sources set with the given source types.

Directories

Path Synopsis
Package callgraphutil implements utilities for golang.org/x/tools/go/callgraph including path searching, graph construction, printing, and more.
Package callgraphutil implements utilities for golang.org/x/tools/go/callgraph including path searching, graph construction, printing, and more.
cmd
xss
log
sql

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL