【问题标题】:Launch child process as root (python, setuid, MacOS)以 root 身份启动子进程(python、setuid、MacOS)
【发布时间】:2022-10-16 11:48:52
【问题描述】:

如何启动具有 root 权限的子进程?

我在 MacOS 中有一个 python 程序,它可以作为普通用户执行大部分操作。但有时,由于某些用户交互触发,它需要 root 权限才能执行任务。

出于安全原因,我不希望整个 GUI 应用程序以 root 身份启动并运行。我只想要一个具有极少功能子集的子进程以 root 身份运行。

出于用户体验的原因,我不想告诉用户“对不起,请以管理员身份重新启动这个应用程序”。我希望能够让他们留在 GUI 中,并出现一个弹出窗口,上面写着“呃,你需要 root 才能做到这一点。请输入你的密码。”

当然,如果我的非特权 python 进程尝试成为 root

setuid(0)

...然后我得到一个权限错误

PermissionError: [Errno 1] Operation not permitted

我可以使用什么作为setuid() 的替代品,以便在通过 GUI 中的用户进行身份验证来提升权限后,我可以在 MacOS 系统上启动新的子进程?

【问题讨论】:

  • 您可以使用subprocess.check_exec("sudo .<program to run as root> <arg1> <arg2>...);,但您必须弄清楚如何让sudo 接受您从用户那里获得的密码,因为它本身无法向您的用户询问他们的密码。
  • 我认为我的应用程序获取用户密码并将其传递给操作系统是一个非首发。我不应该知道用户的密码。我应该要求操作系统得到它。

标签: python macos root setuid


【解决方案1】:

我希望能够让他们留在 GUI 中,并出现一个弹出窗口,上面写着“呃,你需要 root 才能做到这一点。请输入你的密码。”

这正是 MacOS API 的 AuthorizationExecuteWithPrivileges() 函数的创建目的。

你可以直接用python的ctypes调用AuthorizationExecuteWithPrivileges()

例如,假设您的父脚本以您的普通非 root 用户身份运行。如果您尝试只运行setuid(0),那么它将失败

PermissionError: [Errno 1] Operation not permitted

相反,让我们创建另一个名为root_child.py 的脚本,我们将使用AuthorizationExecuteWithPrivileges() 以root 身份执行它

孩子(root_child.py)

#!/usr/bin/env python3
import os

if __name__ == "__main__":
   try:
      os.setuid(9)
      print( "I am root!" )
   except Exception as e:
      print( "I am not root :'(" )

父级 (spawn_root.py)

我们可以从我们的非root脚本spawn_root.py以root身份执行上述root_child.py脚本:

import sys, ctypes, struct
import ctypes.util
from ctypes import byref

# import some C libraries for interacting via ctypes with the MacOS API
libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c"))

# https://developer.apple.com/documentation/security
sec = ctypes.cdll.LoadLibrary(ctypes.util.find_library("Security"))

kAuthorizationFlagDefaults = 0
auth = ctypes.c_void_p()
r_auth = byref(auth)
sec.AuthorizationCreate(None,None,kAuthorizationFlagDefaults,r_auth)

exe = [sys.executable,"root_child.py"]
args = (ctypes.c_char_p * len(exe))()
for i,arg in enumerate(exe[1:]):
    args[i] = arg.encode('utf8')

io = ctypes.c_void_p()

print( "running root_child.py")
err = sec.AuthorizationExecuteWithPrivileges(auth,exe[0].encode('utf8'),0,args,byref(io))
print( "err:|" +str(err)+ "|" )
print( "root_child.py executed!")

【讨论】:

    猜你喜欢
    • 2013-06-09
    • 1970-01-01
    • 2014-01-22
    • 2014-10-12
    • 2010-10-08
    • 2013-11-23
    • 2021-02-27
    • 1970-01-01
    • 2021-02-26
    相关资源
    最近更新 更多