Merge pull request #251 from gagliardetto/standard-lib-pt-1

Add taint-tracking for archive/tar and archive/zip
This commit is contained in:
Max Schaefer 2020-07-28 14:27:02 +01:00 коммит произвёл GitHub
Родитель 75d69efb15 437f4b7eab
Коммит e9ae697d0d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
8 изменённых файлов: 390 добавлений и 0 удалений

Просмотреть файл

@ -3,6 +3,8 @@
*/
import go
import semmle.go.frameworks.stdlib.ArchiveTar
import semmle.go.frameworks.stdlib.ArchiveZip
/** A `String()` method. */
class StringMethod extends TaintTracking::FunctionModel, Method {

Просмотреть файл

@ -0,0 +1,63 @@
/**
* Provides classes modeling security-relevant aspects of the `archive/tar` package.
*/
import go
/** Provides models of commonly used functions in the `archive/tar` package. */
module ArchiveTar {
private class FunctionModels extends TaintTracking::FunctionModel {
FunctionInput inp;
FunctionOutput outp;
FunctionModels() {
// signature: func FileInfoHeader(fi os.FileInfo, link string) (*Header, error)
hasQualifiedName("archive/tar", "FileInfoHeader") and
(inp.isParameter(0) and outp.isResult(0))
or
// signature: func NewReader(r io.Reader) *Reader
hasQualifiedName("archive/tar", "NewReader") and
(inp.isParameter(0) and outp.isResult())
or
// signature: func NewWriter(w io.Writer) *Writer
hasQualifiedName("archive/tar", "NewWriter") and
(inp.isResult() and outp.isParameter(0))
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = inp and output = outp
}
}
private class MethodModels extends TaintTracking::FunctionModel, Method {
FunctionInput inp;
FunctionOutput outp;
MethodModels() {
// Methods:
// signature: func (*Header).FileInfo() os.FileInfo
this.(Method).hasQualifiedName("archive/tar", "Header", "FileInfo") and
(inp.isReceiver() and outp.isResult())
or
// signature: func (*Reader).Next() (*Header, error)
this.(Method).hasQualifiedName("archive/tar", "Reader", "Next") and
(inp.isReceiver() and outp.isResult(0))
or
// signature: func (*Reader).Read(b []byte) (int, error)
this.(Method).hasQualifiedName("archive/tar", "Reader", "Read") and
(inp.isReceiver() and outp.isParameter(0))
or
// signature: func (*Writer).Write(b []byte) (int, error)
this.(Method).hasQualifiedName("archive/tar", "Writer", "Write") and
(inp.isParameter(0) and outp.isReceiver())
or
// signature: func (*Writer).WriteHeader(hdr *Header) error
this.(Method).hasQualifiedName("archive/tar", "Writer", "WriteHeader") and
(inp.isParameter(0) and outp.isReceiver())
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = inp and output = outp
}
}
}

Просмотреть файл

@ -0,0 +1,59 @@
/**
* Provides classes modeling security-relevant aspects of the `archive/zip` package.
*/
import go
/** Provides models of commonly used functions in the `archive/zip` package. */
module ArchiveZip {
private class FunctionModels extends TaintTracking::FunctionModel {
FunctionInput inp;
FunctionOutput outp;
FunctionModels() {
// signature: func FileInfoHeader(fi os.FileInfo) (*FileHeader, error)
hasQualifiedName("archive/zip", "FileInfoHeader") and
(inp.isParameter(0) and outp.isResult(0))
or
// signature: func NewReader(r io.ReaderAt, size int64) (*Reader, error)
hasQualifiedName("archive/zip", "NewReader") and
(inp.isParameter(0) and outp.isResult(0))
or
// signature: func NewWriter(w io.Writer) *Writer
hasQualifiedName("archive/zip", "NewWriter") and
(inp.isResult() and outp.isParameter(0))
or
// signature: func OpenReader(name string) (*ReadCloser, error)
hasQualifiedName("archive/zip", "OpenReader") and
(inp.isParameter(0) and outp.isResult(0))
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = inp and output = outp
}
}
private class MethodModels extends TaintTracking::FunctionModel, Method {
FunctionInput inp;
FunctionOutput outp;
MethodModels() {
// Methods:
// signature: func (*File).Open() (io.ReadCloser, error)
this.(Method).hasQualifiedName("archive/zip", "File", "Open") and
(inp.isReceiver() and outp.isResult(0))
or
// signature: func (*Writer).Create(name string) (io.Writer, error)
this.(Method).hasQualifiedName("archive/zip", "Writer", "Create") and
(inp.isResult(0) and outp.isReceiver())
or
// signature: func (*Writer).CreateHeader(fh *FileHeader) (io.Writer, error)
this.(Method).hasQualifiedName("archive/zip", "Writer", "CreateHeader") and
(inp.isResult(0) and outp.isReceiver())
}
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input = inp and output = outp
}
}
}

Просмотреть файл

@ -0,0 +1,105 @@
// Code generated by https://github.com/gagliardetto/codebox. DO NOT EDIT.
package main
import (
"archive/tar"
"io"
"os"
)
func TaintStepTest_ArchiveTarFileInfoHeader_B0I0O0(sourceCQL interface{}) interface{} {
fromFileInfo656 := sourceCQL.(os.FileInfo)
intoHeader414, _ := tar.FileInfoHeader(fromFileInfo656, "")
return intoHeader414
}
func TaintStepTest_ArchiveTarNewReader_B0I0O0(sourceCQL interface{}) interface{} {
fromReader518 := sourceCQL.(io.Reader)
intoReader650 := tar.NewReader(fromReader518)
return intoReader650
}
func TaintStepTest_ArchiveTarNewWriter_B0I0O0(sourceCQL interface{}) interface{} {
fromWriter784 := sourceCQL.(*tar.Writer)
var intoWriter957 io.Writer
intermediateCQL := tar.NewWriter(intoWriter957)
link(fromWriter784, intermediateCQL)
return intoWriter957
}
func TaintStepTest_ArchiveTarHeaderFileInfo_B0I0O0(sourceCQL interface{}) interface{} {
fromHeader520 := sourceCQL.(tar.Header)
intoFileInfo443 := fromHeader520.FileInfo()
return intoFileInfo443
}
func TaintStepTest_ArchiveTarReaderNext_B0I0O0(sourceCQL interface{}) interface{} {
fromReader127 := sourceCQL.(tar.Reader)
intoHeader483, _ := fromReader127.Next()
return intoHeader483
}
func TaintStepTest_ArchiveTarReaderRead_B0I0O0(sourceCQL interface{}) interface{} {
fromReader989 := sourceCQL.(tar.Reader)
var intoByte982 []byte
fromReader989.Read(intoByte982)
return intoByte982
}
func TaintStepTest_ArchiveTarWriterWrite_B0I0O0(sourceCQL interface{}) interface{} {
fromByte417 := sourceCQL.([]byte)
var intoWriter584 tar.Writer
intoWriter584.Write(fromByte417)
return intoWriter584
}
func TaintStepTest_ArchiveTarWriterWriteHeader_B0I0O0(sourceCQL interface{}) interface{} {
fromHeader991 := sourceCQL.(*tar.Header)
var intoWriter881 tar.Writer
intoWriter881.WriteHeader(fromHeader991)
return intoWriter881
}
func RunAllTaints_ArchiveTar() {
{
source := newSource(0)
out := TaintStepTest_ArchiveTarFileInfoHeader_B0I0O0(source)
sink(0, out)
}
{
source := newSource(1)
out := TaintStepTest_ArchiveTarNewReader_B0I0O0(source)
sink(1, out)
}
{
source := newSource(2)
out := TaintStepTest_ArchiveTarNewWriter_B0I0O0(source)
sink(2, out)
}
{
source := newSource(3)
out := TaintStepTest_ArchiveTarHeaderFileInfo_B0I0O0(source)
sink(3, out)
}
{
source := newSource(4)
out := TaintStepTest_ArchiveTarReaderNext_B0I0O0(source)
sink(4, out)
}
{
source := newSource(5)
out := TaintStepTest_ArchiveTarReaderRead_B0I0O0(source)
sink(5, out)
}
{
source := newSource(6)
out := TaintStepTest_ArchiveTarWriterWrite_B0I0O0(source)
sink(6, out)
}
{
source := newSource(7)
out := TaintStepTest_ArchiveTarWriterWriteHeader_B0I0O0(source)
sink(7, out)
}
}

Просмотреть файл

@ -0,0 +1,95 @@
// Code generated by https://github.com/gagliardetto/codebox. DO NOT EDIT.
package main
import (
"archive/zip"
"io"
"os"
)
func TaintStepTest_ArchiveZipFileInfoHeader_B0I0O0(sourceCQL interface{}) interface{} {
fromFileInfo656 := sourceCQL.(os.FileInfo)
intoFileHeader414, _ := zip.FileInfoHeader(fromFileInfo656)
return intoFileHeader414
}
func TaintStepTest_ArchiveZipNewReader_B0I0O0(sourceCQL interface{}) interface{} {
fromReaderAt518 := sourceCQL.(io.ReaderAt)
intoReader650, _ := zip.NewReader(fromReaderAt518, 0)
return intoReader650
}
func TaintStepTest_ArchiveZipNewWriter_B0I0O0(sourceCQL interface{}) interface{} {
fromWriter784 := sourceCQL.(*zip.Writer)
var intoWriter957 io.Writer
intermediateCQL := zip.NewWriter(intoWriter957)
link(fromWriter784, intermediateCQL)
return intoWriter957
}
func TaintStepTest_ArchiveZipOpenReader_B0I0O0(sourceCQL interface{}) interface{} {
fromString520 := sourceCQL.(string)
intoReadCloser443, _ := zip.OpenReader(fromString520)
return intoReadCloser443
}
func TaintStepTest_ArchiveZipFileOpen_B0I0O0(sourceCQL interface{}) interface{} {
fromFile127 := sourceCQL.(zip.File)
intoReadCloser483, _ := fromFile127.Open()
return intoReadCloser483
}
func TaintStepTest_ArchiveZipWriterCreate_B0I0O0(sourceCQL interface{}) interface{} {
fromWriter989 := sourceCQL.(io.Writer)
var intoWriter982 zip.Writer
intermediateCQL, _ := intoWriter982.Create("")
link(fromWriter989, intermediateCQL)
return intoWriter982
}
func TaintStepTest_ArchiveZipWriterCreateHeader_B0I0O0(sourceCQL interface{}) interface{} {
fromWriter417 := sourceCQL.(io.Writer)
var intoWriter584 zip.Writer
intermediateCQL, _ := intoWriter584.CreateHeader(nil)
link(fromWriter417, intermediateCQL)
return intoWriter584
}
func RunAllTaints_ArchiveZip() {
{
source := newSource(0)
out := TaintStepTest_ArchiveZipFileInfoHeader_B0I0O0(source)
sink(0, out)
}
{
source := newSource(1)
out := TaintStepTest_ArchiveZipNewReader_B0I0O0(source)
sink(1, out)
}
{
source := newSource(2)
out := TaintStepTest_ArchiveZipNewWriter_B0I0O0(source)
sink(2, out)
}
{
source := newSource(3)
out := TaintStepTest_ArchiveZipOpenReader_B0I0O0(source)
sink(3, out)
}
{
source := newSource(4)
out := TaintStepTest_ArchiveZipFileOpen_B0I0O0(source)
sink(4, out)
}
{
source := newSource(5)
out := TaintStepTest_ArchiveZipWriterCreate_B0I0O0(source)
sink(5, out)
}
{
source := newSource(6)
out := TaintStepTest_ArchiveZipWriterCreateHeader_B0I0O0(source)
sink(6, out)
}
}

Просмотреть файл

Просмотреть файл

@ -0,0 +1,56 @@
/**
* @kind problem
*/
import go
/* A special helper function used inside the test code */
class Link extends TaintTracking::FunctionModel {
Link() { hasQualifiedName(_, "link") }
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
inp.isParameter(0) and outp.isParameter(1)
}
}
predicate isSource(DataFlow::Node source, DataFlow::CallNode call) {
exists(Function fn | fn.hasQualifiedName(_, "newSource") |
call = fn.getACall() and source = call.getResult()
)
}
predicate isSink(DataFlow::Node sink, DataFlow::CallNode call) {
exists(Function fn | fn.hasQualifiedName(_, "sink") |
call = fn.getACall() and sink = call.getArgument(1)
)
}
class FlowConf extends TaintTracking::Configuration {
FlowConf() { this = "FlowConf" }
override predicate isSource(DataFlow::Node source) { isSource(source, _) }
override predicate isSink(DataFlow::Node sink) { isSink(sink, _) }
}
/**
* True if the result of the provided sourceCall flows to the corresponding sink,
* both marked by the same numeric first argument.
*/
predicate flowsToSink(DataFlow::CallNode sourceCall) {
exists(
FlowConf cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::CallNode sinkCall
|
cfg.hasFlowPath(source, sink) and
(
isSource(source.getNode(), sourceCall) and
isSink(sink.getNode(), sinkCall) and
sourceCall.getArgument(0).getIntValue() = sinkCall.getArgument(0).getIntValue()
)
)
}
/* Show only flow sources that DON'T flow to their dedicated sink. */
from DataFlow::CallNode sourceCall
where isSource(_, sourceCall) and not flowsToSink(sourceCall)
select sourceCall, "No flow to its sink"

Просмотреть файл

@ -0,0 +1,10 @@
package main
func main() {}
func sink(id int, v interface{}) {}
func link(from interface{}, into interface{}) {}
func newSource(id int) interface{} {
return nil
}