【问题标题】:Is there a way to chroot/sandbox a go os.exec call (prevent rm -rf /)有没有办法 chroot/sandbox 一个 go os.exec 调用(防止 rm -rf /)
【发布时间】:2016-03-12 19:17:28
【问题描述】:

我想测试/自动化一些存储库,基本流程是这样的:

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

有什么想法吗?

【问题讨论】:

  • 您需要什么样的沙盒?您只需要对文件系统或网络套接字等其他东西进行沙箱处理?
  • 有一个叫做 syscall 的包,它有一个 Chroot 函数可以满足你的需要:golang.org/pkg/syscall
  • 我只需要文件系统的沙盒
  • @robbrit 我认为我没有正确使用 syscall/chroot 是否有机会分享一个示例?
  • 不幸的是,我从未使用过它,我只是在 Google 上搜索了一些可能会满足您的需求的东西。你必须自己测试一下。

标签: macos go chroot


【解决方案1】:

使用 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-28
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    • 2020-10-10
    • 2014-06-26
    • 1970-01-01
    相关资源
    最近更新 更多