How do I drop supplementary groups in Linux? - c

I have an executable that's ug+s to a non-root user and group. I would like it to leave all the supplementary groups it originally had behind. Is there a way to make this happen? It doesn't look like the setgroups call allows you to do this if you're not root. And when I try it, I get EPERM.
It seems like there ought to be a way to lose privileges you previously possessed.

The short answer is "A process without CAP_SETGID can't.". And it is by design that setgroups can't be used to remove groups when the process has no privileges. The previous link is to an excellent LWN article detailing why not.
In my particular case, since I'm immediately creating a user namespace, those supplementary groups get mapped to 'nobody' anyway. And so it isn't very important. If it is important, you can use setcap(8) to set capabilities on a wrapper executable that checks that it's being run by the expected user with the expected group permissions and then drops the groups and drops CAP_SETGID and runs the executable you really want to run. The command you would use to do this is:
sudo setcap cap_setgid+ep wrapper_exe
Be careful though, it's now possible that someone who has a shell on your system can use that executable to run some sort of privilege escalation attack if you did not write it very carefully.

Related

Changin uid/gid of a running non-provileged process

I need to implement an small capability system for Linux similar to Plan 9 cap device. Host owner (root in Linux) allows user1 to impersonate user2 writing user1#user2#random-string to /dev/caphash. Any user1 process that knows random-string can change its uid to user2 writing user1#user2#random-string to /dev/capuse.
On Linux, any privileged process can impersonate any unprivileged user with setuid(2) system call, but I do not know any mechanism to allow horizontal impersonation. How do Linux do it?
Serge E. Hallyn submitted p9auth to the Linux-kernel mailing list in April 2010, which would have provided pretty much this functionality (albeit in the last submitted form, with a slightly different interface). Unfortunately, it was not included in the Linux kernel.
The underlying security paradigm in Linux is vertical, rather than horizontal.
Privileges are separated into capabilities, and they can be acquired at exec time only. Extra privileges can be dropped at any time. In practice, you use filesystem capabilities and the setcap utility to give an unprivileged binary some specific capabilities whenever it is executed, regardless of the identity of the user executing it. (With Linux kernels 2.6.33 and later, it is no longer possible for any process to modify the capabilities of another running process.)
The key point to notice is that in Linux, only a privileged process (a process with the CAP_SETUID) can change its identity at run time.
In other words, point of exec is used in Linux for elevation of privileges, with the now-privileged binary changing to the specified user (and/or group and perhaps supplementary groups), dropping extra privileges. I am not aware of any mechanism that would allow an unprivileged process to change its credentials without an exec.
For the OP, this means that the Plan 9 interface (/dev/caphash, /dev/capuse) will not work. A comparable Linux interface implemented in userspace will require the exec of a binary as part of the change in credentials, but other than that, I don't know enough of OP's use cases to make any suggestion.
In-kernel, such an interface is obviously possible (as shown by the first link in this answer), just not available in the vanilla kernels.
In linux (and in unix in general) there's a similar feature that has to do with one of the bit permissions of an executable file. If you have an executable binary file, marked as setuid bit, then when you execute that file, the kernel runs that executable by setting the effective user id of the process to the owner of that file. So the mechanism works if you have execute permissions to execute that file. Let's suppose you want users a, b and c to impersonate user d on execution of some program. You first create a group of users (group setuid_d) in the system and put on it all the users a, b and c. then you create the executable, make it belong to user d, and group setuid_d. Once this has been done, as user d or as root make the file executable only by the group setuid_d and activate the set uid bit in the permissions
$ chgrp setuid_d program
$ chown d program
$ chmod ug+x,o-x,u+s program
$ program # you'll be effectively user d when executing program

Drop privileges as regular non-root user for sandboxing?

Is it possible to use a set of C library or system calls to drop all user privileges on POSIX, or at least on Linux? Note that I am not asking how to drop root privileges, which is what all of the other StackOverflow search results seem to be asking and answering.
I want the same effect as switching to user nobody, but stronger if possible. That is, I want my C application to do the following:
Run as a normal user, not root, and without the setuid file permission bit
Retain the ability to access specific files and open outgoing network connections
Voluntarily and permanently lose the ability to read and write files in specified (or all) directories, especially $HOME
If possible, give up or sandbox all other nonessential abilities, like opening a listening socket with accept
Things I have considered so far that don't fit the bill:
Switching to user nobody with setuid/setgid
Ordinary users are forbidden from switching to other users (like nobody), and the application should not require root just to switch to nobody.
Linux/POSIX.1e Capabilities
Capabilities only add root-like privileges, not take away ordinary user privileges
Traditional seccomp
My application will need more than just exit, sigreturn, read, and write
Things that look interesting, but for which I couldn't find documentation, appear to be unmaintained, or appear to be non-portable:
seccomp-bpf
AppArmor
grsecurity RBAC/role-based access control
So is there a well-documented, preferably portable way to drop nonessential user privileges and sandbox a process without having to become root first?
It's unlikely any solution will work on all POSIX, since POSIX doesn't define the mechanism you're looking for.
Looking at just the requirements and just Linux, probably the easiest way to satisfy them is actual via the security modules. Any of apparmor, selinux, RBAC will do what you need, but only via external profile - not something built into your app. The problem may be that adding a profile in all those cases requires the root user to do it (but the profile applies to user process too).
A bit more complicated solution that almost satisfies the requirements is seccomp. While it doesn't understand paths at all (you can only see pointers), there are ways to limit the access: seccomp policies can be defined per thread, so you could redesign your system to have a "path verification thread", which doesn't do anything apart from reading paths and returning sockets if they match your specification. Then limit that thread to just recv(), open() and send(). Thread doing other work can then drop open() and use the other service.
Or if you can configure the paths at program startup, you can put them into an array, mark that page as read-only, and setup seccomp policy which will only accept open() with filenames from that array (that's just a pointer comparison in that case).
To some extent, the approach of splitting application into separate processes which have very limited responsibilities is something you could replicate on other systems, but without the same guarantees as on Linux. For example qmail is kind of a system of very small processes which work as a pipeline for data (simplification). On Linux you could still apply seccomp to them, on Solaris just drop exec and other capabilities, on other systems... I don't know, but probably you can do something.

Can we change permissions from user to root?

I have a written a C program that creates a file "abcd.txt" and write some data into it. I was executing my code by logging with a username"bobby" and so the file abcd.txt was created with owner as bobby.
But my task is, even though I execute my code with some username "bobby", the file should always be created with owner as root. Can someone help me by saying how this could possible?
As a general principle you need your effective uid (euid to be root) either when you are are writing the file or when you perform a chown(2) on the file.
If you are doing this under Linux then there are linux specific methods that you can use.
Generic Solution
Without availability of sudo
This is the old UNIX DAC approach, it's fraught with peril. It assumes that you do not have something like sudo installed or cannot install it.
Your executable should be owned by root and have the executables setuid bit set.
Process
You should use seteuid () to drop your privileges from root to bobby for most of the operation, including writing. When you are done, bring your privilege level back up to root using seteuid(0) and perform a chown() (or fchown on the fd) on the file to change its ownership to root.
some basic safety
For safety set it up so that your executable is owned by root:safegrp where 'safegrp' is name of a group unique to users who are allowed to execute this file (add bobby to safegrp) ; and ensure that the setuid executable's mode is 4510 ;
With availability of sudo
If sudo is available on your system then follow the same process as above for dealing with privileges within the executable but DO NOT set the file mode to setuid, have safegrp added to sudoers for this executable and now bobby can run it with sudo /your/bin/prog
Linux specific solution
POSIX.1e
It is possible to have tighter control over the file use POSIX.1e capabilities support. In your case you wish to grant SYS_CHOWN to your program;
For security reasons, I would probably set that up as a COMPLETELY separate binary or a sub process and still use sudo and perform appropriate dropping of privileges.
linuxacl[ACL Using Access Control Lists on Linux] has excellent tutorial on this topic
SE-Linux
You can use Mandatory Access Control to limit the access to such a dangerous binary but SE linux is a pain to configure :^) although a possibly a good approach
You probably don't want to run your program as root, unless you really have to. Perhaps run "chown" from a shell script after running your program? Or, you can use chown(2) from a program running as root (or with equivalent capabilities, on linux).
Use the chown() method. There are probably more authoritative links, but this one is nice since it includes the calls to getpwnam(). I've done all of this in the past, but unfortunately I don't still have the code (it's owned by IBM).
http://manpages.courier-mta.org/htmlman2/chown.2.html

UID/GID change notification

My application creates a rudimentary ACL and communicates this to a Kernel Module. The ACL contains a list of UID/GID. The checks on these IDs are custom and on top of what the system already provides.
Now if the root/user changes UID/GID the ACL needs to be refreshed. Is there a way to get notification in an application whenever UID/GID changes e.g. through usermod command? Right now the platform is Linux but we could be porting this to other platforms as well(AIX/Solaris)
I'd say there is no way to reliably detect a change in the UID/Username mapping, especially when you go cross-platform. The user database may reside in NIS, NIS+, or nowadays, LDAP. They might be integrating their UNIX/Linux systems with a Windows Server running Active Directory, or they might be using something more obscure like Hesoid. I know of no way to receive any automatic feedback from these various databases. But also, any good book on UNIX Administration will tell you to not change these mappings, or at the very least, if you must, don't ever re-use a UID. Don't forget, the filesystem whether it's using standard POSIX permissions or POSIX ACLs will also be storing UIDs that won't be getting updates if an Administrator decides to change the UID for a user. The Kernel and filesystem both treat a specific UID as a specific user, regardless of their username. I really don't think you need to bother with the case of an Administrator changing UIDs for a user, it's likely to be too error prone for everyone.
Also, a quick look at NTFS on Windows will reveal that it also stores the equivalent of a UID called SID, it'a a long number used to represent a user and Windows does not provide or expect you to be changing the mapping of that SID to a specific Username. The SID is what the NT Kernel uses internally, not a username. If I open up the Security tab on a file, for a split second I may see numbers until Windows is able to query the Active Directory Controller and give convenient usernames to those numbers. Ultimately, it's the SID, not username that uniquely identifies the user.
On Linux, inotify does what you want. On other systems, try FAM.
One possible way (triggered from Frédéric's reply) is that I could possibly set a inotify/(dnotify gasp! for older kernels) operation on /etc/passwd because that file will always change for at least any change in local user privileges. Trouble is how to do this in NIS environment.
In the typical Unix security model, you should only care about the numerical value for GID/UID, not the mapping between human-readable string and numeric value. As that seems to be the case, have you carefully considered what you are trying to accomplish? Maybe it would be better to pass the name or a name/id tuple, instead of just the id?

C Privilege Escalation (With Password)

I need to write a C program that will allow me to read/write files that are owned by root. However, I can only run the code under another user. I have the root password, but there are no "sudo" or "su" commands on the system, so I have no way of accessing the root account (there are practically no shell commands whatsoever, actually). I don't know a whole lot about UNIX permissions, so I don't know whether or not it is actually possible to do this without exploiting the system in some way or running a program owned by root itself (with +s or whatever). Any advice?
Thanks!
P.S. No, this isn't anything malicious, this is on an iPhone.
Under the UNIX permissions system, you need to run a file owned by root itself that's marked setuid-root (+s, as you said) or communicate with some process that is already running as root.
If there is no such file, you are out of luck.
You can do this with setting suid bit to application, but if you want from this c application run a some shell this was be runned on local user if you do it normally this is security system.
However you can read/write/execute files owned by root, but if your user is not in group of file your target file must have setted read/write/execute on last 3 bits or when your user is in file owner group you must check/apply this to 3 bits in middle position. (3 first bits setting permission to owner but this may not by a usable information for you).
If you dont have any access to root account. Then if group and other user permissions dont access functions as you must have, you can't do with this anything except trying get some prilveaged user for access this file. In other cases you can do some fixes in file access permissions but not from this system, you must get hard drive from this device and attach to other to change it or load on this device some live system to change this. However you can do this on privleaged system not on this.
More information about SUID bits you can find at:
http://www.codecoffee.com/tipsforlinux/articles/028.html
http://www.everyjoe.com/newlinuxuser/explain-what-is-setuid-and-setgid/
The iPhone SDK doesn't allow this. Your application is sandboxed and it is not allowed to go outside of that sandbox except in very specific ways provided by Apple. The only way to do this on an iPhone is to jailbreak it.

Resources