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 超声波模块测距控制点灯,灯的闪烁很不稳定,经过调试发现测的距离偏大
  • ¥15 import arcpy出现importing _arcgisscripting 找不到相关程序
  • ¥15 onvif+openssl,vs2022编译openssl64
  • ¥15 iOS 自定义输入法-第三方输入法
  • ¥15 很想要一个很好的答案或提示
  • ¥15 扫描项目中发现AndroidOS.Agent、Android/SmsThief.LI!tr
  • ¥15 怀疑手机被监控,请问怎么解决和防止
  • ¥15 Qt下使用tcp获取数据的详细操作
  • ¥15 idea右下角设置编码是灰色的
  • ¥15 全志H618ROM新增分区