The root character cannot be reset to python even after seteuid. Bug?

The root resource cannot be reset to python even after seteuid. Error?

EDIT Summary: I forgot to reset the gid. However, the accepted answer may help you.

Hey. I cannot drop the root privilege in python 3.2 on my Linux. In fact, even after seteuid (1000), it can read files in 400 mode with root privileges. Of course, the euid value is 1000!

I found that after an empty call to os.fork (), privileged access was correctly rejected. (But this is only in the parent. A child can still read illegally.) Is this a mistake in python or linux like that?

Try the code below. Comment on one of the three lines at the bottom and run it as root.

Thanks in advance.

#!/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() 
+4
source share
1 answer

Manipulating process credentials on Unix systems is difficult. I highly recommend getting a complete picture of how identifiers of real, effective, and stored sets are interconnected. It is very easy to drown out the "discarding privileges."

As for your specific observations ... I wonder if there is a simple reason that you may have missed. Your code first creates conflicting tests, and you did not specify the exact permissions for the files in /etc/sudoers and /etc/group- . Perhaps you could behave as described if /etc/sudoers has permission mode = 440, uid = root, gid = root (which are the default permissions for my system) and if /etc/group- has mode = 400.

You do not change the process GID, so if /etc/sudoers is readable in a group, this explains why it is always readable. fork() does not change the credentials of the process. However, this may look like the one shown in your sample code, since you are checking different files in the parent and child. If /etc/group- does not have permission to access the group where /etc/sudoers , this explains the obvious problem.

If all you are trying to do is drop privileges, use the following code:

 os.setgid( NEW_GID ) os.setuid( NEW_UID ) 

Generally speaking, you only want to use an effective user ID if your process should turn it on and off throughout the process. If you just need to perform some configuration operations with root privileges, but will no longer require them after completing these installation operations, simply use the code above to delete them irrevocably.

Oh, and a useful debugging utility for manipulating process credentials on Linux is to print the output of /proc/self/status , the Uid and Gid lines of this file display the real, effective, saved, and file identifiers stored in the current process (in that order). Python APIs can be used to extract the same information, but you can view the contents of this file as “truth data” and avoid any possible complications from the cross-platform Python APIs.

+6
source

All Articles