Linux 有可能突破限制(自定义)外壳吗?

Linux 有可能突破限制(自定义)外壳吗?,linux,shell,security,go,Linux,Shell,Security,Go,不确定这是不是该问的地方 假设我写了一个shell,它接受stdin输入,过滤这个输入,所以我们只说某些命令,比如 ls(列出二进制目录和子目录的内容) 更新(git克隆) 构建(go-build) 测试(go测试) 启动(仅限systemctl启动此服务) 停止(仅限systemctl stop this.service) 正在运行(正在执行二进制文件,有多少个gomaxproc?) 使用率(内存、cpu使用率) gensvc(生成.service文件) 退出(离开外壳/注销) 工作,您猜

不确定这是不是该问的地方

假设我写了一个shell,它接受stdin输入,过滤这个输入,所以我们只说某些命令,比如

  • ls(列出二进制目录和子目录的内容)
  • 更新(git克隆)
  • 构建(go-build)
  • 测试(go测试)
  • 启动(仅限systemctl启动此服务)
  • 停止(仅限systemctl stop this.service)
  • 正在运行(正在执行二进制文件,有多少个gomaxproc?)
  • 使用率(内存、cpu使用率)
  • gensvc(生成.service文件)
  • 退出(离开外壳/注销)
工作,您猜对了,我试图通过ssh为用户提供非常有限的维护访问权限

说我很小心使用
\0
(无论如何我都会使用bufio.Scanner用Go编写)

是否有任何方法停止运行shell并执行/bin/sh或类似命令,或者有任何方法绕过此shell

这个想法是用户应该通过git将他们的东西推送到一个裸repo,这个repo被克隆到文件系统的某个目录,然后调用go build,并使用先前生成的systemd.service文件运行二进制文件

从逻辑上考虑,如果用户只能编写被接受的特定字符串,那么没有办法。但也许你知道一个,一些ctrl+z巫术;)或者别的什么

唯一的攻击面是输入字符串或字节。当然,用户可以git推送一个构建自己的shell或运行某些命令的程序,但这超出了范围(我会删除systemd的功能,限制设备访问,禁止任何东西,但不允许连接到数据库服务器、专用tmp和all、命名空间和子命名空间)

我看到的唯一问题是git推送,但我相信我可以在仅git模式argv中解决这个问题,并将其添加到~/.ssh/authorized_密钥中。类似于
lish gitmode
的东西,如果以git或类似的东西开头,则执行stdin命令

例如:


如果只允许您使用某些命令,您的“shell”将读取命令,解析它,然后执行它,那么您应该没事,除非我误解了它

Go“内存”无法执行,除非您对汇编进行了一些讨厌的黑客攻击,所以您不必担心shell注入

沿着这些路线应该是安全的:

func getAction() (name string, args []string) {
    // read stdin to get the command of the user
}

func doAction() {
    for {
        action, args := getAction()
        switch action {
            case "update": //let's assume the full command is: update https://repo/path.git
                if len(args) != 1 {
                    //error
                }
                out, err := exec.Command("/usr/bin/git", "clone", "--recursive", args[0]).CombinedOutput()
                // do stuff with out and err
        }
    }
} 

如果您只允许使用某些命令,您的“shell”将读取命令,解析它,然后执行它,那么您应该不会有问题,除非我误解了它

Go“内存”无法执行,除非您对汇编进行了一些讨厌的黑客攻击,所以您不必担心shell注入

沿着这些路线应该是安全的:

func getAction() (name string, args []string) {
    // read stdin to get the command of the user
}

func doAction() {
    for {
        action, args := getAction()
        switch action {
            case "update": //let's assume the full command is: update https://repo/path.git
                if len(args) != 1 {
                    //error
                }
                out, err := exec.Command("/usr/bin/git", "clone", "--recursive", args[0]).CombinedOutput()
                // do stuff with out and err
        }
    }
} 

如果您自己实现shell,并通过
exec()
直接执行命令或在内部实现命令,那么当然可以生成一个安全的受限shell。如果您只是在将命令行传递给真正的shell之前对其进行表面检查,那么可能会出现一些您意想不到的边缘情况


话虽如此,我还是有点担心您列出的
test
命令。是否打算运行用户上传的Go包的测试套件?如果是这样的话,如果我是一名攻击者,我甚至不会尝试利用受限shell:我只需上传一个包含执行我想要的操作的测试的包。对于
build
/
start

也可以这样说,如果您自己实现shell,并通过
exec()
直接执行命令或在内部实现命令,那么当然可以生成安全的受限shell。如果您只是在将命令行传递给真正的shell之前对其进行表面检查,那么可能会出现一些您意想不到的边缘情况


话虽如此,我还是有点担心您列出的
test
命令。是否打算运行用户上传的Go包的测试套件?如果是这样的话,如果我是一名攻击者,我甚至不会尝试利用受限shell:我只需上传一个包含执行我想要的操作的测试的包。对于
构建
/
开始

也可以这样说,让pentesting团队对其进行审查


当人们打开任何类型的沙箱时,他们都会很有创造力。只有当你不接受用户的输入时,你可以认为自己在安全的前提下(但这里任何命令都是输入)——纸安全假设被认为是评估软件的弱点。它们类似于纸上算法的“无缺陷”假设:一旦你实现了它,99%的错误出现的时间都会由pentesting团队进行审查


当人们打开任何类型的沙箱时,他们都会很有创造力。只有当你不接受用户的输入时,你可以认为自己在安全的前提下(但这里任何命令都是输入)——纸安全假设被认为是评估软件的弱点。它们类似于纸上算法的“无bug”假设:一旦你实现了它,99%的bug会出现

不要让他们使用像
vim
这样的编辑器;一旦他们使用了
vim
,他们就可以访问shell,然后访问任何他们喜欢的地方。你没有提到编辑,所以你可能没事。一定要特别注意build和test命令可能执行的操作。@JonathanLeffler
vim
如果以
vim-Z
@fuzzxl:interest启动,应该是安全的;是的,
vim-Z
似乎减少了一些选项。原始的
vi
没有被很好地包含。至少,你必须非常小心地允许编辑。如果安全是一个问题,也许你应该考虑使用一个标准的受限shell(例如<代码> RBASH ),并集中精力去正确地配置它。如果你允许用<代码> G来运行代码。