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

时间:2016-03-12 19:17:29

标签: macos go chroot

我想测试/自动化一些存储库,基本流程类似于:

repos := []string{"repo 1", "repo 2", ...}
for r := range repos {
    // git clone the repo 
    // cd repo dir
    // make test
    // make build
    // ...
}

我正在使用forceMkdir()使用os.exec来调用所有系列命令,例如:

 exec.Command("sh", "-c", "git clone project")

到目前为止一直很好,但我想知道是否有办法保护/防止Makefile上的错误写入可能会像rm -rf /这样做。并打破我的主人。

基本上我想使用系统库/工具,但是只将输出限制/ chroot到特定的workdir,这样我就可以避免为此预先构建一个chroot。

一个可行的解决方案是使用GO,但我想知道是否有替代/安全的方式来做这个而不需要容器,virtualbox等;并使用基本的Mac OS X工作站。这样任何人都可以安全地#34;跑步&毫无后顾之忧。

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

你应该没问题使用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,因为如果您不这样做,示例将失败。

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

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