为了账号安全,请及时绑定邮箱和手机立即绑定

有没有办法 chroot/sandbox 一个 go os.exec 调用(防止 rm -rf /)

有没有办法 chroot/sandbox 一个 go os.exec 调用(防止 rm -rf /)

Go
慕神8447489 2021-12-20 16:54:26
我想测试/自动化一些存储库,基本流程类似于:repos := []string{"repo 1", "repo 2", ...}for r := range repos {    // git clone the repo     // cd repo dir    // make test    // make build    // ...}我有这样GO使用 os.exec调用所有的一系列命令,是这样的: exec.Command("sh", "-c", "git clone project")到目前为止一切顺利,但我想知道是否有一种方法可以保护/防止 Makefile 上的某些错误写入可能会做类似rm -rf /. 并打破我的主机。基本上我想使用系统库/工具,但限制/chroot 只输出到特定的workdir,这样我就可以避免为此预先构建一个 chroot。一个可行的解决方案是使用FreeBSD jail,但我想知道是否有替代/安全的方法来做到这一点,而无需容器、虚拟机等;并使用基本的 Mac OS X 工作站。这样任何人都可以“安全地”运行和测试而无需担心。有任何想法吗 ?
查看完整描述

1 回答

?
杨__羊羊

TA贡献1943条经验 获得超7个赞

使用 os.Setuid/os.Setgid (example.go) 应该没问题:


package main


import (

    "log"

    "flag"

    "os"

    "os/exec"

    "syscall"

)


func main() {

    var oUid = flag.Int("uid", 0, "Run with User ID")

    var oGid = flag.Int("gid", 0, "Run with Group ID")

    flag.Parse()


    // Get UID/GUID from args

    var uid = *oUid

    var gid = *oGid


    // Run whoami

    out, err := exec.Command("whoami").Output()

    if err != nil {

        log.Fatal(err)

        return

    }


    // Output whoami

    log.Println("Original UID/GID whoami:", string(out))

    log.Println("Setting UID/GUID")


    // Change privileges

    err = syscall.Setgid(gid)

    if err != nil {

        log.Println("Cannot setgid")

        log.Fatal(err)

        return

    }


    err = syscall.Setuid(uid)

    if err != nil {

        log.Println("Cannot setuid")

        log.Fatal(err)

        return

    }


    // Execute whoami again

    out, err = exec.Command("whoami").Output()

    if err != nil {

        log.Fatal(err)

        return

    }

    log.Println("Changed UID/GID whoami:", string(out))



    // Do some dangerous stuff

    log.Println("Creating a executable file within /bin should fail...")

    _, err = os.Create("/bin/should-fail")

    if err == nil {

        log.Println("Warning: operation did not fail")

        return

    }


    log.Println("We are fine", err)

}

我还建议阅读有关正确设置 gid/uid 的信息(https://unix.stackexchange.com/questions/166817/using-the-setuid-bit-properly,在 C 中)。哦!它需要在 uid 之前设置 gid,因为如果您不这样做,示例将失败。


您应该example.go以 root 权限执行,并分别使用标志 -gid、-uid 为命令指定非特权 gid/uid。


sudo go run example.go -uid <unprivileged id> -gid <unprivileged id>


查看完整回答
反对 回复 2021-12-20
  • 1 回答
  • 0 关注
  • 147 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信