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

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


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 工作站。这样任何人都可以“安全地”运行和测试而无需担心。


有任何想法吗 ?


慕神8447489
浏览 148回答 1
1回答

杨__羊羊

使用 os.Setuid/os.Setgid (example.go) 应该没问题:package mainimport (&nbsp; &nbsp; "log"&nbsp; &nbsp; "flag"&nbsp; &nbsp; "os"&nbsp; &nbsp; "os/exec"&nbsp; &nbsp; "syscall")func main() {&nbsp; &nbsp; var oUid = flag.Int("uid", 0, "Run with User ID")&nbsp; &nbsp; var oGid = flag.Int("gid", 0, "Run with Group ID")&nbsp; &nbsp; flag.Parse()&nbsp; &nbsp; // Get UID/GUID from args&nbsp; &nbsp; var uid = *oUid&nbsp; &nbsp; var gid = *oGid&nbsp; &nbsp; // Run whoami&nbsp; &nbsp; out, err := exec.Command("whoami").Output()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; // Output whoami&nbsp; &nbsp; log.Println("Original UID/GID whoami:", string(out))&nbsp; &nbsp; log.Println("Setting UID/GUID")&nbsp; &nbsp; // Change privileges&nbsp; &nbsp; err = syscall.Setgid(gid)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Println("Cannot setgid")&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; err = syscall.Setuid(uid)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Println("Cannot setuid")&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; // Execute whoami again&nbsp; &nbsp; out, err = exec.Command("whoami").Output()&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal(err)&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; log.Println("Changed UID/GID whoami:", string(out))&nbsp; &nbsp; // Do some dangerous stuff&nbsp; &nbsp; log.Println("Creating a executable file within /bin should fail...")&nbsp; &nbsp; _, err = os.Create("/bin/should-fail")&nbsp; &nbsp; if err == nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Println("Warning: operation did not fail")&nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; }&nbsp; &nbsp; 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>
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go