Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to switch back to root user using python

Tags:

python

I logged in to terminal as root user.

Then in Python:

os.setuid(471) is able to switch to subroot but when I am trying to switch back to root user using os.setuid(0) I am getting the following error: Operation not permitted

Please let me know how to switch back to root user from subroot.

like image 396
Rajesh Kumar Avatar asked Jan 09 '13 07:01

Rajesh Kumar


2 Answers

Call os.fork() and switch to the non-root user in the child process. "Switch back" simply by exiting in the child and waiting for the child to exit in the parent. For example:

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)
like image 98
user4815162342 Avatar answered Oct 06 '22 16:10

user4815162342


That's not how setuid works. When root demote itself, it's by design that root cannot be reobtained. Once you give up root (in this context), it's gone.

If you use setuid as root, you cannot go back.

I'm assuming os.setuid is a thin proxy through to the C level call. From the man page:

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.


As for why root cannot be reobtained, consider a typical use. Imagine an Apache server that drops down to www (or some kind of non-privileged user) to handle actual requests. If you could regain root, a Python script (or PHP/Perl/CGI/etc), could regain root and wreak absolute havoc.


As for a solution, you can use seteuid instead (os.seteuid -- once again, a simple proxy through to C-level seteuid). The python documentation on setuid and seteuid looks pretty bad, but there's tons of documentation on the system calls.

As for the security of temporarily dropping root and regaining... You'll need to be very careful. If malicious code has the opportunity to gain root, you're screwed. For this reason, it's a good idea to fork into a child process (as user4815162342 suggested). The child process will not be able to re-root. More about the concerns can be found here. More about the general oddness of setuid is here.

The idea is to set the effective user id with seteuid and spawn a new process. Because of the way exec works, the effective user id will be copied into the saved uid of the new process. Since the saved uid is no longer root, root cannot be changed back into. Yet more fun documentation can be found here.

The most relevant parts:

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.

like image 34
Corbin Avatar answered Oct 06 '22 16:10

Corbin