简体   繁体   English

这是(Python)脚本的安全suid /功能包装器吗?

[英]Is this a safe suid/capability wrapper for (Python) scripts?

(Note: I've Linux in mind, but the problem may apply on other platforms.) (注意:我考虑过Linux,但该问题可能适用于其他平台。)

Problem: Linux doesn't do suid on #! 问题: Linux在#上不执行suid! scripts nor does it activate “Linux capabilities” on them. 脚本也不会激活脚本上的“ Linux功能”。

Why dow we have this problem? 为什么我们有这个问题? Because during the kernel interpreter setup to run the script, an attacker may have replaced that file. 因为在内核解释程序安装过程中运行脚本,所以攻击者可能已替换了该文件。 How? 怎么样? The formerly trusted suid/capability-enabled script file may be in a directory he has control over (eg can delete the not-owned trusted file, or the file is actually a symbolic link he owns). 以前受信任的启用suid /功能的脚本文件可以位于他可以控制的目录中(例如可以删除不拥有的受信任文件,或者该文件实际上是他拥有的符号链接)。

Proper solution: make the kernel allow suid/cap scripts if: a) it is clear that the caller has no power over the script file -or- like a couple of other operating systems do b) pass the script as /dev/fd/x, referring to the originally kernel-opened trusted file. 正确的解决方案:以下情况下,使内核允许suid / cap脚本:a)很明显,调用者无法控制脚本文件-或-像其他几个操作系统一样,b)将脚本作为/ dev / fd /传递x,指最初由内核打开的受信任文件。

Answer I'm looking for: for kernels which can't do this (all Linux), I need a safe “now” solution. 我正在寻找答案:对于无法做到这一点的内核(所​​有Linux),我需要一个安全的“现在”解决方案。

What do I have in mind? 我有什么想法 A binary wrapper, which does what the kernel does not, in a safe way. 二进制包装程序,以安全的方式执行内核不执行的操作。

I would like to 我想要

  1. hear from established wrappers for (Python) scripts that pass Linux capabilities and possibly suid from the script file to the interpreter to make them effective. 从已建立的(Python)脚本包装程序中听到,这些脚本将Linux功能以及suid从脚本文件传递到解释器以使其有效。
  2. get comments on my wrapper proposed below 在下面提出的我的包装上获取评论

Problems with sudo : sudo is not a good wrapper, because it doesn't help the kernel to not fall for that just explained “script got replaced” trap (“man sudo” under caveats says so). sudo的问题 :sudo并不是一个很好的包装器,因为它不能帮助内核避免因为刚才解释的“脚本被替换”陷阱(注意事项下的“ man sudo”这样说)而崩溃。


Proposed wrapper 建议的包装

  • actually, I want a little program, which generates the wrapper 实际上,我想要一个小程序,它生成包装器
    • command line, eg: sudo suid_capability_wrapper ./script.py 命令行,例如:sudo suid_capability_wrapper ./script.py
    • script.py has already the suid bit and capabilites set (no function, just information) script.py已经设置了suid位和功能(无功能,仅提供信息)
  • the generator suid_capability_wrapper does 生成器suid_capability_wrapper可以
    • generate C(?) source and compile 生成C(?)源并进行编译
    • compile output into: default: basename script.py .py , or argument -o 将输出编译为:默认: basename script.py .py或参数-o
    • set the wrapper owner, group, suid like script.py 设置包装所有者,组,suid(如script.py)
    • set the permitted capabilities like script.py, ignore inheritable and effective caps 设置允许的功能,例如script.py,忽略可继承的有效上限
    • warn if the interpreter (eg /usr/bin/python) does not have the corresponding caps in its inheritable set (this is a system limitation: there is no way to pass on capabilites without suid-root otherwise) 如果解释器(例如/ usr / bin / python)在其可继承集中没有对应的大写,则发出警告(这是系统限制:如果没有suid-root,则无法传递功能)
  • the generated code does: 生成的代码可以:
    • check if file descriptors 0, 1 and 2 are open, abort otherwise (possibly add more checks for too crazy environment conditions) 检查文件描述符0、1和2是否打开,否则中止(可能为过于疯狂的环境添加更多检查)
    • if compiled-in target script is compiled-in with relative path, determine self's location via /proc/self/exe 如果编译的目标脚本是使用相对路径编译的,请通过/ proc / self / exe确定自身的位置
    • combine own path with relative path to the script to find it 结合自己的路径和脚本的相对路径来找到它
    • check if target scripts owner, group, permissions, caps, suid are still like the original (compiled-in) [this is the only non-necessary safety-check I want to include: otherwise I trust that script] 检查目标脚本的所有者,组,权限,大写字母,suid是否仍与原始(内置)一样[这是我想包括的唯一不必要的安全检查:否则,我相信该脚本]
    • set the set of inherited capabilities equal to the set of permitted capabilities 将继承的功能设置为等于允许的功能设置
    • execve() the interpreter similar to how the kernel does, but use the script-path we know, and the environment we got (the script should take care of the environment) execve()解释器类似于内核的工作方式,但是使用我们知道的脚本路径和我们所获得的环境(脚本应照顾环境)

A bunch of notes and warnings may be printed by suid_capability_wrapper to educate the user about: suid_capability_wrapper可能会打印大量注释和警告,以使用户了解以下内容:

  • make sure nobody can manipulate the script (eg world writable) 确保没有人可以操纵脚本(例如可写的世界)
  • be aware that suid/capabilities come from the wrapper, nothing cares about suid/xattr mounts for the script file 请注意,suid /功能来自包装程序,因此无需关心脚本文件的suid / xattr挂载
  • the interpreter (python) is execve()ed, it will get a dirty environment from here 解释器(python)被执行,它将从这里得到一个肮脏的环境
  • it will also get the rest of the standard process environment passed through it, which is ... ... ... (read man-pages for exec to begin with) 它还将获得通过它的其余标准过程环境,即……(请阅读exec的手册页开头)
  • use #!/usr/bin/python -E to immunize the python interpreter from environment variables 使用#!/ usr / bin / python -E从环境变量中清除python解释器
  • clean the environment yourself in the script or be aware that there is a lot of code you run as side-effect which does care about some of these variables 自己在脚本中清理环境,或者意识到有很多副作用代码在运行,这些代码确实会影响其中的一些变量

You don't want to use a shebang at all , on any file - you want to use a binary which invokes the Python interpreter, then tells it to start the script file for which you asked. 你不想使用认领所有,任何文件-你想用它调用Python解释器的二进制,然后告诉它开始为您问的脚本文件。

It needs to do three things: 它需要做三件事:

  • Start a Python interpreter (from a trusted path, breaking chroot jails and so on). 启动Python解释器(从受信任的路径,破坏chroot监狱等等)。 I suggest statically linking libpython and using the CPython API for this, but it's up to you. 我建议静态链接libpython并为此使用CPython API,但这取决于您。
  • Open the script file FD and atomically check that it is both suid and owned by root. 打开脚本文件FD,并自动检查它是否为suid并由root拥有。 Don't allow the file to be altered between the check and the execution - be careful. 不允许在检查和执行之间更改文件-小心。
  • Tell CPython to execute the script from the FD you opened earlier. 告诉CPython从您先前打开的FD执行脚本。

This will give you a binary which will execute all owned-by-root-and-suid scripts under Python only . 这将为您提供一个二进制文件,该二进制文件将仅在Python下执行所有由root和suid拥有的脚本。 You only need one such program, not one per script. 您只需要一个这样的程序,而不需要每个脚本一个。 It's your "suidpythonrunner". 这是您的“ suidpythonrunner”。

As you surmised, you must clear the environment before running Python. 如您所料,您必须在运行Python之前清除环境。 LD_LIBRARY_PATH is taken care of by the kernel, but PYTHONPATH could be deadly. LD_LIBRARY_PATH由内核处理,但是PYTHONPATH可能是致命的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM