I'm writing a simple package manager and I'd like to automatically try sudo if the program isn't run as root. I found a function called seteuid, which looks likes it's exactly what I need, but I don't have the permissions to run it. So far all I can think of is a bash script to check before they get to the actual binary, but I'd like to do this all as C++ if possible.
Is there any method of changing a processes's euid after it starts executing? Or a way to call sudo?
Here's how these functions work.
If a program has the setuid bit, it will execute as it's owner. Once it is executing, it can call seteuid to run as the original user instead of its owner. Ditty for setgid.
The principle is the principal of least privilege. If I write a program that needs special access, I want as little code as possible to run with the access. So, I install it setuid, but the first thing it does it give back the privileges until the narrow window of code that needs them.
You can't call sudo (except, of course, via fork/exec). You can be a program like sudo that is installed setuid and which decided when to use that awesome power appropriately.
As bmargulies says in his answer, you can do this if you binary is owned by root and has the setuid bit set - but then you will need to implement the authentication part (checking that the user is actually allowed to become root) yourself too.
You'd be essentially rewriting sudo within your application - the best way to handle this is to do what you suggested yourself, and install your application with a wrapper script that uses /usr/bin/id to check if it is root, and if not, call out to sudo (or su).
Related
I am writing a C/C++ program that needs to be able to mount a disk as an ordinary user (can't run with sudo). Typically, questions of this type pertain to using the mount command in a shell, and the answer is to use the "user" option in the /etc/fstab entry corresponding to the disk in question. However, I don't think that the listings in the /etc/fstab matter at all when using the mount system call in a program.
However, since it is clear that the mount command is capable of allowing non-root users to mount disks (assuming the /etc/fstab is setup right), and presumably the mount command calls the mount system call, then I think it should be possible to achieve what I want.
How can I successfully call the mount() system call without running the program with sudo?
A valid solution to this dilemma is to pack the mount/umount calls into a shell script, provide sudo permissions for that to the application user, and call it from the application e. g. using system(). Make sure that the script does adequate error handling and perhaps logging, returning the appropriate exit code on error or success you can handle in the calling application.
/etc/sudoers.d/myApplication:
<appUser> <host> = (root) NOPASSWD: /usr/local/bin/myMountScript.sh
In your application:
const int result = system("sudo /usr/local/bin/myMountScript.sh <options>");
//Error handling on result follows below
Another possibility is to use capabilities, as mentioned in a comment above, and set them on the binary, but that's bit more complex, so I don't get into details here.
How do you set a program to ask for elevation upon execution? I've asked around here and there, but haven't gotten an answer. I'm not sure how I would do this, but the program that i want to write, needs permissions to be run.
Security models are rather platform-specific. Qt does not AFAIK address this sort of thing. (Case in point: the Qt Creator installer itself choked when I didn't run it as root.)
You'll presumably need to make native calls or interact with some daemon designed for the purpose. Often easiest to try whatever it is you think you should be able to do, and check for failure, and if you can't do what you want then ask the user to explicitly re-run with higher privileges.
Linux:
Best way elevate the privileges programmatically under different versions of Linux?
Windows:
http://msdn.microsoft.com/en-us/magazine/cc163486.aspx
Mac:
Escalate App Privileges Programmatically OS X
(Note: Often if you have to ask a question about something like this, there may be a better way to do whatever it is you're trying to do. Consider posting a question that is more general about what you want, and you might get suggestions on a way to do it more cleanly.)
I don't think it is possible to ask to be elevated automatically.
The only way I can think of doing it would be to have a service running as a Local Administrator account and performing elevated run for you.
I have used this when installing/uninstalling MSI packages autmatically as part of a CI Build (Go Agent runs as Local System Account)
I have a user-level C++ test application running on a linux mobile device. One of the test involves enabling/disabling printer paper sensor which requires root privileges writing on a device file. Is there a way to grant my application that kind of privilege? If none, is there a workaround for that?
This will do,
as root execute:
chown -v root:root /path/to/yourapp
chmod -v 4755 /path/to/yourapp
or alternatively
chmod -v u+s /path/to/yourapp
or alternatively
man chmod
This will not work with scripts. And yes, you should take seriously what jdizzle said about dropping unnecessary privileges.
Another way to solve this is to make the user who runs the application a member of the group that owns the device file. For example,
ls -la /dev/devicefile
crw-rw---- 1 root printer 4, 0 may 6 10:56 /dev/devicefile
members of the printer group can read and write to the device, so you just need to add joe to the printer group (and restart the session).
gpasswd -a joe printer
If you need to adjust the devicefile permissions, you probably will need to edit udev rules to make it permanent. But chmod should work too.
Other options worth investigating: setcap(8) (nice guide here) and sudo(8).
You can set the program setuid root, which means it will always run as root even when run by a user. This typically requires special care to drop privileges inside the program once the necessary actions requiring root access are completed.
You could also have a helper program, itself setuid root -or with appropriate capabilities, or started thru sudo- which communicate with the printer. Your main application would fork & exec that program and communicate with it thru pipes, so it should not be itself running as root.
The helper program would be a simple executable (with appropriate capabilities) which would only be started by your main application (not directly by the user) and communicate with it thru pipes or program arguments, etc.
A lot of graphical administrative programs are done likewise: the graphical part is a program separated from the administrative part, and they communicate appropriately. Only the administrative program (usually existing command line programs like adduser) need special privilege.
you should definitey try to avoid running your program as "root", as this would not only allow your program to read/write /dev/sensordevice but it would grant access to virtually everything on your system (including the ability to completely brick it)
you should therefore try to add fine-grained access to just the ressource you need, using proper groups and making sure that your device-file grants your group write access.
see (e.g.) udev on how to write a proper udev rule, that grants write access for a certain device to a given group.
I am designing an C++ app that, among other things, executes a few scripts every now and then. The app should be efficient and preferably platform independent.
The issue is, however: is there a reason one shouldn't use system() call for launching scripts and use, for example, POSIX facilities instead? The discussion on the matter that I've seen so far usually boils down to:
system() is less flexible. (Fine with me)
It offers no control of the command being executed. (Fine with me, I just need a return value from the script)
It is not quite platform independent. (Now, this would be a concern. I would really love to see an example where it behaves differently on different platforms)
It is a security concern. (Again, this would be an issue. Can someone provide an example of a potential security problem with system()? )
Any other issues?
3) It is not quite platform independent (Now, this would be a concern. I would really love to see an example where it behaves differently on different platforms)
Well, for instance system("ls") would probably fail in Windows, since there is no ls command.
4) It is a security concern. (Again, this would be an issue. Can someone provide an example of a potential security problem with system() ? )
If the argument passed to system comes from user input, and not properly validated, it can be used to execute unwanted things with the privilege levels of the original executer. If its static content, its quite easy to find that within an executable image and modify it to do nasty things as well.
(3) If you just want a counterexample, for example grep behaves differently on Solaris vs Linux vs whatever.
(4) Your program's privileges are inherited by its spawned programs. If your application ever runs as a privileged user, all someone has to do is put their own program with the name of the thing you shell out too, and then can execute arbitrary code (this implies you should never run a program that uses system as root or setuid root).
(5) It will probably be saner to maintain in the long run to use the posix facilities because you won't have to rely on a specific set of external scripts or binaries already existing wherever your program runs.
I maintain a system that consists of several separate executables. In this case I have control over the permissions, names, calling conventions, security over all supported platforms. In this case, system() works just fine. The applications communicate through a RDBMS.
Again, as others have noted "The Devil's in the details".
Regarding security concerns, a classical example about (4) is the following scenario: imagine the user is prompted to give some directory name to be backed up into a std::string dirname; then you'll compute some backup directory name into a std::string backup and do
system((std::string{"cp -a "} + dirname + " " + backup).c_str())
Now think what happens if a malicious user enter foo bar; rm -rf $HOME; ls as the dirname and backup is /vol/backup_2015_fev/. The system command would execute
cp -a foo bar; rm -rf $HOME; ls /vol/backup_2015_fev/
which is not what you expected (all the user's $HOME would be deleted!). This is an example of code injection, and when using system you should ensure that it never happens (e.g. by sanitizing and/or escaping every user input related string)
Also, the PATH might not be what you believe it is (e.g. starting with /tmp/ and a malicious user having done ln -s /bin/rm /tmp/cp before your system runs).
I used the system() call in my CGI C++ app under windows and Linux too.
One problem I had was when using system() was not having the proper access rights to execute my skript with the web user.
I did not have that problem any more when using the CreateProcess() method.
Whatever command you want to execute just store that in a file c.txt. Pass that file to the execl() like as done below.
fd = open("c.txt", O_CREAT | O_RDWR, 00777);
write(fd,arr,sizeof(arr));
if(fork() == 0)
{
execl("/bin/sh", "sh", "-c","sh c.txt", (char *) 0);
}
Our app is ran from SU or normal user. We have a library we have connected to our project. In that library there is a function we want to call. We have a folder called notRestricted in the directory where we run application from. We have created a new thread. We want to limit access of the thread to file system. What we want to do is simple - call that function but limit its access to write only to that folder (we prefer to let it read from anywhere app can read from).
Update:
So I see that there is no way to disable only one thread from all FS but one folder...
I read your propositions dear SO users and posted some kind of analog to this question here so in there thay gave us a link to sandbox with not a bad api, but I do not really know if it would work on anething but GentOS (but any way such script looks quite intresting in case of using Boost.Process command line to run it and than run desired ex-thread (which migrated to seprate application=)).
There isn't really any way you can prevent a single thread, because its in the same process space as you are, except for hacking methods like function hooking to detect any kind of file system access.
Perhaps you might like to rethink how you're implementing your application - having native untrusted code run as su isn't exactly a good idea. Perhaps use another process and communicate via. RPC, or use a interpreted language that you can check against at run time.
In my opinion, the best strategy would be:
Don't run this code in a different thread, but run it in a different process.
When you create this process (after the fork but before any call to execve), use chroot to change the root of the filesystem.
This will give you some good isolation... However doing so will make your code require root... Don't run the child process as root since root can trivially work around this.
Inject a replacement for open(2) that checks the arguments and returns -EACCES as appropriate.
This doesn't sound like the right thing to do. If you think about it, what you are trying to prevent is a problem well known to the computer games industry. The most common approach to deal with this problem is simply encoding or encrypting the data you don't want others to have access to, in such a way that only you know how to read/understand it.