dongyuruan2957 2014-09-30 02:16
浏览 39
已采纳

是否有可能突破受限(自定义)外壳?

Not sure if this is the right place to ask.

Say I write a shell that takes stdin input, filters this input so let's say only certain commands like

  • ls (list contents of binary directory and subdirectory)
  • update (git clone)
  • build (go build)
  • test (go test)
  • start (systemctl start this.service only)
  • stop (systemctl stop this.service only)
  • running (is the binary being executed and with how many GOMAXPROCS?)
  • usage (memory, cpu usage)
  • gensvc (generate .service file)
  • exit (leave shell/logout)

work, you guessed it, I'm trying to give a user only very limited maintenance access over ssh.

Say I'm careful with \0 (I'd write it in Go anyway using bufio.Scanner)

Is there any way to stop the running shell and execute /bin/sh or similar or any way to get around this shell?

The idea is a user should push their stuff via git to a bare repo, this repo is cloned to the filesystem to a certain directory, then go build is called and the binary is ran with a systemd .service file that is generated previously.

Thinking logically, if the user is only able to write certain strings that are accepted, no there is no way. But maybe you know of one, some ctrl+z witchcraft ;) or whatever.

The only attack surface is the input string or rather bytes. Of course the user could git push a program that builds its own shell or runs certain commands, but that's out of scope (I would remove capabilities with systemd and restrict device access and forbid anything but the connection to the database server, private tmp and all, namespace and subnamespace it TODO)

The only problem I see is git pushing but I'm sure I could work around that in a git only mode argv and adding it to ~/.ssh/authorized_keys. something like lish gitmode and execute stdin commands if they start with git or something like it.

Example:

https://gist.github.com/dalu/ce2ef43a2ef5c390a819

  • 写回答

3条回答

  • dongmo8943 2014-09-30 03:32
    关注

    If you're only allowed certain commands, your "shell" will read the command, parse it and then execute it then you should be fine, unless I misunderstood it.

    Go "memory" can't be executed, not without you doing some nasty hacks with assembly anyway, so you don't have to worry about shell injection.

    Something along these lines should be safe:

    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
            }
        }
    } 
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100