Allow user to run binary as root - linux

I have a script written by someone else, which mounts a file system, and I would like to reproduce it.
The script has been compiled with shc, and is used to mount a filesystem for a particular user, but is able to be run with root priveleges. The guess is it does something like this mount_script.sh:
#!/bin/bash
mount -t cifs -o username=$USER,domain=my_domain //hostname.com/Files /mnt/${USER}-drive
I have compiled the script with shc and then applied
chmod u+s mount_script.sh.x
so that
-rwsr-xr-x. 1 root root 11088 Feb 15 14:11 mount_script.sh.x
matches the original compiled bash script's permissions, the original is wrapped with the following mount_drive.sh
#!/bin/bash
if [ "$(mountpoint -q /mnt/${USER}-drive/ && echo "mounted" || echo "not mounted")" = "not mounted" ]; then
echo
echo "Not mounted, running mount script..."
echo
mount_script.sh.x
else
echo
echo "The drive is already mounted at /mnt/${USER}-drive..."
echo
fi
WIth permissions:
-rwxr-xr-x 1 root root 335 Sep 20 10:58 /usr/local/bin/mount_drive.sh
When I try and run it as my normal user i get:
Not mounted, running mount script...
mount: only root can use "--options" option
What should the script contain to avoid this probelm and allow the $USER to run it successfully?
Is there any reason this would be a stupid idea from a security perspective?
Thanks!

If this is NOT intended for multiple users, then the simplest (and most secure) method is for the partition to be mounted via fstab with a specified user as owner of the partition and restricted privileges. Namely,
UUID={something} / ext4 defaults,nosuid,uid=1000,gid=1000,fmask=0077,dmask=0077 0 1
That would have the partition mounted every time the system boots, but only the specified user could access that (or anyone with sudo privileges able to assume that identity). If that leaves it too open, you could consider whether to encrypt that partition as well. Implementing that is beyond my experience, but would allow only that user to mount/use/access on basis of the password required to mount. You also have to control the who and how the partition encryption password is changed.
If you pursue the encryption option, you can avoid the fstab approach, and allow the user to mount/unmount at will, since he would be the only one with the password.
The danger with encryption is that when the password is set, it needs to be stored securely, so that administrators can use to recover data when (not if) the organization loses the person that had the "master key".

Related

test -x in Mounted Filesystem

I'm using QEMU to test Raspberry Pi before putting the image onto an SD card. I'm setting up an automated script to put some files onto the Pi, among other things, so that when I put the SD card into the Pi, it is immediately usable. I think I've run into a quirk in how permissions work, but I'm not sure.
When you run test -x, the file is supposed to be executable. Basically, the x bit is supposed to be on for your user. However, this doesn't seem to apply to files inside mounted filesystems.
The host is Ubuntu, and the guest backing image is Raspberry Pi Buster. I created the mountpoint with guestmount, because I was mounting a snapshot, not the original, and this seems to be the only/best way to do that. The basic flow was:
qemu-img convert -Oqcow2 raspberry-pi.img raspberry-pi.qcow
qemu-img create -f qcow2 snapshot.qcow -b raspberry-pi.qcow
sudo guestmount -a 'snapshot.qcow' -i 'mountpoint/'
For example, I have a file outside the repository. The file I'm testing inside the mountpoint was created by root, so I chmoded this file to root for comparison:
$ sudo ls -l --author ~/test/file
-rw-r--r-- 1 root root root 1133 Oct 8 21:43 /home/me/test/file
$ sudo test -x ~/test/file && echo 'exists' || echo 'doesn\'t exist'
doesn't exist
However, for a file inside the mountpoint, with the same permissions, the test is successful:
$ sudo ls -l --author mountpoint/home/pi/test/file
-rw-r--r-- 1 root root root 0 Oct 8 22:41 mountpoint/home/pi/test/file
$ sudo test -x ~/test/file && echo 'exists' || echo 'doesn\'t exist'
exists
Why is the file inside the mountpoint executable, whereas the one outside is not executable? Is this because the mounted filesystem is a different architecture (x86 vs. ARM)? Is it because I'm using guestmount, and the filesystem isn't the real filesysem, but an amalgamation of the snapshot & the original file? Or is this just the way mounting works? Where can I find more resources on this peculiar behavior, like other permission quirks I might encounter?
If you need any more information about the host or guest, please ask.
This is a bug in libguestfs used by guestmount. You can see it here:
/* Root user should be able to access everything, so only bother
* with these fine-grained tests for non-root. (RHBZ#1106548).
*/
if (fuse->uid != 0) {
[...]
if (mask & X_OK)
ok = ok &&
( fuse->uid == statbuf.st_uid ? statbuf.st_mode & S_IXUSR
: fuse->gid == statbuf.st_gid ? statbuf.st_mode & S_IXGRP
: statbuf.st_mode & S_IXOTH);
}
The FS takes a shortcut saying that since you're root you have full access, so there's no point checking the permissions.
As you've demonstrated, this is not true. Root should only have execute permissions for directories, and for files where at least one of the execute bits is set.
I was unable to build the project to submit a patch, but you can file a bug.

Normal user touching a file in /var/run failed

I have a program called HelloWorld belonging to user test
HelloWorld will create a file HelloWorld.pid in /var/run to keep single instance.
I using following command to try to make test can access /var/run
usermod -a -G root test
However, when I run it, falied
could someone help me?
What are the permissions on /var/run? On my system, /var/run is rwxr-xr-x, which means only the user root can write to it. The permissions do not allow write access by members of the root group.
The normal way of handling this is by creating a subdirectory of /var/run that is owned by the user under which you'll be running your service. E.g.,
sudo mkdir /var/run/helloworld
sudo chown myusername /var/run/helloworld
Note that /var/run is often an ephemeral filesystem that disappears when your system reboots. If you would like your target directory to be created automatically when the system boots you can do that using the systemd tmpfiles service.
Some linux systems store per-user runtime files in /var/run/user/UID/.
In this case you can create your pid file in /var/run/user/$(id -u test)/HelloWorld.pid.
Alternatively just use /tmp.
You may want to use the user's name as a prefix to the pid filename to avoid collision with other users, for instance /tmp/test-HelloWorld.pid.

How the privileged commands are controlled?

How the Operating system prevents normal users from executing commands like fdisk and umount eventhough the commands have execute permissions for everyone ?
[root#r7prd1 ~]# ls -la $(which umount)
-rwsr-xr-x. 1 root root 31960 Aug 21 2015 /usr/bin/umount
[root#r7prd1 ~]# ls -la $(which fdisk)
-rwxr-xr-x. 1 root root 182472 Aug 21 2015 /usr/sbin/fdisk
There probably may be some situations when it may be worth to disallow user to execute any binaries (I suppose it may be one of countermeasures against privilege escalation exploits). But in many cases regular users are able to execute their own binaries, so what if user will write and compile fdisk or something similar by himself? Really, you don't want to disallow user to run fdisk. You just want to disallow fdisk or any other program to modify the system state in some way. So regular user really can execute fdisk:
$ fdisk --help
Usage:
fdisk [options] <disk> change partition table
fdisk [options] -l [<disk>] list partition table(s)
...
What regular user actually cannot do is executing restricted operations:
$ fdisk /dev/sda
Welcome to fdisk (util-linux 2.27.1).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
fdisk: cannot open /dev/sda: Permission denied
So fdisk started successfully, printed some messages. Then it tried to open raw disk device /dev/sda and it was that operation that was really restricted by permissions, so fdisk just complained that it cannot do anything and exited.
There are some cases, though, when you may want to restrict executability of some binaries by some users. When administrator or OS maintainer want regular user to be able to execute some privileged action (such as mounting some partition that this particular user is allowed to by some record in the /etc/fstab), them set up some special hardened binaries such as mount or sudo with set-user-ID permission:
$ ls -l /bin/mount /usr/bin/sudo
-rwsr-xr-x 1 root root 40152 May 27 02:31 /bin/mount
-rwsr-xr-x 1 root root 136808 Aug 17 16:20 /usr/bin/sudo
When such binary is executed, the kernel gives it not the user ID of the calling user, but, in this case, UID 0 (root). Because regular user cannot set binaries up this way (root owner and set-UID bit set), then it may be theoretically worth restricting executability of these binaries to some particular group (but in the above case, they are world-executable and check permissions of calling user by themselves. I don't really know, if executability restrictions of set-UID executables cannot be circumvented in some way and whether such as approach is really widely used by someone).
And one extra note: in case of fdisk on your system, it is installed to /usr/sbin directory that may or may not be in the PATH variable of regular users, so fdisk may or may not be executed by regular user by just typing fdisk at command prompt, but it is not really a restriction (one may simply specify full path to executable on the command line).

cp/rsync command with destination as symlink to a directory

I am working on a cPanel backup solution at the moment. We are now informed about this exploit.
Exploit : Full ROOT ACCESS to server
1.) create malicious file from, normal user account:
mkdir root
echo "hello" > root/.accesshash
2.) Wait for backup to run
3.) Replace root with a symlink:
ln -s /root root
4.) Restore root/.accesshash ( I am running this command as root for this: "cp -rf /backup/.accesshash /home/username/root/")
5.) User now have root access because We overwrote /root/.accesshash. An attacker will be able to login to WHM as root by placing a access hash into this file.
root#cpanel [/home/master]# cat /root/.accesshash
hello
root#cpanel [/home/master]# ls -l /root/.accesshash
-rw-r--r-- 1 master master 3 Nov 20 21:41 /root/.accesshash
root#cpanel [/home/master]#
Can somebody advise me on this for a workaround? Thanks in advance.
The key problem here is running the restore command as root. When doing it for a specific restricted user (who might have malicious intents), you must run it as that user (or maybe as an even more restricted one, restoring files in a sandbox and copying them back later).

chmod cannot change group permission on Cygwin

I am using Cygwin and trying to change the group access permission with chmod, e.g.
$ls -l id_rsa
-rwxrwxr-- 1 None 1679 Jun 13 10:16 id_rsa
$ chmod g= id_rsa
$ ls -l id_rsa
-rwxrwxr-- 1 None 1679 Jun 13 10:16 id_rsa
But this does not work. I can change permission for user and others. Seems that the permission level for group somehow keeps the same as that of user?
I was having a similar problem to you, and I was using the NTFS filesystem, so Keith Thompson's answer didn't solve it for me.
I changed the file's group owner to the Users group:
chown :Users filename
After doing that I was able to change the group permissions to my will using chmod. In my case, since it was an RSA key for OpenSSH, I did:
chmod 700 filename
And it worked. In Cygwin you get two groups by default, the Root group and the Users group. I wanted to add another group, but I wasn't able to do it with the tools I'm used to use on Linux. For that reason I just used the Users group.
Cygwin doesn't like files to be owned by groups that it doesn't know.
Unfortunately, that happens quite often in Cygwin, especially if your PC is in a Windows domain where things keep changing.
I also synchronise my files between two PCs, via an external drive, and the uids/gids are different between the different PCs, so this is a source of problems.
If you do ls -l and see a numeric group id instead of a group name, it means Cygwin doesn't know the gid - i.e. it's not in /etc/group, and Cygwin can't query it from Windows either. You can confirm this by running getent group <gid>, where <gid> is the numeric group id.
To fix it, you can either use chgrp to change the group for all affected files/directories, as described in the accepted answer above, or create an entry for the unknown gid in /etc/group, with any unused group name (e.g. Users2).
After doing this, it may be necessary to close all of your Cygwin windows and then re-open them.
An experiment shows that chmod does work correctly to change group permissions under Cygwin.
The experiment used a file on an NTFS partition. Cygwin implements a POSIX layer on top of Windows, but it still ultimately uses the features of Windows itself, and of the particular filesystem implementation.
On modern versions of Windows, most hard drives are formatted to use NTFS, which provides enough support for chmod. But external USB drives typically use FAT32, which doesn't have the same abilities to represent permissions. The Cygwin layer fakes POSIX semantics as well as it can, but there's only so much it can do.
Try
$ df -T .
If it indicates that you're using a FAT32 filesystem, that's probably the problem. The solution would be to store the file on an NTFS filesystem instead. A file named id_dsa is probably an SSH private key, and it needs to be stored in $HOME/.ssh anyway.
Is your home directory on a FAT32 partition? As I recall, recent versions of Windows ("recent" meaning the last 10 or more years) are able to convert FAT32 filesystems to NTFS.
The remainder of this answer was in response to the original version of the question, which had a typo in the chmod command.
Cygwin uses the GNU Coreutils version of chmod. This,
chmod g=0 fileName
is not the correct syntax. I get:
$ chmod g=0 fileName
chmod: invalid mode: `g=0'
Try `chmod --help' for more information.
(This is on Linux, not Cygwin, but it should be the same.)
To turn off all group permissions, this should work:
$ chmod g= fileName
$ ls -l fileName
-rw----r-- 1 kst kst 0 Jun 13 10:31 fileName
To see the chmod documentation:
$ info coreutils chmod
To see the documentation on symbolic file mode:
$ info coreutils Symbolic
The format of symbolic modes is:
[ugoa...][+-=]PERMS...[,...]
where PERMS is either zero or more letters from the set 'rwxXst', or a
single letter from the set 'ugo'.
Like previous answers, not recognized groups cause such issues. It mostly happens in Windows Domains.
The easiest way to fix it is regenerate your /etc/passwd and /etc/group files (parameter -d is needed for domain users):
mkpasswd -l -d > /etc/passwd
mkgroup -l -d > /etc/group
Close and launch Cygwin again.
This is a very annoying issue for me. In my case user135348's solution worked best. The biggest issue with the chown :Users -R approach is that every time a new file is created, it will be assigned to the unknown gid 1049120. It's very frustrating to keep changing file gid.
I tried mkgroup too, but in my case it didn't work: My gid is 1049120.
Based on the rules explained in Mapping Windows SIDs to POSIX uid/gid values : : 0x100000 offset is used for account from the machine's primary domain.
Trying to remove the same offset from 1049120, you get 544, which is built-in Administrators group's RID.
This account is not a member of the local Administrators group; we use SuRun to grant administrator rights without giving out credentials. In this case, mkgroup failed to generate all the possible gids.
Editing the group file and adding a customized group name seems always to fix the issue easily.
I had this issue when working remotely from the Domain and using cygserver.
Running ls -l showed a numeric group id instead of a group name.
I stopped cygserver, net stop "CYGWIN cygserver, and other Cygwin processes, then ran the ls -l again, and group names were then displayed correctly.
I guess cygserver was holding incomplete domain group information.
After restarting cygserver the system continued to work correctly.
#!/bin/bash
find . |while read obj; do
if [[ -d "$obj" ]]; then
setfacl --set "user::rwx,group::r-x,other::r-x" "${obj}"
elif [[ -f "$obj" ]]; then
setfacl --set "user::rw-,group::r--,other::r--" "${obj}"
fi
done
You must specify the group name on the Windows system which your user belongs to.
So I just did this:
chown -R ONEX:Users ~/*
You can find your user name and group here:

Resources