2013-01-09 15 views
7

我以root用户身份登录到终端。无法使用python切换回root用户

然后在Python:

os.setuid(471)能够切换到子根,但是当我试图用os.setuid(0)我收到以下错误切换到root用户:Operation not permitted

请让我知道如何从subroot切换回root用户。

+0

你的意思下的子根? – Denis

回答

8

这不是setuid的工作原理。当根本降级时,根本无法重新获得根。一旦你放弃了根(在这种情况下),它就消失了。

如果以root身份使用setuid,则无法返回。

我假设os.setuid是通过C级调用的瘦代理。从man页:

If the user is root or the program is set-user-ID-root, special care must be taken. The setuid() function checks the effective user ID of the caller and if it is the superuser, all process-related user ID's are set to uid. After this has occurred, it is impossible for the program to regain root privileges.


至于为什么根本无法reobtained,考虑一个典型的应用。假设一个Apache服务器下降到www(或某种非特权用户)来处理实际的请求。如果你可以重新获得root权限,Python脚本(或者PHP/Perl/CGI /等)可以重新获得根目录并造成绝对的破坏。


至于解决的办法,你可以改用个seteuid(os.seteuid - 再次,一个简单的代理通过C级seteuid)。关于setuid和seteuid的python文档看起来很糟糕,但系统调用中有大量的文档。

至于暂时掉落根和恢复的安全性...您需要非常小心。如果恶意代码有机会获得根源,那么就搞砸了。出于这个原因,最好分叉到一个子进程(如user4815162342建议)。子进程将无法重新生成。关于这些问题的更多信息可以参考here。关于setuid的一般奇怪的更多信息是here

这个想法是用seteuid设置有效的用户ID并产生一个新的进程。由于exec的工作方式,有效的用户ID将被复制到新进程的已保存uid中。由于已保存的uid不再是root,所以root不能再变回。更多有趣的文档可以在here找到。

最相关的部分:

If the set-user-ID bit is set on the program file pointed to by filename, and the underlying file system is not mounted nosuid (the MS_NOSUID flag for mount(2)), and the calling process is not being ptraced, then the effective user ID of the calling process is changed to that of the owner of the program file. Similarly, when the set-group-ID bit of the program file is set the effective group ID of the calling process is set to the group of the program file.

The effective user ID of the process is copied to the saved set-user-ID; similarly, the effective group ID is copied to the saved set-group-ID. This copying takes place after any effective ID changes that occur because of the set-user-ID and set-group-ID permission bits.

9

呼叫os.fork()并切换到子进程的非root用户。只需退出孩子并等待孩子退出父母,就可以“切换回”。例如:

pid = os.fork() 
if pid == 0: 
    # child - do the work and exit 
    try: 
     os.setuid(471) 
     ... do the work here 
    finally: 
     os._exit(0) 

# parent - wait for the child to do its work and keep going as root 
os.waitpid(pid, 0) 
+0

os.waitpid需要两个参数,一个给出 – answerSeeker

+0

@answerSeeker已修复,谢谢 – user4815162342

3

使用个seteuid(),而不是设置有效ID,但维持特权:

import os 
os.seteuid(471) 
... 
os.seteuid(os.getuid()) 
相关问题