Convert path-injection sinks to use MaD

This commit is contained in:
Owen Mansel-Chan
2024-08-06 14:00:10 +01:00
parent fa472f5e18
commit 8536e7eb02
30 changed files with 212 additions and 273 deletions

View File

@@ -6,6 +6,11 @@ extensions:
- ["beego-context", "github.com/astaxie/beego/context"]
- ["beego-context", "github.com/beego/beego/context"]
- ["beego-context", "github.com/beego/beego/server/web/context"]
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["group:beego-context", "BeegoOutput", False, "Download", "", "", "Argument[0]", "path-injection", "manual"]
- addsTo:
pack: codeql/go-all
extensible: summaryModel

View File

@@ -10,6 +10,7 @@ extensions:
pack: codeql/go-all
extensible: sinkModel
data:
# log-injection
- ["group:beego", "", False, "Alert", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["group:beego", "", False, "Critical", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["group:beego", "", False, "Debug", "", "", "Argument[0..1]", "log-injection", "manual"]
@@ -21,6 +22,11 @@ extensions:
- ["group:beego", "", False, "Trace", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["group:beego", "", False, "Warn", "", "", "Argument[0..1]", "log-injection", "manual"]
- ["group:beego", "", False, "Warning", "", "", "Argument[0..1]", "log-injection", "manual"]
# path-injection
- ["group:beego", "", False, "Walk", "", "", "Argument[1]", "path-injection", "manual"]
- ["group:beego", "Controller", False, "SaveToFile", "", "", "Argument[1]", "path-injection", "manual"]
- ["group:beego", "Controller", False, "SaveToFileWithBuffer", "", "", "Argument[1]", "path-injection", "manual"] # only exists in v2
- ["group:beego", "FileSystem", False, "Open", "", "", "Argument[0]", "path-injection", "manual"]
- addsTo:
pack: codeql/go-all
extensible: summaryModel

View File

@@ -1,4 +1,11 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/gin-gonic/gin", "Context", False, "File", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/gin-gonic/gin", "Context", False, "FileAttachment", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/gin-gonic/gin", "Context", False, "SaveUploadedFile", "", "", "Argument[1]", "path-injection", "manual"]
- addsTo:
pack: codeql/go-all
extensible: summaryModel

View File

@@ -0,0 +1,9 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/gofiber/fiber", "Ctx", False, "SendFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/gofiber/fiber", "Ctx", False, "Download", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/gofiber/fiber", "Ctx", False, "SaveFile", "", "", "Argument[1]", "path-injection", "manual"]
- ["github.com/gofiber/fiber", "Ctx", False, "SaveFileToStorage", "", "", "Argument[1]", "path-injection", "manual"] # does not exist in v1

View File

@@ -0,0 +1,17 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: packageGrouping
data:
- ["iris-context", "github.com/kataras/iris/context"]
- ["iris-context", "github.com/kataras/iris/server/web/context"]
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["group:iris-context", "Context", True, "SendFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["group:iris-context", "Context", True, "ServeFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["group:iris-context", "Context", True, "SendFileWithRate", "", "", "Argument[0]", "path-injection", "manual"]
- ["group:iris-context", "Context", True, "ServeFileWithRate", "", "", "Argument[0]", "path-injection", "manual"]
- ["group:iris-context", "Context", True, "UploadFormFiles", "", "", "Argument[0]", "path-injection", "manual"]
- ["group:iris-context", "Context", True, "SaveFormFile", "", "", "Argument[1]", "path-injection", "manual"]

View File

@@ -1,4 +1,10 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/labstack/echo", "Context", False, "Attachment", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/labstack/echo", "Context", False, "File", "", "", "Argument[0]", "path-injection", "manual"]
- addsTo:
pack: codeql/go-all
extensible: summaryModel

View File

@@ -32,6 +32,11 @@ extensions:
- ["group:revel", "Request", True, "UserAgent", "", "", "ReturnValue", "remote", "manual"]
- ["group:revel", "ServerWebSocket", True, "MessageReceive", "", "", "Argument[0]", "remote", "manual"]
- ["group:revel", "ServerWebSocket", True, "MessageReceiveJSON", "", "", "Argument[0]", "remote", "manual"]
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["group:revel", "Controller", True, "RenderFileName", "", "", "Argument[0]", "path-injection", "manual"] # we model this as a path-injection sink rather than extending HTTP::ResponseBody as this will usually mean exposing a user-controlled file rather than the actual contents being user-controlled.
- addsTo:
pack: codeql/go-all
extensible: summaryModel

View File

@@ -0,0 +1,39 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["github.com/spf13/afero", "HttpFs", False, "Create", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "HttpFs", False, "Open", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "HttpFs", False, "OpenFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "HttpFs", False, "Remove", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "HttpFs", False, "RemoveAll", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "MemMapFs", False, "Create", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "MemMapFs", False, "Open", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "MemMapFs", False, "OpenFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "MemMapFs", False, "Remove", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "MemMapFs", False, "RemoveAll", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "MemMapFs", False, "Mkdir", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "MemMapFs", False, "MkdirAll", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "OsFs", False, "Create", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "OsFs", False, "Open", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "OsFs", False, "OpenFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "OsFs", False, "ReadlinkIfPossible", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "OsFs", False, "Remove", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "OsFs", False, "RemoveAll", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "OsFs", False, "Mkdir", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "OsFs", False, "MkdirAll", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "ReadOnlyFs", False, "Create", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "ReadOnlyFs", False, "Open", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "ReadOnlyFs", False, "OpenFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "ReadOnlyFs", False, "ReadDir", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "ReadOnlyFs", False, "ReadlinkIfPossible", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "ReadOnlyFs", False, "Mkdir", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "ReadOnlyFs", False, "MkdirAll", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "RegexpFs", False, "Create", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "RegexpFs", False, "Open", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "RegexpFs", False, "OpenFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "RegexpFs", False, "Remove", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "RegexpFs", False, "RemoveAll", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "RegexpFs", False, "Mkdir", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/spf13/afero", "RegexpFs", False, "MkdirAll", "", "", "Argument[0]", "path-injection", "manual"]

View File

@@ -3,6 +3,7 @@ extensions:
pack: codeql/go-all
extensible: sinkModel
data:
# request-forgery
- ["github.com/valyala/fasthttp", "", True, "Get", "", "", "Argument[1]", "request-forgery", "manual"]
- ["github.com/valyala/fasthttp", "", True, "GetDeadline", "", "", "Argument[1]", "request-forgery", "manual"]
- ["github.com/valyala/fasthttp", "", True, "GetTimeout", "", "", "Argument[1]", "request-forgery", "manual"]
@@ -28,6 +29,15 @@ extensions:
- ["github.com/valyala/fasthttp", "TCPDialer", True, "DialDualStack", "", "", "Argument[0]", "request-forgery[TCP Addr + Port]", "manual"]
- ["github.com/valyala/fasthttp", "TCPDialer", True, "DialDualStackTimeout", "", "", "Argument[0]", "request-forgery[TCP Addr + Port]", "manual"]
- ["github.com/valyala/fasthttp", "TCPDialer", True, "DialTimeout", "", "", "Argument[0]", "request-forgery[TCP Addr + Port]", "manual"]
# path-injection
- ["github.com/valyala/fasthttp", "", False, "SaveMultipartFile", "", "", "Argument[1]", "path-injection", "manual"]
- ["github.com/valyala/fasthttp", "", False, "ServeFile", "", "", "Argument[1]", "path-injection", "manual"]
- ["github.com/valyala/fasthttp", "", False, "ServeFileBytes", "", "", "Argument[1]", "path-injection", "manual"]
- ["github.com/valyala/fasthttp", "", False, "ServeFileBytesUncompressed", "", "", "Argument[1]", "path-injection", "manual"]
- ["github.com/valyala/fasthttp", "", False, "ServeFileUncompressed", "", "", "Argument[1]", "path-injection", "manual"]
- ["github.com/valyala/fasthttp", "RequestCtx", False, "SendFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/valyala/fasthttp", "RequestCtx", False, "SendFileBytes", "", "", "Argument[0]", "path-injection", "manual"]
- ["github.com/valyala/fasthttp", "Response", False, "SendFile", "", "", "Argument[0]", "path-injection", "manual"]
- addsTo:
pack: codeql/go-all
extensible: summaryModel

View File

@@ -1,4 +1,13 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["io/ioutil", "", False, "ReadDir", "", "", "Argument[0]", "path-injection", "manual"]
- ["io/ioutil", "", False, "ReadFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["io/ioutil", "", False, "TempDir", "", "", "Argument[0..1]", "path-injection", "manual"]
- ["io/ioutil", "", False, "TempFile", "", "", "Argument[0..1]", "path-injection", "manual"]
- ["io/ioutil", "", False, "WriteFile", "", "", "Argument[0]", "path-injection", "manual"]
- addsTo:
pack: codeql/go-all
extensible: summaryModel

View File

@@ -1,4 +1,9 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["net/http", "", False, "ServeFile", "", "", "Argument[2]", "path-injection", "manual"]
- addsTo:
pack: codeql/go-all
extensible: summaryModel

View File

@@ -1,4 +1,34 @@
extensions:
- addsTo:
pack: codeql/go-all
extensible: sinkModel
data:
- ["os", "", False, "Chdir", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Chmod", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Chown", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Chtimes", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Create", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Lchown", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Link", "", "", "Argument[0..1]", "path-injection", "manual"]
- ["os", "", False, "Lstat", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Mkdir", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "MkdirAll", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "NewFile", "", "", "Argument[1]", "path-injection", "manual"]
- ["os", "", False, "Open", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "OpenFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Readlink", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Remove", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "RemoveAll", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Rename", "", "", "Argument[0..1]", "path-injection", "manual"]
- ["os", "", False, "Stat", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "Symlink", "", "", "Argument[0..1]", "path-injection", "manual"]
- ["os", "", False, "Truncate", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "DirFS", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "ReadDir", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "ReadFile", "", "", "Argument[0]", "path-injection", "manual"]
- ["os", "", False, "MkdirTemp", "", "", "Argument[0..1]", "path-injection", "manual"]
- ["os", "", False, "CreateTemp", "", "", "Argument[0..1]", "path-injection", "manual"]
- ["os", "", False, "WriteFile", "", "", "Argument[0]", "path-injection", "manual"]
- addsTo:
pack: codeql/go-all
extensible: summaryModel

View File

@@ -40,15 +40,12 @@ import semmle.go.frameworks.ElazarlGoproxy
import semmle.go.frameworks.Email
import semmle.go.frameworks.Encoding
import semmle.go.frameworks.Fasthttp
import semmle.go.frameworks.Fiber
import semmle.go.frameworks.Gin
import semmle.go.frameworks.GinCors
import semmle.go.frameworks.Glog
import semmle.go.frameworks.GoJose
import semmle.go.frameworks.GoKit
import semmle.go.frameworks.GoMicro
import semmle.go.frameworks.Gqlgen
import semmle.go.frameworks.Iris
import semmle.go.frameworks.Jwt
import semmle.go.frameworks.K8sIoApimachineryPkgRuntime
import semmle.go.frameworks.K8sIoApiCoreV1

View File

@@ -112,6 +112,23 @@ module FileSystemAccess {
}
}
private class DefaultFileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
DataFlow::ArgumentNode pathArgument;
DefaultFileSystemAccess() {
sinkNode(pathArgument, "path-injection") and
this = pathArgument.getCall()
}
override DataFlow::Node getAPathArgument() {
not pathArgument instanceof DataFlow::ImplicitVarargsSlice and
result = pathArgument
or
pathArgument instanceof DataFlow::ImplicitVarargsSlice and
result = this.getAnImplicitVarargsArgument()
}
}
/** A function that escapes meta-characters to prevent injection attacks. */
class EscapeFunction extends Function instanceof EscapeFunction::Range {
/**

View File

@@ -15,9 +15,11 @@ module Afero {
string aferoPackage() { result = package("github.com/spf13/afero", "") }
/**
* DEPRECATED: Use `FileSystemAccess::Range` instead.
*
* The File system access sinks of [afero](https://github.com/spf13/afero) framework methods
*/
class AferoSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
deprecated class AferoSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
AferoSystemAccess() {
exists(Method m |
m.hasQualifiedName(aferoPackage(), "HttpFs",

View File

@@ -173,33 +173,6 @@ module Beego {
}
}
/**
* The File system access sinks
*/
private class FsOperations extends FileSystemAccess::Range, DataFlow::CallNode {
int pathArg;
FsOperations() {
this.getTarget().hasQualifiedName(packagePath(), "Walk") and pathArg = 1
or
exists(Method m | this = m.getACall() |
m.hasQualifiedName(packagePath(), "FileSystem", "Open") and pathArg = 0
or
m.hasQualifiedName(packagePath(), "Controller", "SaveToFile") and pathArg = 1
or
m.hasQualifiedName(contextPackagePath(), "BeegoOutput", "Download") and
pathArg = 0
or
// SaveToFileWithBuffer only available in v2
m.hasQualifiedName("github.com/beego/beego/v2/server/web", "Controller",
"SaveToFileWithBuffer") and
pathArg = 1
)
}
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathArg) }
}
private class RedirectMethods extends Http::Redirect::Range, DataFlow::CallNode {
string className;

View File

@@ -70,9 +70,11 @@ private module Echo {
}
/**
* DEPRECATED: Use `FileSystemAccess::Range` instead.
*
* The File system access sinks
*/
class FsOperations extends FileSystemAccess::Range, DataFlow::CallNode {
deprecated class FsOperations extends FileSystemAccess::Range, DataFlow::CallNode {
FsOperations() {
exists(Method m |
m.hasQualifiedName(packagePath(), "Context", ["Attachment", "File"]) and

View File

@@ -175,9 +175,11 @@ module Fasthttp {
*/
module Functions {
/**
* DEPRECATED: Use `FileSystemAccess::Range` instead.
*
* A function that doesn't sanitize user-provided file paths.
*/
class FileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
deprecated class FileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
FileSystemAccess() {
exists(Function f |
f.hasQualifiedName(packagePath(),
@@ -399,12 +401,14 @@ module Fasthttp {
/**
* Provide modeling for fasthttp.Response Type.
*/
module Response {
deprecated module Response {
/**
* DEPRECATED: Use `FileSystemAccess::Range` instead.
*
* A Method that sends files from its input.
* It does not check the input path against path traversal attacks, So it is a dangerous method.
*/
class FileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
deprecated class FileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
FileSystemAccess() {
exists(Method mcn |
mcn.hasQualifiedName(packagePath(), "Response", "SendFile") and
@@ -477,9 +481,11 @@ module Fasthttp {
*/
module RequestCtx {
/**
* DEPRECATED: Use `FileSystemAccess::Range` instead.
*
* The Methods that don't sanitize user provided file paths.
*/
class FileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
deprecated class FileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
FileSystemAccess() {
exists(Method mcn |
mcn.hasQualifiedName(packagePath(), "RequestCtx", ["SendFile", "SendFileBytes"]) and

View File

@@ -1,38 +0,0 @@
/**
* Provides classes for working the `github.com/gofiber/fiber` package.
*/
import go
private module Fiber {
/** Gets the package name `github.com/gofiber/fiber`. */
string packagePath() { result = package("github.com/gofiber/fiber", "") }
/** Gets the v2 module path `github.com/gofiber/fiber/v2` */
string v2modulePath() { result = "github.com/gofiber/fiber/v2" }
/**
* The File system access sinks
*/
class FsOperations extends FileSystemAccess::Range, DataFlow::CallNode {
int pathArg;
FsOperations() {
exists(Method m |
(
m.hasQualifiedName(packagePath(), "Ctx", ["SendFile", "Download"]) and
pathArg = 0
or
m.hasQualifiedName(packagePath(), "Ctx", "SaveFile") and
pathArg = 1
or
m.hasQualifiedName(v2modulePath(), "Ctx", "SaveFileToStorage") and
pathArg = 1
) and
this = m.getACall()
)
}
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathArg) }
}
}

View File

@@ -1,32 +0,0 @@
/**
* Provides classes for working with the `github.com/gin-gonic/gin` package.
*/
import go
private module Gin {
/** Gets the package name `github.com/gin-gonic/gin`. */
string packagePath() { result = package("github.com/gin-gonic/gin", "") }
/**
* The File system access sinks
*/
class FsOperations extends FileSystemAccess::Range, DataFlow::CallNode {
int pathArg;
FsOperations() {
exists(Method m |
(
m.hasQualifiedName(packagePath(), "Context", ["File", "FileAttachment"]) and
pathArg = 0
or
m.hasQualifiedName(packagePath(), "Context", "SaveUploadedFile") and
pathArg = 1
) and
this = m.getACall()
)
}
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathArg) }
}
}

View File

@@ -1,49 +0,0 @@
/**
* Provides classes for working the `github.com/kataras/iris` package.
*/
import go
private module Iris {
/** Gets the v1 module path `github.com/kataras/iris`. */
string v1modulePath() { result = "github.com/kataras/iris" }
/** Gets the v12 module path `github.com/kataras/iris/v12` */
string v12modulePath() { result = "github.com/kataras/iris/v12" }
/** Gets the path for the context package of all versions of beego. */
string contextPackagePath() {
result = v12contextPackagePath()
or
result = v1contextPackagePath()
}
/** Gets the path for the context package of beego v12. */
string v12contextPackagePath() { result = v12modulePath() + "/context" }
/** Gets the path for the context package of beego v1. */
string v1contextPackagePath() { result = v1modulePath() + "/server/web/context" }
/**
* The File system access sinks
*/
class FsOperations extends FileSystemAccess::Range, DataFlow::CallNode {
int pathArg;
FsOperations() {
exists(Method m |
(
m.hasQualifiedName(contextPackagePath(), "Context",
["SendFile", "ServeFile", "SendFileWithRate", "ServeFileWithRate", "UploadFormFiles"]) and
pathArg = 0
or
m.hasQualifiedName(v12contextPackagePath(), "Context", "SaveFormFile") and
pathArg = 1
) and
this = m.getACall()
)
}
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathArg) }
}
}

View File

@@ -87,20 +87,6 @@ module Revel {
override string getAContentType() { result = contentType }
}
/**
* The `revel.Controller.RenderFileName` method, which instructs Revel to open a file and return its contents.
* We extend FileSystemAccess rather than HTTP::ResponseBody as this will usually mean exposing a user-controlled
* file rather than the actual contents being user-controlled.
*/
private class RenderFileNameCall extends FileSystemAccess::Range, DataFlow::CallNode {
RenderFileNameCall() {
this =
any(Method m | m.hasQualifiedName(packagePath(), "Controller", "RenderFileName")).getACall()
}
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
}
/**
* The `revel.Controller.Redirect` method.
*

View File

@@ -24,7 +24,6 @@ import semmle.go.frameworks.stdlib.Html
import semmle.go.frameworks.stdlib.HtmlTemplate
import semmle.go.frameworks.stdlib.Io
import semmle.go.frameworks.stdlib.IoFs
import semmle.go.frameworks.stdlib.IoIoutil
import semmle.go.frameworks.stdlib.Log
import semmle.go.frameworks.stdlib.MimeMultipart
import semmle.go.frameworks.stdlib.MimeQuotedprintable

View File

@@ -1,18 +0,0 @@
/**
* Provides classes modeling security-relevant aspects of the `io/ioutil` package.
*/
import go
/** Provides models of commonly used functions in the `io/ioutil` package. */
module IoIoutil {
private class IoUtilFileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
IoUtilFileSystemAccess() {
exists(string fn | this.getTarget().hasQualifiedName("io/ioutil", fn) |
fn = ["ReadDir", "ReadFile", "TempDir", "TempFile", "WriteFile"]
)
}
override DataFlow::Node getAPathArgument() { result = this.getAnArgument() }
}
}

View File

@@ -288,9 +288,11 @@ module NetHttp {
}
/**
* DEPRECATED: Use `FileSystemAccess::Range` instead.
*
* The File system access sinks
*/
class HttpServeFile extends FileSystemAccess::Range, DataFlow::CallNode {
deprecated class HttpServeFile extends FileSystemAccess::Range, DataFlow::CallNode {
HttpServeFile() {
exists(Function f |
f.hasQualifiedName("net/http", "ServeFile") and

View File

@@ -6,71 +6,6 @@ import go
/** Provides models of commonly used functions in the `os` package. */
module Os {
/**
* A call to a function in `os` that accesses the file system.
*/
private class OsFileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
int pathidx;
OsFileSystemAccess() {
exists(string fn | this.getTarget().hasQualifiedName("os", fn) |
fn = "Chdir" and pathidx = 0
or
fn = "Chmod" and pathidx = 0
or
fn = "Chown" and pathidx = 0
or
fn = "Chtimes" and pathidx = 0
or
fn = "Create" and pathidx = 0
or
fn = "Lchown" and pathidx = 0
or
fn = "Link" and pathidx in [0 .. 1]
or
fn = "Lstat" and pathidx = 0
or
fn = "Mkdir" and pathidx = 0
or
fn = "MkdirAll" and pathidx = 0
or
fn = "NewFile" and pathidx = 1
or
fn = "Open" and pathidx = 0
or
fn = "OpenFile" and pathidx = 0
or
fn = "Readlink" and pathidx = 0
or
fn = "Remove" and pathidx = 0
or
fn = "RemoveAll" and pathidx = 0
or
fn = "Rename" and pathidx in [0 .. 1]
or
fn = "Stat" and pathidx = 0
or
fn = "Symlink" and pathidx in [0 .. 1]
or
fn = "Truncate" and pathidx = 0
or
fn = "DirFS" and pathidx = 0
or
fn = "ReadDir" and pathidx = 0
or
fn = "ReadFile" and pathidx = 0
or
fn = "MkdirTemp" and pathidx in [0 .. 1]
or
fn = "CreateTemp" and pathidx in [0 .. 1]
or
fn = "WriteFile" and pathidx = 0
)
}
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathidx) }
}
/** The `os.Exit` function, which ends the process. */
private class Exit extends Function {
Exit() { this.hasQualifiedName("os", "Exit") }

View File

@@ -10,7 +10,6 @@ import go
* (SSRF) vulnerabilities.
*/
module ServerSideRequestForgery {
private import semmle.go.frameworks.Gin
private import validator
private import semmle.go.security.UrlConcatenation
private import semmle.go.dataflow.barrierguardutil.RegexpCheck

View File

@@ -7,18 +7,23 @@
| test.go:342:53:342:61 | untrusted | test.go:340:15:340:26 | call to Data | test.go:342:53:342:61 | untrusted | This path depends on a $@. | test.go:340:15:340:26 | call to Data | user-provided value |
| test.go:344:23:344:31 | untrusted | test.go:340:15:340:26 | call to Data | test.go:344:23:344:31 | untrusted | This path depends on a $@. | test.go:340:15:340:26 | call to Data | user-provided value |
edges
| test.go:215:15:215:26 | call to Data | test.go:216:18:216:26 | untrusted | provenance | Src:MaD:2 |
| test.go:215:15:215:26 | call to Data | test.go:217:10:217:18 | untrusted | provenance | Src:MaD:2 |
| test.go:215:15:215:26 | call to Data | test.go:218:35:218:43 | untrusted | provenance | Src:MaD:2 |
| test.go:324:17:324:37 | selection of RequestBody | test.go:324:40:324:43 | &... | provenance | Src:MaD:3 MaD:1 |
| test.go:324:40:324:43 | &... | test.go:326:35:326:43 | untrusted | provenance | |
| test.go:332:15:332:26 | call to Data | test.go:334:23:334:31 | untrusted | provenance | Src:MaD:2 |
| test.go:340:15:340:26 | call to Data | test.go:342:53:342:61 | untrusted | provenance | Src:MaD:2 |
| test.go:340:15:340:26 | call to Data | test.go:344:23:344:31 | untrusted | provenance | Src:MaD:2 |
| test.go:215:15:215:26 | call to Data | test.go:216:18:216:26 | untrusted | provenance | Src:MaD:3 Sink:MaD:5 |
| test.go:215:15:215:26 | call to Data | test.go:217:10:217:18 | untrusted | provenance | Src:MaD:3 Sink:MaD:8 |
| test.go:215:15:215:26 | call to Data | test.go:218:35:218:43 | untrusted | provenance | Src:MaD:3 Sink:MaD:6 |
| test.go:324:17:324:37 | selection of RequestBody | test.go:324:40:324:43 | &... | provenance | Src:MaD:4 MaD:1 |
| test.go:324:40:324:43 | &... | test.go:326:35:326:43 | untrusted | provenance | Sink:MaD:6 |
| test.go:332:15:332:26 | call to Data | test.go:334:23:334:31 | untrusted | provenance | Src:MaD:3 Sink:MaD:2 |
| test.go:340:15:340:26 | call to Data | test.go:342:53:342:61 | untrusted | provenance | Src:MaD:3 Sink:MaD:7 |
| test.go:340:15:340:26 | call to Data | test.go:344:23:344:31 | untrusted | provenance | Src:MaD:3 Sink:MaD:2 |
models
| 1 | Summary: encoding/json; ; false; Unmarshal; ; ; Argument[0]; Argument[1]; taint; manual |
| 2 | Source: group:beego-context; BeegoInput; true; Data; ; ; ReturnValue[0]; remote; manual |
| 3 | Source: group:beego-context; BeegoInput; true; RequestBody; ; ; ; remote; manual |
| 2 | Sink: group:beego-context; BeegoOutput; false; Download; ; ; Argument[0]; path-injection; manual |
| 3 | Source: group:beego-context; BeegoInput; true; Data; ; ; ReturnValue[0]; remote; manual |
| 4 | Source: group:beego-context; BeegoInput; true; RequestBody; ; ; ; remote; manual |
| 5 | Sink: group:beego; ; false; Walk; ; ; Argument[1]; path-injection; manual |
| 6 | Sink: group:beego; Controller; false; SaveToFile; ; ; Argument[1]; path-injection; manual |
| 7 | Sink: group:beego; Controller; false; SaveToFileWithBuffer; ; ; Argument[1]; path-injection; manual |
| 8 | Sink: group:beego; FileSystem; false; Open; ; ; Argument[0]; path-injection; manual |
nodes
| test.go:215:15:215:26 | call to Data | semmle.label | call to Data |
| test.go:216:18:216:26 | untrusted | semmle.label | untrusted |

View File

@@ -2,10 +2,12 @@
| test.go:222:17:222:24 | filepath | test.go:221:15:221:38 | call to QueryParam | test.go:222:17:222:24 | filepath | This path depends on a $@. | test.go:221:15:221:38 | call to QueryParam | user-provided value |
| test.go:226:23:226:30 | filepath | test.go:225:15:225:38 | call to QueryParam | test.go:226:23:226:30 | filepath | This path depends on a $@. | test.go:225:15:225:38 | call to QueryParam | user-provided value |
edges
| test.go:221:15:221:38 | call to QueryParam | test.go:222:17:222:24 | filepath | provenance | Src:MaD:1 |
| test.go:225:15:225:38 | call to QueryParam | test.go:226:23:226:30 | filepath | provenance | Src:MaD:1 |
| test.go:221:15:221:38 | call to QueryParam | test.go:222:17:222:24 | filepath | provenance | Src:MaD:3 Sink:MaD:2 |
| test.go:225:15:225:38 | call to QueryParam | test.go:226:23:226:30 | filepath | provenance | Src:MaD:3 Sink:MaD:1 |
models
| 1 | Source: github.com/labstack/echo; Context; true; QueryParam; ; ; ReturnValue[0]; remote; manual |
| 1 | Sink: github.com/labstack/echo; Context; false; Attachment; ; ; Argument[0]; path-injection; manual |
| 2 | Sink: github.com/labstack/echo; Context; false; File; ; ; Argument[0]; path-injection; manual |
| 3 | Source: github.com/labstack/echo; Context; true; QueryParam; ; ; ReturnValue[0]; remote; manual |
nodes
| test.go:221:15:221:38 | call to QueryParam | semmle.label | call to QueryParam |
| test.go:222:17:222:24 | filepath | semmle.label | filepath |

View File

@@ -4,12 +4,15 @@
| Gin.go:27:20:27:27 | filepath | Gin.go:24:15:24:33 | call to Query | Gin.go:27:20:27:27 | filepath | This path depends on a $@. | Gin.go:24:15:24:33 | call to Query | user-provided value |
| Gin.go:29:32:29:39 | filepath | Gin.go:24:15:24:33 | call to Query | Gin.go:29:32:29:39 | filepath | This path depends on a $@. | Gin.go:24:15:24:33 | call to Query | user-provided value |
edges
| Gin.go:24:15:24:33 | call to Query | Gin.go:25:10:25:17 | filepath | provenance | Src:MaD:1 |
| Gin.go:24:15:24:33 | call to Query | Gin.go:26:39:26:46 | filepath | provenance | Src:MaD:1 |
| Gin.go:24:15:24:33 | call to Query | Gin.go:27:20:27:27 | filepath | provenance | Src:MaD:1 |
| Gin.go:24:15:24:33 | call to Query | Gin.go:29:32:29:39 | filepath | provenance | Src:MaD:1 |
| Gin.go:24:15:24:33 | call to Query | Gin.go:25:10:25:17 | filepath | provenance | Src:MaD:4 Sink:MaD:1 |
| Gin.go:24:15:24:33 | call to Query | Gin.go:26:39:26:46 | filepath | provenance | Src:MaD:4 |
| Gin.go:24:15:24:33 | call to Query | Gin.go:27:20:27:27 | filepath | provenance | Src:MaD:4 Sink:MaD:2 |
| Gin.go:24:15:24:33 | call to Query | Gin.go:29:32:29:39 | filepath | provenance | Src:MaD:4 Sink:MaD:3 |
models
| 1 | Source: github.com/gin-gonic/gin; Context; true; Query; ; ; ReturnValue; remote; manual |
| 1 | Sink: github.com/gin-gonic/gin; Context; false; File; ; ; Argument[0]; path-injection; manual |
| 2 | Sink: github.com/gin-gonic/gin; Context; false; FileAttachment; ; ; Argument[0]; path-injection; manual |
| 3 | Sink: github.com/gin-gonic/gin; Context; false; SaveUploadedFile; ; ; Argument[1]; path-injection; manual |
| 4 | Source: github.com/gin-gonic/gin; Context; true; Query; ; ; ReturnValue; remote; manual |
nodes
| Gin.go:24:15:24:33 | call to Query | semmle.label | call to Query |
| Gin.go:25:10:25:17 | filepath | semmle.label | filepath |