2

我的要求

我的 python 服务器在 RHEL 上作为普通用户运行,但它需要在它无法访问的地方创建文件/目录。还需要使用随机 UID/GID 对那些文件进行 chown

我的方法

在仅功能环境中尝试此操作,没有 setuid。我正在尝试利用 cap_chown 和 cap_dac_override 功能。但是我完全不知道如何让它在 systemctl 那种环境中工作

目前我在服务文件中有以下内容:

#cat /usr/lib/systemd/system/my_server.service 

[Service]
Type=simple
SecureBits=keep-caps
User=testuser
CapabilityBoundingSet=~
Capabilities=cap_dac_override,cap_chown=eip
ExecStart=/usr/bin/linux_capability_test.py

并遵循二进制本身:

# getcap /usr/bin/linux_capability_test.py
/usr/bin/linux_capability_test.py = cap_chown,cap_dac_override+ei

但是这里说,它永远不会在脚本上工作: 有没有办法让非 root 进程绑定到 Linux 上的“特权”端口?

在当前设置下,我对运行进程的能力是:

# ps -ef | grep lin
testuser    28268     1  0 22:31 ?        00:00:00 python /usr/bin/linux_capability_test.py

# getpcaps 28268
Capabilities for `28268': = cap_chown,cap_dac_override+i

但是,如果我尝试从该脚本中在 /etc/ 中创建文件:

try:
    file_name = '/etc/junk'
    with open(file_name, 'w') as f:
        os.utime(file_name,None)

它因“权限被拒绝”而失败

对我来说,它不起作用是同样的情况吗?我可以在这里使用 python-prctl 模块让它工作吗?

4

3 回答 3

0

根据我们上面的讨论,我做了以下事情:

[Service]
Type=simple
User=testuser
SecureBits=keep-caps
Capabilities=cap_chown,cap_dac_override=i
ExecStart=/usr/bin/linux_capability_test.py

这将启动具有这两种功能的服务器作为可继承的。

写了一个小C,测试代码到chown文件

#include <unistd.h>

int main()
  {
    int ret = 0;

    ret = chown("/etc/junk", 160, 160);

    return ret;
  }

在 gcc 的二进制文件上设置以下内容

chown testuser:testuser /usr/bin/chown_c
chmod 550 /usr/bin/chown_c
setcap cap_chown,cap_dac_override=ie /usr/bin/chown_c

服务器执行以下操作来调用二进制文件

import prctl
prctl.cap_inheritable.chown = True
prctl.cap_inheritable.dac_override = True
execve('/usr/bin/chown_c',[],os.environ)

我能够得到想要的结果

# ll /etc/junk 
-rw-r--r-- 1 root root 0 Aug  8 22:33 /etc/junk

# python capability_client.py 

# ll /etc/junk 
-rw-r--r-- 1 testuser testuser 0 Aug  8 22:33 /etc/junk
于 2015-08-08T17:16:09.843 回答
0

由于脚本的执行方式,setuid 不能用于脚本,因为它是一个安全漏洞。这方面有几个文件。您甚至可以从查看维基百科页面开始。

一个非常好的解决方法是编写一个小型 C 程序,该程序将启动您的 Python 脚本,其中包含 Python 和脚本的硬编码路径。可以在这里找到对所有问题的非常好的讨论

于 2015-08-08T02:50:22.683 回答
0

更新:一种方法来做到这一点,不确定是否是最好的。使用“python-prctl”模块:

1. Ditch 'User=testuser' from my-server.service
2. Start server as root
3. Set 'keep_caps' flag True
4. Do 'setgroups, setgid and setuid'
5. And immediately limit the permitted capability set to 'DAC_OVERRIDE' and 'CHOWN' capability only
6. Set the effective capability for both to True

这是相同的代码

import prctl

prctl.securebits.keep_caps = True

os.setgroups([160])
os.setgid(160)
os.setuid(160)

prctl.cap_permitted.limit(prctl.CAP_CHOWN, prctl.CAP_DAC_OVERRIDE)
prctl.cap_effective.dac_override = True
prctl.cap_effective.chown = True`

完毕 !!

于 2015-08-08T09:34:03.177 回答