即使在seteuid之后,也无法在python中删除root priv。一个错误?
编辑摘要:我忘了放弃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()
答案 0 :(得分: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 )
一般来说,如果您的流程需要在流程的整个生命周期内打开和关闭其root权限,那么您只需要操纵有效的用户ID。如果您只需要使用root权限进行一些设置操作,但在完成这些设置操作后将不再需要它们,只需使用上面的代码就可以不可撤销地删除它们。
哦,Linux上用于进程凭据操作的有用调试实用程序是打印/proc/self/status
的输出,此文件的Uid和Gid行显示真实,有效,已保存集和文件ID按当前流程(按此顺序)。 Python API可用于检索相同的信息,但您可以将此文件的内容视为“真实数据”,并避免Python跨平台API的任何潜在复杂情况。