即使在seteuid之后,也无法在python中删除root priv.一个bug?

tei*_*ura 4 python privilege

即使在seteuid之后,也无法在python中删除root priv.一个bug?

编辑摘要:我忘了放弃gid.但是,接受的答案可能对你有所帮助.

你好.我不能在我的linux上删除python 3.2中的root权限.实际上,即使在seteuid(1000)之后,它也可以读取root拥有的400模式文件.euid肯定会设置为1000!

我发现在空的os.fork()调用之后,正确拒绝了特权访问.(但它只在父母身上.孩子仍然可以非法阅读.)这是python中的错误,还是linux?

请尝试下面的代码.注释掉底部的三行中的一行,并以root身份运行.

先谢谢.

#!/usr/bin/python3

# Python seteuid pitfall example.
# Run this __as__ the root.

# Here, access to root-owned files /etc/sudoers and /etc/group- are tried.
# Simple access to them *succeeds* even after seteuid(1000) which should fail.

# Three functions, stillRoot(), forkCase() and workAround() are defined.
# The first two seem wrong. In the last one, access fails, as desired.


# ***Comment out*** one of three lines at the bottom before execution.

# If your python is < 3.2, comment out the entire def of forkCase()

import os

def stillRoot():
    """Open succeeds, but it should fail."""
    os.seteuid(1000)
    open('/etc/sudoers').close()

def forkCase():
    """Child can still open it. Wow."""
    # setresuid needs python 3.2
    os.setresuid(1000, 1000, 0)
    pid = os.fork()
    if pid == 0:
        # They're surely 1000, not 0!
        print('uid: ', os.getuid(), 'euid: ', os.geteuid())
        open('/etc/sudoers').close()
        print('open succeeded in child.')
        exit()
    else:
        print('child pid: ', pid)
        open('/etc/group-').close()
        print('parent succeeded to open.')

def workAround():
    """So, a dummy fork after seteuid is necessary?"""
    os.seteuid(1000)
    pid = os.fork()
    if pid == 0:
        exit(0)
    else:
        os.wait()

    open('/etc/group-').close()

## Run one of them.

# stillRoot()
# forkCase()
# workAround()
Run Code Online (Sandbox Code Playgroud)

Rak*_*kis 6

在Unix系统上操作进程凭据非常棘手.我强烈建议您彻底了解Real,Effective和Saved-Set用户ID是如何相互关联的.搞砸"删除权限"非常容易.

至于你的具体观察......我想知道是否有一个你可能忽略的简单原因.您的代码正在执行不一致的测试,并且您忽略了在您/etc/sudoers和/etc/group-文件上指定确切的文件权限.如果/etc/sudoers权限模式= 440,uid = root,gid = root(这是我系统的默认权限)以及/etc/group-模式= 400 ,那么您的预期行为将完全如您所描述的那样.

你没有修改进程的GID,所以如果/etc/sudoers是组可读的,那就可以解释为什么它总是可读的.fork()不会修改进程凭据.但是,您可能会在示例代码中执行此操作,因为您正在检查父级和子级中的不同文件.如果/etc/group-没有组读取权限/etc/sudoers,那将解释明显的问题.

如果你要做的只是"删除权限",请使用以下代码:

os.setgid( NEW_GID )
os.setuid( NEW_UID )
Run Code Online (Sandbox Code Playgroud)

一般来说,如果您的流程需要在流程的整个生命周期内打开和关闭其root权限,那么您只需要操纵有效的用户ID.如果您只需要使用root权限进行一些设置操作,但在完成这些设置操作后将不再需要它们,只需使用上面的代码就可以不可撤销地删除它们.

哦,Linux上进程凭证操作的一个有用的调试实用程序是打印输出/proc/self/status,该文件的Uid和Gid行显示当前进程持有的真实,有效,保存集和文件ID(按此顺序) ).Python API可用于检索相同的信息,但您可以将此文件的内容视为"真实数据",并避免Python跨平台API的任何潜在复杂情况.