Python: Securing untrusted scripts/subprocess with chroot and chjail?

前端 未结 2 656
旧巷少年郎
旧巷少年郎 2021-02-13 21:34

I\'m writing a web server based on Python which should be able to execute \"plugins\" so that functionality can be easily extended.

For this I considered the approach to

相关标签:
2条回答
  • 2021-02-13 22:03

    After creating your jail you would call os.chroot from your Python source to go into it. But even then, any shared libraries or module files already opened by the interpreter would still be open, and I have no idea what the consequences of closing those files via os.close would be; I've never tried it.

    Even if this works, setting up chroot is a big deal so be sure the benefit is worth the price. In the worst case you would have to ensure that the entire Python runtime with all modules you intend to use, as well as all dependent programs and shared libraries and other files from /bin, /lib etc. are available within each jailed filesystem. And of course, doing this won't protect other types of resources, i.e. network destinations, database.

    An alternative could be to read in the untrusted code as a string and then exec code in mynamespace where mynamespace is a dictionary defining only the symbols you want to expose to the untrusted code. This would be sort of a "jail" within the Python VM. You might have to parse the source first looking for things like import statements, unless replacing the built-in __import__ function would intercept that (I'm unsure).

    0 讨论(0)
  • 2021-02-13 22:09

    Perhaps something like this?

    # main.py
    subprocess.call(["python", "pluginhandler.py", "plugin", env])
    

    Then,

    # pluginhandler.py
    os.chroot(chrootpath)
    os.setgid(gid) # Important! Set GID first! See comments for details.
    os.setuid(uid)
    os.execle(programpath, arg1, arg2, ..., env)
    # or another subprocess call 
    subprocess.call["python", "plugin", env])
    

    EDIT: Wanted to use fork() but I didn't really understand what it did. Looked it up. New code!

    # main.py
    import os,sys
    somevar = someimportantdata
    pid = os.fork()
    if pid:
        # this is the parent process... do whatever needs to be done as the parent
    else:
        # we are the child process... lets do that plugin thing!
        os.setgid(gid) # Important! Set GID first! See comments for details.
        os.setuid(uid)
        os.chroot(chrootpath)
        import untrustworthyplugin
        untrustworthyplugin.run(somevar)
        sys.exit(0)
    

    This was useful and I pretty much just stole that code, so kudos to that guy for a decent example.

    0 讨论(0)
提交回复
热议问题