Go [lang]二进制文件上的SetGID / SetUID是否安全?

吉姆·丹尼斯:

我编写了一个使用YAML和MySQL驱动程序的简单程序,目的是提供一个简单的实用程序来更新数据库,而不会向执行该程序的用户暴露用户名和密码凭据。

(我很清楚,我也可以用Python或其他脚本语言编写此代码,并使用管理权限委托,但我想在这里尝试另一种方法,以达到自己的目的)。

构建程序后,我使用了chgrp sys dbcreds.yaml && chmod 0640 dbcreds.yamlchgrp sys ./myprog && chmod g+s ./myprog(作为root)...,一切似乎都可以正常工作。(我还测试了在setGID步骤之前应该拒绝的访问)。

我还进行了测试strace,结果导致权限被拒绝(应该如此)。(为了好玩,我还运行ltrace -S了它;这是在Linux下运行的。正如预期的那样,我没有看到许多正常的libc函数调用……通过使我感到惊讶的是,我看到了一些pthread _....()和一个malloc()调用。我猜想,GO运行时确实确实链接到某些系统库函数)。

我的问题:这样安全吗?有什么已知的方法可以导致Go程序,例如(下面)这样的Go程序在读取了这些私有凭据之后进行核心转储或公开其内存?阅读凭据后,是否可以删除SGID特权?Go二进制文件上有SUID / SGID漏洞利用的任何示例吗?有一个更好的方法吗?是否有一种方法可以主动防止核心转储或确保敏感数据(凭证)不会出现在核心转储中?

另一个注意事项:我发现gopkg.in/yaml.v2语义有点令人不安。在我的YAML文件中,我有类似以下内容:

---
user me
pw mypassword

但是在我的代码中,我必须使用UserPw(大写),而不是像我期望的那样使用小写字母。我认为这是Goyaml的作者的实现决定是这样吗?

#!go
package main

import (
    "fmt"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
    "gopkg.in/yaml.v2"
    "io/ioutil"
    "os"
    "strconv"
)

type Creds struct {
    User string
    Pw   string
}

func main() {

    filename := "./dbcreds.yaml"
    var creds Creds
    conf, err := ioutil.ReadFile(filename)
    if err != nil {
        panic(err)
    }
    err = yaml.Unmarshal(conf, &creds)
    if err != nil {
        panic(err)
    }

    var arg1 int
    arg1, err = strconv.Atoi(os.Args[1])
    if err != nil {
        panic(err.Error()) // Just for example purpose. You should use proper error handling instead of panic
    }

    fmt.Println("arg1: ", arg1, "\n")
    dsn := fmt.Sprintf("%s:%s@/mydatabase", creds.User, creds.Pw)
    db, err := sql.Open("mysql", dsn)
    if err != nil {
        panic(err.Error())
    }
    defer db.Close()

    err = db.Ping()
    if err != nil {
        panic(err.Error())
    }

    stmtOut, err := db.Prepare("SELECT quant FROM c WHERE id >= ?")
    if err != nil {
        panic(err.Error())
    }
    defer stmtOut.Close()

    rows, err := stmtOut.Query(arg1)
    if err != nil {
        panic(err.Error())
    }
    defer rows.Close()

    for rows.Next() {
        var quant int
        err = rows.Scan(&quant)
        if err != nil {
            panic(err.Error())
        }
        fmt.Println(quant)
    }
}
依恩特:

setuid / setgid Go程序相当安全,有一个主要警告。与C / C ++ setuid / setgid程序相比,go setuid / setgid程序通常没有更多安全性。

的确,您可以通过使用环境变量GOTRACEBACK = crash运行Go程序并向其发送信号来强制Go程序转储内核。但是,这对您来说是可以的,因为Go程序将(尝试)通过向自身发送SIGABRT信号来创建核心转储。内核不会为被信号杀死的setuid / setgid程序生成核心转储。

Go的主要警告是,在GNU / Linux系统上,您不能退回到原始用户ID。这是因为在GNU / Linux上如何为多线程程序实现setuid(和setgid,setgroups,setreuid,setregid,setresuid和setresgid)的。有关详细信息,请参见http://golang.org/issue/1435

最后,Uw和Pw必须大写,因为标准的反射包不允许写入未导出的字段。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Go-二进制密码安全

go二进制文件是否有可能重新加载自身?

是否可以通过使用 TinyGo 编译 Go 二进制文件来使其更小?

使用 go get 检查是否有新版本的基于 go 的二进制文件可用

是否可以使用`go install`而不是`go test -c`来编译测试二进制文件

是否可以在运行时检测Go二进制文件是否用-H = windowsgui编译

是否可以为 CLI python 脚本构建单个二进制文件?就像 Go 和 Rust 一样

如何在ARM上测试Google Go二进制文件?

在github上发布基于golang的二进制文件,并使用“ go get”安装

如何从二进制文件在Docker上运行Go Server

如何创建在每个发行版上运行的静态Go二进制文件?

如何在Go中读取二进制文件

如何执行此Go二进制文件?

无法生成或安装GO工具二进制文件

使用go动态创建编译的二进制文件

go-使用struct读取二进制文件

如何gitignore Go二进制文件?

从go二进制文件动态构建和链接

是否可以使用Bazel构建Go库而不是二进制库?

在vs代码中调试go-lang时如何指定生成的调试二进制文件的路径

为什么Go(lang)二进制文件不会显示在`where`,`whereis`和类似工具中?

简单的setuid二进制开发

如何在Windows上检查二进制文件是否为16位

如何在Linux上检查二进制文件是否需要SSE4或AVX

是否可以在ARM处理器上运行x86二进制文件?

Pyinstaller是否可以生成二进制文件以在Windows下的CentO上运行?

在Macbook Pro 2019上针对Amazon AWS EC2交叉编译Go二进制文件

有人尝试在Windows上编译Go吗?,现在似乎支持生成PE格式二进制文件

在Linux 4.15.0上编译的Static Go二进制文件在较旧的Linux 2.6.18上不起作用