def start(self): serversockets = [] for port in self.ports: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: s.bind(("", port)) except socket.error as e: self.print_error("Could not bind port %s: %s." % (port, e)) sys.exit(1) s.listen(5) serversockets.append(s) del s self.print_info("Listening on port %d." % port) if self.chroot: os.chdir(self.chroot) os.chroot(self.chroot) self.print_info("Changed root directory to %s" % self.chroot) if self.setuid: os.setresgid(self.setuid[1], self.setuid[1], self.setuid[1]) os.setresuid(self.setuid[0], self.setuid[0], self.setuid[0]) self.print_info("Setting uid:gid to %s:%s" % (self.setuid[0], self.setuid[1])) last_aliveness_check = time.time() while True: (iwtd, owtd, ewtd) = select.select( serversockets + [x.socket for x in self.clients.values()], [x.socket for x in self.clients.values() if x.write_queue_size() > 0], [], 10) for x in iwtd: if x in self.clients: self.clients[x].socket_readable_notification() else: (conn, addr) = x.accept() if self.ssl_pem_file: import ssl try: conn = ssl.wrap_socket( conn, server_side=True, certfile=self.ssl_pem_file, keyfile=self.ssl_pem_file) except ssl.SSLError as e: self.print_error( "SSL error for connection from %s:%s: %s" % ( addr[0], addr[1], e)) continue self.clients[conn] = self.client_factory(conn) self.print_info("Accepted connection from %s:%s." % ( addr[0], addr[1])) for x in owtd: if x in self.clients: # client may have been disconnected self.clients[x].socket_writable_notification() now = time.time() if last_aliveness_check + 10 < now: for client in self.clients.values(): client.check_aliveness() last_aliveness_check = now
def demote_subprocess(): """ Lower the privileges of the spawned subprocess by setting limits on its resource use and by switching it to be run as another user. NOTE: The resource limits were set by using ulimit and shell=True before. This was changed in order to address security questions raised by using the shell and to make passing arguments easier. """ #info("Demoting subprocess.") # Set resource limits resource.setrlimit(resource.RLIMIT_NPROC, (10, 10)) # Prevent fork bombs resource.setrlimit(resource.RLIMIT_NOFILE, (50, 50)) # Limit number of files resource.setrlimit(resource.RLIMIT_FSIZE, (500*1024, 500*1024)) # Limit space used by a file resource.setrlimit(resource.RLIMIT_CPU, (2, 2)) # Limit CPU time # Change the group and user IDs to lower privileged ones user_gid = Privileges.get_low_gid() user_uid = Privileges.get_low_uid() try: os.setresgid(user_gid, user_gid, user_gid) os.setresuid(user_uid, user_uid, user_uid) except OSError: #error("Unable to demote the subprocess to uid: %d, gid: %d!" % (user_uid, user_gid)) pass else: #info("Successfully demoted the subprocess to uid: %d, gid: %d." % (user_uid, user_gid)) pass
def runfastcgi(app, argset=[], **kwargs): options = FASTCGI_OPTIONS.copy() options.update(kwargs) for x in argset: if '=' in x: k, v = x.split('=', 1) else: k, v = x, True options[k.lower()] = v if 'help' in options: return fastcgi_help() if 'run_as' in options: from pwd import getpwnam try: pw = getpwnam(options['run_as']) except KeyError: pw = None if pw: os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) try: import flup except ImportError, e: print >> sys.stderr, 'ERROR: %s' % e print >> sys.stderr, ' Unable to load the flup package. In order to run rsted' print >> sys.stderr, ' as a FastCGI application, you will need to get flup from' print >> sys.stderr, " http://www.saddi.com/software/flup/ If you've already" print >> sys.stderr, ' installed flup, then make sure you have it in your PYTHONPATH.' return False
def drop_privileges(user, group): if user is None: uid = os.getuid() elif user.lstrip("-").isdigit(): uid = int(user) else: uid = pwd.getpwnam(user).pw_uid if group is None: gid = os.getgid() elif group.lstrip("-").isdigit(): gid = int(group) else: gid = grp.getgrnam(group).gr_gid username = pwd.getpwuid(uid).pw_name # groupname = grp.getgrgid(gid).gr_name groups = [g for g in grp.getgrall() if username in g.gr_mem] os.setgroups(groups) if hasattr(os, 'setresgid'): os.setresgid(gid, gid, gid) else: os.setregid(gid, gid) if hasattr(os, 'setresuid'): os.setresuid(uid, uid, uid) else: os.setreuid(uid, uid)
def main(argv): """ The entry point of daemon_factory process :param argv: parameters given from command line """ if (len(argv) != 3): usage() # TODO(takashi): returning non-zero value is better? return pipe_path = argv[0] log_level = argv[1] container_id = argv[2] # Initialize logger logger = start_logger("daemon_factory", log_level, container_id) logger.debug("Daemon factory started") SBus.start_logger("DEBUG", container_id=container_id) # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) # create an instance of daemon_factory factory = daemon_factory(pipe_path, logger) # Start the main loop factory.main_loop(container_id)
def _unmount_as_user_fstab_fail(self, pipe, uid, gid, device): """ Try to unmount @device as user with given @uid and @gid. @device shouldn't be listed in /etc/fstab when running this, so this is expected to fail. """ os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) # try to mount the device -- it should fail try: safe_dbus.call_sync(self.iface_prefix, self.path_prefix + '/block_devices/' + os.path.basename(device), self.iface_prefix + '.Filesystem', 'Unmount', GLib.Variant('(a{sv})', ({},))) except Exception as e: msg = 'GDBus.Error:org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain: Not authorized to perform operation' if msg in str(e): pipe.send([True, '']) pipe.close() return else: pipe.send([False, 'Unmount DBus call failed with unexpected exception: %s' % str(e)]) pipe.close() return ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device) if ret == 0: pipe.send([False, 'Unmount DBus call didn\'t fail but %s seems to be still mounted.' % device]) pipe.close() return else: pipe.send([False, '%s was unmounted for UID %d without proper record in fstab' % (device, uid)]) pipe.close() return
def prepare(suid, slave): if suid is not None: try: if not type(suid) in (int, long): userinfo = pwd.getpwnam(suid) suid = userinfo.pw_uid sgid = userinfo.pw_gid else: userinfo = pwd.getpwuid(suid) sgid = userinfo.pw_gid except: pass try: if slave: path = os.getttyname(slave) os.chown(path, suid) except: pass try: os.initgroups(userinfo.pw_name, sgid) os.chdir(userinfo.pw_dir) except: pass try: os.setresgid(suid, suid, sgid) os.setresuid(suid, suid, sgid) except: pass os.setsid() fcntl.ioctl(sys.stdin, termios.TIOCSCTTY, 0)
def debug_server(self, shared_queue): self.read_configuration() uid = int(self.server_uid) if os.getuid() != uid: os.setresuid(uid, uid, uid) gid = int(self.server_gid) if os.getgid() != gid: os.setresgid(gid, gid, gid) for key in self.env: debug("Setting environment variable %s=%s" % (key, self.env[key])) os.putenv(key, self.env[key]) if self.pre_command is not None: os.system(self.pre_command) crash = None for i in range(0,3): try: crash = self.launch_debugger(self.timeout, self.command, "") break except: log("Exception: %s" % sys.exc_info()[1]) continue if self.post_command is not None: os.system(self.post_command) if crash is not None: self.crash_info = crash shared_queue.put(crash) return True return False
def _demoted_child_call(uid, gid, ret_data_q, func): """Call a function/method with different uid/gid""" # Set UID and GID if gid and gid > 0: try: os.setresgid(gid, gid, gid) except OSError as err: ret_data_q.put(GbpServiceError("Setting GID (%s) failed: %s" % (gid, err))) sys.exit(_RET_FORK_ERR) if uid and uid > 0: try: os.setresuid(uid, uid, uid) except OSError as err: ret_data_q.put(GbpServiceError("Setting UID (%s) failed: %s" % (uid, err))) sys.exit(_RET_FORK_ERR) try: # Set environment os.environ['HOME'] = pwd.getpwuid(uid).pw_dir except KeyError: pass # Call the function try: # Func must be a callable without arguments ret = func() # pylint: disable=broad-except except Exception as err: ret_data_q.put(GbpChildBTError()) sys.exit(_RET_FORK_ERR) # pylint: enable=broad-except else: ret_data_q.put(ret) sys.exit(_RET_FORK_OK)
def main(argv): ''' @summary: main The entry point. - Initialize logger, - impersonate to swift user, - create an instance of daemon_factory, - start the main loop. ''' if (len(argv) != 2): usage() return pipe_path = argv[0] log_level = argv[1] logger = start_logger("daemon_factory", log_level) logger.debug("Daemon factory started") SBus.start_logger("DEBUG") # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid,pw.pw_gid,pw.pw_gid) os.setresuid(pw.pw_uid,pw.pw_uid,pw.pw_uid) factory = daemon_factory(pipe_path, logger) factory.main_loop()
def main(argv): """ The entry point of daemon_factory process :param argv: parameters given from command line """ if (len(argv) != 5): usage() return EXIT_FAILURE storlet_name = argv[0] sbus_path = argv[1] log_level = argv[2] pool_size = argv[3] container_id = argv[4] # Initialize logger logger = start_logger("storlets-daemon", log_level, container_id) logger.debug("Storlet Daemon started") SBus.start_logger("DEBUG", container_id=container_id) # Impersonate the swift user pw = pwd.getpwnam('swift') os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) # create an instance of storlet daemon try: daemon = Daemon(storlet_name, sbus_path, logger, pool_size) except Exception as e: logger.error(e.message) return EXIT_FAILURE # Start the main loop return daemon.main_loop()
def __init__(self, user, visitor, token): self.user = user self.visitor = visitor self.token = token if os.geteuid() is 0: os.setresgid(61015, 61015, 61015) os.setresuid(61020, 61020, 61020)
def drop_privileges(): try: uid = os.getuid() gid = os.getgid() os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) except: die('Unable to drop privileges')
def __set_unprivileged_user(): """ Set the real and effective user and group to an unprivileged user. """ _, _, uid, gid, _, _, _ = pwd.getpwnam('enarksh') os.setresgid(gid, gid, 0) os.setresuid(uid, uid, 0)
def drop_privileges(uid_spec=None, uid=None, gid=None): if uid_spec: assert not (uid or gid), [uid_spec, uid, gid] uid, gid = parse_uid_spec(uid_spec) assert uid is not None and gid is not None, [uid_spec, uid, gid] os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) log.debug('Switched uid/gid to %s:%s', uid, gid)
def setresuid(space, ruid, euid, suid): """ setresuid(ruid, euid, suid) Set the current process's real, effective, and saved user ids. """ try: os.setresuid(ruid, euid, suid) except OSError as e: raise wrap_oserror(space, e)
def restore_user_group(self): try: (ruid, euid, suid) = os.getresuid() (rgid, egid, sgid) = os.getresgid() os.setresuid(suid, suid, suid) os.setresgid(sgid, sgid, sgid) except Exception, e: log.error("Error: %s" % e) exit(1)
def up_permissions(self): """ Elevate our current permissions """ try: os.setresuid(0, 0, 0) os.setresgid(0, 0, 0) os.environ['HOME'] = '/root' except Exception as e: print("Failed to raise permissions: {}".format(e)) return False return True
def down_permissions(self): """ Drop our current permissions """ try: os.setresgid(self.down_gid, self.down_gid, 0) os.setresuid(self.down_uid, self.down_uid, 0) os.environ['HOME'] = self.home_dir except Exception as e: print("Failed to drop permissions: {}".format(e)) return False return True
def drop_privileges(uid_spec=None, uid=None, gid=None, log=None): if log is False: log = lambda *a,**k: None elif log is None: log = logging.getLogger('fgc.sh.drop_privileges') if uid_spec: assert not (uid or gid), [uid_spec, uid, gid] uid, gid = parse_uid_spec(uid_spec) assert uid is not None and gid is not None, [uid_spec, uid, gid] os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) log.debug('Switched uid/gid to %s:%s', uid, gid)
def start_job(self): self.__log_job_start() # Create pipes for stdout and stderr. pipe_stdout = os.pipe() pipe_stderr = os.pipe() self.__child_pid = os.fork() if self.__child_pid == 0: # Child process. try: # Close the read ends from the pipes. os.close(pipe_stdout[0]) os.close(pipe_stderr[0]) # Duplicate stdout and stderr on the pipes. sys.stdout.flush() sys.stderr.flush() os.dup2(pipe_stdout[1], sys.stdout.fileno()) os.dup2(pipe_stderr[1], sys.stderr.fileno()) # Set the effective user and group. if self.__user_name in self.__allowed_users: _, _, uid, gid, _, _, _ = pwd.getpwnam(self.__user_name) os.setuid(0) os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) else: raise RuntimeError("Spanner is not allowed to start processes under user '%s'." % self.__user_name) # Set variable for subprocess. os.putenv('ENK_RND_ID', str(self.__rnd_id)) os.putenv('ENK_SCH_ID', str(self.__sch_id)) # Replace this child process with the actual job. os.execv(self.__args[0], self.__args) except Exception as e: self.__log.error('Unable to start job') self.__log.error('Reason: {}'.format(str(e))) self.__log.exception('Error') # Exit immediately without running the exit handlers (e.g. from daemon) from the parent process. os._exit(-1) else: # Parent process. # Close the write ends from the pipes. os.close(pipe_stdout[1]) os.close(pipe_stderr[1]) # Remember the fds for reading the stdout and stderr from the child process. self.__stdout = pipe_stdout[0] self.__stderr = pipe_stderr[0]
def _mount_as_user_fstab(self, pipe, uid, gid, device): """ Try to mount and then unmount @device as user with given @uid and @gid. @device should be listed in /etc/fstab with proper options so user is able to run these operations and this shouldn't fail. """ os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) # try to mount the device try: safe_dbus.call_sync(self.iface_prefix, self.path_prefix + '/block_devices/' + os.path.basename(device), self.iface_prefix + '.Filesystem', 'Mount', GLib.Variant('(a{sv})', ({},))) except Exception as e: pipe.send([False, 'Mount DBus call failed: %s' % str(e)]) pipe.close() return ret, out = self.run_command('grep \"%s\" /proc/mounts' % device) if ret != 0: pipe.send([False, '%s not mounted' % device]) pipe.close() return if 'uid=%s,gid=%s' % (uid, gid) not in out: pipe.send([False, '%s not mounted with given uid/gid.\nMount info: %s' % (device, out)]) pipe.close() return # and now try to unmount it try: safe_dbus.call_sync(self.iface_prefix, self.path_prefix + '/block_devices/' + os.path.basename(device), self.iface_prefix + '.Filesystem', 'Unmount', GLib.Variant('(a{sv})', ({},))) except Exception as e: pipe.send([False, 'Unmount DBus call failed: %s' % str(e)]) pipe.close() return ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device) if ret == 0: pipe.send([False, '%s mounted after unmount called' % device]) pipe.close() return pipe.send([True, '']) pipe.close() return
def init(self, path): uid_cache = UnixUsernameCache() PCache = PermissionCache if not Has_Redis else RedisPermissionCache self.perm_cache = PCache( uid_cache, self.permission_host, self.permission_cache_timeout, self.permission_cache_size ) # setuid of user performing the file operations u = pwd.getpwnam(USER) os.setresuid(u.pw_uid, u.pw_uid, u.pw_uid)
def su_to_zulip(save_suid: bool = False) -> None: """Warning: su_to_zulip assumes that the zulip checkout is owned by the zulip user (or whatever normal user is running the Zulip installation). It should never be run from the installer or other production contexts before /home/zulip/deployments/current is created.""" pwent = get_zulip_pwent() os.setgid(pwent.pw_gid) if save_suid: os.setresuid(pwent.pw_uid, pwent.pw_uid, os.getuid()) else: os.setuid(pwent.pw_uid) os.environ['HOME'] = pwent.pw_dir
def switch_user_group(uid: int, gid: int): groups = list(os.getgroups()) os.setresgid(0, gid, 0) os.setgroups([gid]) os.setresuid(0, uid, 0) try: yield finally: os.setresuid(0, 0, 0) os.setresgid(0, 0, 0) os.setgroups([0] + groups)
def init_lower_privileges(uid: int, gid: int) -> None: """Function to lower privileges (*i.e.* change *real* and *effective* UIDs and GIDs to UID/GID values given as arguments) intended to be called at cosmk module importation.""" # Reset the supplementary groups of the current user to the supplementary # groups of the target unprivileged user: username = pwd.getpwuid(uid).pw_name usergroups = os.getgrouplist(username, gid) os.setgroups(usergroups) # And then hange real, effective and saved-set UID and GID: os.setresgid(gid, gid, 0) # GID before UID otherwise this fails os.setresuid(uid, uid, 0)
def __init__(self, user, visitor): self.user = user self.visitor = visitor creddb = cred_setup() person = creddb.query(Cred).get(self.user) if not person: self.token = None else: self.token = person.token # Change uid gid = 61012 os.setresgid(gid, gid, gid) uid = 61012 os.setresuid(uid, uid, uid)
def __exit__(self, *args): try: os.seteuid(s.euid) os.setgroups(self.groups) os.setresgid(*self.g) os.setresuid(*self.u) for k in self.env: os.putenv(k, self.env[k]) except OSError as e: _raise_setting_error(self.to_root, repr(e)) if os.geteuid() != self.u[1]: _raise_setting_error(self.to_root, "setresuid to %d failed" % to_u) return None
def child_preexec(): """ Sets umask and becomes the correct user. """ try: os.umask(self.execution_settings.umask) os.setresgid(self.execution_settings.gid, self.execution_settings.gid, self.execution_settings.gid) os.setresuid(self.execution_settings.uid, self.execution_settings.uid, self.execution_settings.uid) except OSError as e: print(str(e), file=sys.stderr, flush=True)
def su_to_zulip(save_suid=False): # type: (bool) -> None """Warning: su_to_zulip assumes that the zulip checkout is owned by the zulip user (or whatever normal user is running the Zulip installation). It should never be run from the installer or other production contexts before /home/zulip/deployments/current is created.""" pwent = get_zulip_pwent() os.setgid(pwent.pw_gid) if save_suid: os.setresuid(pwent.pw_uid, pwent.pw_uid, os.getuid()) else: os.setuid(pwent.pw_uid) os.environ['HOME'] = pwent.pw_dir
def drop_privileges_save(): """Drop the real UID/GID as well, and hide them in saved IDs.""" # At the moment, we only know how to handle this when effective # privileges were already dropped. assert _dropped_privileges is not None and _dropped_privileges > 0 uid = os.environ.get('SUDO_UID') gid = os.environ.get('SUDO_GID') if uid is not None: uid = int(uid) set_groups_for_uid(uid) if gid is not None: gid = int(gid) os.setresgid(gid, gid, 0) if uid is not None: os.setresuid(uid, uid, 0)
def _drop_privileges(self, username): if os.geteuid() != 0: return pw = pwd.getpwnam(username) os.setgroups( [g.gr_gid for g in grp.getgrall() if username in g.gr_mem]) # Portability note: this assumes that we have [gs]etres[gu]id, which # is true on Linux but not necessarily elsewhere. If you need to # support something else, there are reasonably standard alternatives # involving other similar calls; see e.g. gnulib/lib/idpriv-drop.c. os.setresgid(pw.pw_gid, pw.pw_gid, pw.pw_gid) os.setresuid(pw.pw_uid, pw.pw_uid, pw.pw_uid) assert os.getresuid() == (pw.pw_uid, pw.pw_uid, pw.pw_uid) assert os.getresgid() == (pw.pw_gid, pw.pw_gid, pw.pw_gid) os.umask(0o022)
def inner(*args, **kwargs): current_proc = multiprocessing.current_process() logger.debug( "Changing permissions for process: {0} with PID: {1!s}".format( current_proc.name, current_proc.pid)) if sys.version > "2.7": ruid, euid, suid = os.getresuid() rgid, egid, sgid = os.getresgid() logger.debug( "UIDs before are: (ruid) {0}, (euid) {1}, (suid) {2}".format( ruid, euid, suid)) logger.debug( "GIDs before are: (rgid) {0}, (egid) {1}, (sgid) {2}".format( rgid, egid, sgid)) logger.debug("Setting all UIDs/GIDs to 0") # Make the actual permissions changes os.setresuid(0, 0, 0) os.setresgid(0, 0, 0) try: retval = func(*args, **kwargs) finally: # Restore original permissions os.setresgid(rgid, egid, sgid) os.setresuid(ruid, euid, suid) else: ruid = os.getuid() euid = os.geteuid() rgid = os.getgid() egid = os.getegid() logger.debug("UIDs before are: (ruid) {0}, (euid) {1}".format( ruid, euid)) logger.debug("GIDs before are: (rgid) {0}, (egid) {1}".format( rgid, egid)) logger.debug("Setting all UIDs/GIDs to 0") # Make the actual permissions changes os.setreuid(0, 0) os.setregid(0, 0) try: logger.debug("Setting all UIDs/GIDs to 0") retval = func(*args, **kwargs) finally: # Restore original permissions os.setregid(rgid, egid) os.setreuid(ruid, euid) return retval
def launch_sequence(): print "Creating resource directories." for resource in resources.values(): if not os.path.exists(resource.path): print "Creating: %s" % resource.path os.mkdir(resource.path) print "Setting permissions on resources." for resource in resources.values(): uid, gid = resource.uid, resource.gid for leaf in os.listdir(resource.path) + ["."]: path = resource.path + "/" + leaf # Set the owner bits. os.chown(path, uid, gid) # Set the permission bits. if os.path.isdir(path): # Justification: os.chmod(path, 0750) # rwxr-x--- else: os.chmod(path, 0640) # rw-r----- wait_list = [] for process in processes.values(): print "Spawning", process.name # Delete the RPC resource socket, if there happens to be an old one sitting around. # XXX: This code knows about the convention of rpc/Service/sock! if process.rpc_resource != None: if os.path.exists(process.rpc_resource.path + "/sock"): os.unlink(process.rpc_resource.path + "/sock") pid = os.fork() if pid == 0: # Change into the dryer21 directory. os.chdir("/dryer21") # Drop permissions. os.setresgid(NO_PRIVS, NO_PRIVS, NO_PRIVS) os.setgroups(process.groups) os.setresuid(process.uid, process.uid, process.uid) # Now launch python on the given script. os.execve("/usr/bin/python", ["python", process.binary_path] + process.arguments, {"HOME": "/nonexistant", "PYTHONPATH": "/dryer21/code"}) else: # Wait for the child to finish setting up, if it has an rpc_resource. # This is necessary to prevent race conditions where future processes try to connect before this one is done setting up. if process.rpc_resource != None: # Currently I just use a little spin loop, which is good enough -- I'm not going to use inotify. while not os.path.exists(process.rpc_resource.path + "/sock"): time.sleep(0.1) wait_list.append(pid) for pid in wait_list: os.waitpid(pid, 0) print "Exiting."
def demote_server(): srv_uid = Privileges.get_high_uid() srv_gid = Privileges.get_high_gid() srv_name = Privileges.get_high_name() sp_uid = Privileges.get_low_uid() sp_gid = Privileges.get_low_gid() # Demote the server to server_uid, but allow further demotion to sp_uid try: # http://stackoverflow.com/a/6037494 os.setresgid(srv_gid, sp_gid, sp_gid) os.setresuid(srv_uid, sp_uid, sp_uid) except OSError: error("Losing privileges not permitted.") else: info("Demoted the server process to user %s (%d) and group %d." % (srv_name, srv_uid, srv_gid))
def act(act_as): srv_uid = Privileges.get_high_uid() srv_gid = Privileges.get_high_gid() sp_uid = Privileges.get_low_uid() sp_gid = Privileges.get_low_gid() try: if act_as == "server": os.setresgid(srv_gid, sp_gid, srv_gid) os.setresuid(srv_uid, sp_uid, srv_uid) elif act_as == "subprocess": os.setresgid(srv_gid, sp_gid, sp_gid) os.setresuid(srv_uid, sp_uid, sp_uid) except OSError: error("Unable to set effective user rights as %s!" % (act_as)) else: info("Effective user: %s." % (act_as))
def drop_privileges(): sys.stderr.write('dropping privileges\n') os.setgroups([]) gid = int(os.getenv('SUDO_GID')) uid = int(os.getenv('SUDO_UID')) pwname = os.getenv('SUDO_USER') os.setresgid(gid, gid, gid) os.initgroups(pwname, gid) os.setresuid(uid, uid, uid) pw = pwd.getpwuid(uid) # we completely clear the environment and start a new and controlled one os.environ.clear() os.environ['XDG_RUNTIME_DIR'] = f'/run/user/{uid}' os.environ['HOME'] = pw.pw_dir
def _ReExecuteIfNeeded(argv, network): """Re-execute as root so we can unshare resources.""" if os.geteuid() != 0: cmd = ['sudo', '-E', 'HOME=%s' % os.environ['HOME'], 'PATH=%s' % os.environ['PATH'], '--'] + argv os.execvp(cmd[0], cmd) else: cgroups.Cgroup.InitSystem() namespaces.SimpleUnshare(net=not network, pid=True) # We got our namespaces, so switch back to the user to run the tests. gid = int(os.environ.pop('SUDO_GID')) uid = int(os.environ.pop('SUDO_UID')) user = os.environ.pop('SUDO_USER') os.initgroups(user, gid) os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) os.environ['USER'] = user
def _unmount_as_user_fstab_fail(self, pipe, uid, gid, device): """ Try to unmount @device as user with given @uid and @gid. @device shouldn't be listed in /etc/fstab when running this, so this is expected to fail. """ os.setresgid(gid, gid, gid) os.setresuid(uid, uid, uid) # try to mount the device -- it should fail try: safe_dbus.call_sync( self.iface_prefix, self.path_prefix + '/block_devices/' + os.path.basename(device), self.iface_prefix + '.Filesystem', 'Unmount', GLib.Variant('(a{sv})', ({}, ))) except Exception as e: msg = 'GDBus.Error:org.freedesktop.UDisks2.Error.NotAuthorizedCanObtain: Not authorized to perform operation' if msg in str(e): pipe.send([True, '']) pipe.close() return else: pipe.send([ False, 'Unmount DBus call failed with unexpected exception: %s' % str(e) ]) pipe.close() return ret, _out = self.run_command('grep \"%s\" /proc/mounts' % device) if ret == 0: pipe.send([ False, 'Unmount DBus call didn\'t fail but %s seems to be still mounted.' % device ]) pipe.close() return else: pipe.send([ False, '%s was unmounted for UID %d without proper record in fstab' % (device, uid) ]) pipe.close() return
def prepare(suid): if suid is not None: try: if not type(suid) in (int, long): userinfo = pwd.getpwnam(suid) suid = userinfo.pw_uid sgid = userinfo.pw_gid else: userinfo = pwd.getpwuid(suid) sgid = userinfo.pw_gid except: pass try: path = os.ttyname(sys.stdin.fileno()) os.chown(path, suid, sgid) except: pass try: os.initgroups(userinfo.pw_name, sgid) os.chdir(userinfo.pw_dir) except: pass try: if hasattr(os, 'setresuid'): os.setresgid(suid, suid, sgid) os.setresuid(suid, suid, sgid) else: euid = os.geteuid() if euid != 0: os.seteuid(0) os.setegid(0) os.setgid(suid) os.setuid(suid) except: pass os.setsid() try: fcntl.ioctl(sys.stdin, termios.TIOCSCTTY, 0) except: # No life without control terminal :( os._exit(-1)
def main(): # does nothing os.open('/bin/bash', os.O_RDONLY) # opens flag and duplicates the file descriptor fd = os.open('./flag', os.O_RDONLY) os.dup2(fd, 9) # creates path with /tmp and 16 random bytes path = os.path.join('/tmp', secrets.token_hex(16)) # prints prompt ?? print("#!/d", end="") # reads 16 bytes from stdin data = os.read(0, 0x10) # closes stdin os.close(0) # checks if contains dot check_input(data) # creates /tmp/RANDOM fd = os.open(path, os.O_CREAT | os.O_RDWR, 0o777) # writes the prompt and whatever i gave it as input to the file os.write(fd, b'#!/d' + data) os.close(fd) pid = os.fork() if pid == 0: # if child # sets gid for current process os.setresgid(NOGROUP, NOGROUP, NOGROUP) # sets uid for current process os.setresuid(NOBODY, NOBODY, NOBODY) try: # try to execute /tmp/RANDOM file os.execv(path, [path]) except: os._exit(-1) else: # waits for child and deletes file os.waitpid(pid, 0) os.unlink(path)
def drop_privilege(target_uid: int, target_gid: int): backup_egid = os.getegid() should_modify_gid = target_gid != backup_egid backup_euid = os.geteuid() should_modify_uid = target_uid != backup_euid if should_modify_gid: os.setresgid(target_gid, target_gid, backup_egid) if should_modify_uid: os.setresuid(target_uid, target_uid, backup_euid) yield if should_modify_gid: os.setresgid(backup_egid, backup_egid, backup_egid) if should_modify_uid: os.setresuid(backup_euid, backup_euid, backup_euid)
def EnterSandbox(user: str, group: str) -> None: """Enters the sandbox. Drops root privileges, by changing the user and group. Args: user: New UNIX user name to run as. If empty then the user is not changed. group: New UNIX group name to run as. If empty then the group is not changed. """ if group: gid = grp.getgrnam(group).gr_gid os.setgroups([gid]) os.setresgid(gid, gid, gid) if user: uid = pwd.getpwnam(user).pw_uid os.setresuid(uid, uid, uid)
def drop_privileges(user, group): """Drop privileges to specified user and group""" if group is not None: import grp gid = grp.getgrnam(group).gr_gid logger.debug("Dropping privileges to group {0}/{1}".format(group, gid)) try: os.setresgid(gid, gid, gid) except AttributeError: os.setregid(gid, gid) if user is not None: import pwd uid = pwd.getpwnam(user).pw_uid logger.debug("Dropping privileges to user {0}/{1}".format(user, uid)) try: os.setresuid(uid, uid, uid) except AttributeError: os.setreuid(uid, uid)
def detach_process(self): # Don't be hit by CTRL+C setpgrp() # Drop privileges if needed uid, gid = getenv('SUDO_UID'), getenv('SUDO_GID') if uid and gid: uid, gid = int(uid), int(gid) setgroups(getgrouplist(getpwuid(uid).pw_name, gid)) setresgid(gid, gid, -1) setresuid(uid, uid, -1)
def restore_id(config, LOG): """ Restore the process' UID and GID to the stored values (usually root) """ euid, egid = (config['tsi.effective_uid'], config['tsi.effective_gid']) LOG.debug("Resetting ID to (%s %s)" % (euid, egid)) setting_uids = config['tsi.switch_uid'] if setting_uids: os.setresuid(euid, euid, euid) os.setgid(egid) os.setgroups([egid]) os.setegid(egid) # re-set environment to something harmless os.environ['HOME'] = "/tmp" os.environ['USER'] = "******" os.environ['LOGNAME'] = "nobody"
def prepare(suid): import pwd if suid is not None: try: if not type(suid) in (int, long): userinfo = pwd.getpwnam(suid) suid = userinfo.pw_uid sgid = userinfo.pw_gid else: userinfo = pwd.getpwuid(suid) sgid = userinfo.pw_gid except Exception: pass try: path = os.ttyname(sys.stdin.fileno()) os.chown(path, suid, sgid) except Exception: pass try: os.initgroups(userinfo.pw_name, sgid) os.chdir(userinfo.pw_dir) except Exception: pass try: if hasattr(os, 'setresuid'): os.setresgid(suid, suid, sgid) os.setresuid(suid, suid, sgid) else: euid = os.geteuid() if euid != 0: os.seteuid(0) os.setegid(0) os.setgid(suid) os.setuid(suid) except Exception: pass os.setsid()
def preexec(): # chroot to safe place if needed try: if chroot: os.chroot(chroot) except Exception as err: log.warning(str(err) + ': unable to chroot') # setup resource kernel limitation for limit in limits: if limit.rlimit != None: resource.setrlimit( limit.rlimit, # hard limit & soft limit (limit.rlimit_value, limit.rlimit_value)) # setuid for nobody try: os.setresgid(ngid, ngid, ngid) os.setresuid(nuid, nuid, nuid) except Exception as err: log.warning(str(err) + ': unable to setuid')
def drop_privileges(): """ Drop all the privileges that can be reasonably dropped. This is to prevent the forked process from harming its creator and from accessing any data belonging to the evaluation server process exclusively. For more information, review: - http://man7.org/linux/man-pages/man2/setresuid.2.html - https://docs.python.org/3/library/os.html#os.setresuid """ # Drop the real, effective and saved group and user ids try: os.setresgid(student_gid, student_gid, student_gid) os.setresuid(student_uid, student_uid, student_uid) except OSError: print( "Unable to drop privileges to GID: (r:{s_gid}, e:{s_gid}, s:{s_gid}), UID: (r:{s_uid}, e:{s_uid}, s:{s_uid})" .format(s_gid=student_gid, s_uid=student_uid))
def debug_server(self, shared_queue): self.read_configuration() uid = int(self.server_uid) if os.getuid() != uid: os.setresuid(uid, uid, uid) gid = int(self.server_gid) if os.getgid() != gid: os.setresgid(gid, gid, gid) for key in self.env: debug("Setting environment variable %s=%s" % (key, self.env[key])) os.putenv(key, self.env[key]) if self.pre_command is not None: os.system(self.pre_command) crash = None for i in range(0, 3): try: crash = self.launch_debugger(self.timeout, self.command, "") print "SERVER", 1 break except: log("Exception: %s" % sys.exc_info()[1]) raise continue print "SERVER", 2 if self.post_command is not None: os.system(self.post_command) print "SERVER", 3, crash if crash is not None: print "SERVER, CRASH", crash self.crash_info = crash shared_queue.put(crash) print "SERVER, PUT" return True print "SERVER", 4, "AGUR?" return False
def dropped_privileges(passwd: pwd.struct_passwd): """ Context manager for temporarily switching real and effective UID and real and effective GID. """ logger.debug("Dropping privileges temporary to user %s", passwd.pw_name) # To handle multiple users with the same UID correctly, we obtain the # current user name with getpass saved_user = getpass.getuser() saved_uid = os.geteuid() saved_gid = os.getegid() os.initgroups(passwd.pw_name, passwd.pw_gid) os.setresuid(passwd.pw_uid, passwd.pw_uid, saved_uid) try: yield finally: os.seteuid(saved_uid) os.setreuid(saved_uid, saved_uid) os.setregid(saved_gid, saved_gid) os.initgroups(saved_user, saved_gid) logger.debug("Restoring previous privileges as user %s", saved_user)
def EnterSandbox(user: str, group: str) -> None: """Enters the sandbox. Drops root privileges, by changing the user and group. Args: user: New UNIX user name to run as. If empty then the user is not changed. group: New UNIX group name to run as. If empty then the group is not changed. """ if not (user or group): return # Disable networking and IPC by creating new (empty) namespaces for the # current process. libc = ctypes.cdll.LoadLibrary(ctypes.util.find_library("c")) unshare = getattr(libc, "unshare", None) if unshare: unshare.argtypes = [ctypes.c_int] unshare.restype = ctypes.c_int def Unshare(flags: int) -> None: res = unshare(flags) if res == 0: return error = ctypes.get_errno() if error != errno.EINVAL: raise Error(f"unshare({flags}) failed with error {error}.") Unshare(CLONE_NEWNET) Unshare(CLONE_NEWIPC) if group: gid = grp.getgrnam(group).gr_gid os.setgroups([gid]) os.setresgid(gid, gid, gid) if user: uid = pwd.getpwnam(user).pw_uid os.setresuid(uid, uid, uid)
def inner(*args, **kwargs): # Get proper UID try: sudo_uid = int(os.environ['SUDO_UID']) except (KeyError, ValueError) as e: log.error("Could not get UID for sudoer") return # Get proper GID try: sudo_gid = int(os.environ['SUDO_GID']) except (KeyError, ValueError) as e: log.error("Could not get GID for sudoer") return # Drop root os.setresgid(sudo_gid, sudo_gid, -1) os.setresuid(sudo_uid, sudo_uid, -1) # Execute function ret = function(*args, **kwargs) # Get root back os.setresgid(0, 0, -1) os.setresuid(0, 0, -1) return ret
def drop_privileges(uid_name='nobody', gid_name='nogroup'): if os.getuid() != 0: # We're not root so, like, whatever dude raise Exception("Cannot drop privileges! Not running as root!") # Get the uid/gid from the name running_uid = pwd.getpwnam(uid_name).pw_uid running_gid = grp.getgrnam(gid_name).gr_gid # Remove group privileges os.setgroups([]) # Try setting the new uid/gid if hasattr(os, "setresgid"): os.setresgid(running_gid, running_gid, running_gid) os.setgid(running_gid) if hasattr(os, "setresuid"): os.setresuid(running_uid, running_uid, running_uid) os.setuid(running_uid) # Ensure a very conservative umask os.umask(0o077)
def restart(self): """ Restarts smbproviderd and rebinds to D-Bus interface. """ logging.info('restarting smbproviderd') upstart.restart_job('smbproviderd') try: # Get the interface as Chronos since only they are allowed to send # D-Bus messages to smbproviderd. os.setresuid(self._CHRONOS_UID, self._CHRONOS_UID, 0) bus = dbus.SystemBus(self._bus_loop) proxy = bus.get_object(self._DBUS_SERVICE_NAME, self._DBUS_SERVICE_PATH) self._smbproviderd = dbus.Interface(proxy, self._DBUS_INTERFACE_NAME) finally: os.setresuid(0, 0, 0)