Using mkdir in my bash script and getting permission denied - linux

i have script that is owned by root in a directory owned by root. part of the script is to make a directory that will hold the inputs/outputs of that script. i also have a sim link to that script so any user can run it from anywhere. i don't use the temp directory so this info can be used as logs later.
Problem: when a user tries to run the script they get an error that the directory cannot be created because of permission denied.
Questions: why won't the script make the directory so root owns it independent of what user runs it? how can the script make the directory so root owns it instead of the user that ran it? only the script needs this info, not the user.
Additional info:
the directory is: drws--s--x.
the script is: -rwxr-xr-x.
(if you need to know) the line in the script is simply: mkdir $tempdirname
i am matching the permissions of other scripts on the same server that output text files correctly, but since mine is a directory i'm getting permission errors.
i have tried adding the permissions for suid and sgid. suid sounded like the correct solution since it should make the script run as if it were run by the user that owns the script. (why isn't this the correct solution?)
i would like any user to be able to type in the sim link name, that will run the script that is owned by root in the directory that is owned by root, and the directories created by that script will stay in its own directory. and the end user has no knowledge or access to the inner workings of this process. (hence owned by root)

Scripts run as the user that runs them; the owner of the file and/or the directory it's in are irrelevant (except that the user needs read and execute permission to the file and directory). Binary executables can have their setuid bit set to make them always run as the file's owner. Old unixes allowed this for scripts as well but this caused a security hole, so setuid is ignored on scripts in modern unixes/Linuxes.
If you need to let regular users run a script as root, there are a couple of other ways to do this. One is to add the script to your /etc/sudoers file, so that users can use sudo to run it as root. WARNING: if you mess up your /etc/sudoers file, it can be hard to recover access to clean it up and get back to normal. Make a backup first, don't edit it with anything except visudo, and I recommend having a root shell open so if something goes wrong you'll have the root access you need to fix it without having to promote via sudo. The line you'll need to add will be something like this:
%everyone ALL=NOPASSWD: /path/to/script
If you want to make this automatic, so that users don't have to explicitly use sudo to run the script, you can start the script like this:
#!/bin/bash
if [[ $EUID -ne 0 ]];
then
exec sudo "$BASH_SOURCE" "$#"
fi
EDIT: A simpler version occurred to me; rather than having the script re-run itself under sudo, just replace the symlink with a stub script like this:
#!/bin/bash
exec sudo /path/to/real/script "$#"
Note that with this option, the /etc/sudoers entry must refer to the real script's path, not that of the symlink. Also, if the script doesn't take arguments, you can leave the "$#" off. Or use it, it won't do any harm either.
If messing with /etc/sudoers sounds too scary, there's another option: you could "compile" the script with shc (which actually just makes a binary executable wrapper around it), and make that setuid root (chmod 4755 /path/to/compiled-script; chown root /path/to/compiled-script). Since it's in a binary wrapper, setuid will work.

Related

Linux setuid bit [duplicate]

I created this simple script to allow the user to remove files created by the web server in his home directory without giving him "su". Both scripts are set with "chmod 4750".
The craziest thing is that they DID work and now they don't. Here's the scripts:
#!/bin/bash
# Ask for directory to delete
echo "Enter the file or directory you would like to delete, the assumed path is /home/user"
read DIRECTORY
rm -rf /home/user/"$DIRECTORY"
echo "Deleting /home/user/$DIRECTORY ..."
exit 0
2:
#!/bin/bash
# Reset permissions
echo "Resetting the ownership of the contents of /home/user to user."
chown -R user /home/user
exit 0
I will make them a little more advanced and work for multiple users but right now I cannot even get the simple version to work. It works when run as root of course. It used to work when run as user 'user' but now it doesn't. I get this:
user#dev:/home/user$ delete.sh
Enter the file or directory you would like to delete, the assumed path is /home/user/[your input]
test-dir
rm: cannot remove ‘/home/user/test-dir/test-file’: Permission denied
Deleting /home/user/test-dir ...
and
chown: changing ownership of ‘/home/user/test-dir’: Operation not permitted
What can possibly be the problem?
-rwsr-x--- 1 root user 291 Nov 6 05:23 delete.sh
-rwsr-x--- 1 root user 177 Nov 6 05:45 perms.sh
There is a pretty comprehansive answer at https://unix.stackexchange.com/questions/364/allow-setuid-on-shell-scripts
Bottom line is that there are two main points against it:
A race condition between when the Kernel opens the file to find which interpreter it should execute and when the interpreter opens the file to read the script.
Shell scripts which execute many external programs without proper checks can be fooled into executing the wrong program (e.g. using malicious PATH), or expand variables in a broken way (e.g. having white space in variable values), and generally it has less control on how well the external programs it executes handle the input.
Historically, there was a famous bug in the original Bourne shell (at least on 4.2BSD, which is where I saw this in action) which allowed anyone to get interactive root shell by creating a symlink called -i to a suid shell script. That's possibly the original trigger for this being prohibited.
EDIT: To answer "How do I fix it" - configure sudo to allow users to execute only these scripts as user root, and perhaps use a trick like in https://stackoverflow.com/a/4598126/164137 to find the original user's name and force operation on their own home directory, instead of letting them pass in any arbitrary input (i.e. in their current state, nothing in the scripts you include in your question prevents user1 from executing the scripts and passing them users2's directory, or any directory for that matter)

How to get around subshell problem with sudo and file permissions

I have a specific problem. Here's a simplified example:
File /opt/test is owned by root. Has file permissions of 700.
I need to cp /opt/test /home/user/.
So I need this exact command set in my sudoers file. I can't open up permissions to any other command.
But if I put this as a NOPASSWD command in /etc/sudoers it doesn't work because my user does not have permissions to see /opt/test before it su's to the root user (sudo is 'globbing' or whatever the file paths before it runs an su to root).
How can I invoke this command in a subshell or something so that I can get the exact command laid out in /etc/sudoers? Putting the command in a script and then laying out the path to the script in sudoers fails (permissions). I think I need to invoke a subshell of sorts, but don't know how to lay that out in sudoers.

Sharing dotfiles with the root user

Current method
Actually, I'm sharing some of my dotfiles with the root user using symbolic links:
ln -s ~user/.vimrc /root/
ln -s ~user/.zshenv /root/
ln -s ~user/.zlogin /root/
ln -s ~user/.zshrc /root/
Former method
Before, I was using the sudo command with the -E which preserves the environment. So, the root user, when in an interactive shell, use the standard user home directory and read the corresponding dotfiles.
It works, but :
Some files may be created in the standard user directory with root as owner
Some commands does not allow (or warn me) using files on directory which the owner is not the current user (it's obviously for security reasons). So, executing those commands as root is problematic.
Better method ?
The simplest method is to put shared settings in the system-wide configuration files (/etc/zshrc, /etc/vimrc).
But I want to keep all the settings in my home directory, where I can keep them synchronized with a Git remote repository. This way, I can deploy them easily on a new computer.
As my current method is tedious and the former was pleasant but problematic,
is there a better method to make root use my current configuration file ?
What I usually do is to include a deployment script in the git repository. I then invoke that script using sudo. The script then runs with root credentials and updates the dotfiles, either in the root account or globally.
I keep the install script as light as possible with no dependencies beyond shell and the core utilities (so no rsync).

How to run a .sh-script from any path in a terminal?

I know how to run the script I created. But it is a matter of pain that I need to change directory through terminal and run my scripts.
I need to run the slowloris script, that has into Desktop, now change directory to Desktop and run.
Then I have another in root; now change the directory to root and run that.
My question is:
How can I run any shell-script by just typing ./script from any path like we start Metasploit from any path by giving msfconsole from any path.
One option is simply to type the path to the script:
~/Desktop/script
This works fine, but gets a bit unwieldy.
This is what the PATH environment variable is for. And it is what $HOME/bin is for.
Create yourself a directory $HOME/bin. Put all your executable scripts in it (make them executable with chmod +x script if need be††). This way, there's one place to look for the scripts you want to run.
Add $HOME/bin to your PATH. I put mine at the front: PATH="$HOME/bin:$PATH, but you could put it at the back if you prefer.
Update your .profile or .bash_profile (or possibly .bashrc) file to set PATH. Beware of a continually growing PATH, though.
As tripleee noted, once the command is installed in a directory on PATH, you no longer type ./script, but just script. This is exactly like you type ls and not /bin/ls, etc. Once the program is installed in a directory on your PATH, it is (for many purposes) indistinguishable from a system-provided command.
I have about 500 scripts and programs in my $HOME/bin directory.
Note that this doesn't require any special privileges. If you have administrator access to your machine and you think other users might find your commands useful, then you could install the scripts/programs in one of the system-provided directories on your PATH. However, it is usually best not to add programs to any of:
/bin
/usr/bin
/sbin
/usr/sbin
There is often/usually /usr/local/bin which is a suitable place for widely used commands not provided by the system.
†† It would be better to use chmod a+x,go-w script; your scripts should not be writable by other people. You could even simply use chmod 555 script or chmod 755 script. I tend to keep my scripts non-writable. That way, I have to go through a formal change process with the version control system. It means there's less danger of uncontrolled changes.
You have to copy or link the script into a directory that is on the $PATH. Usually /usr/bin and /usr/local/bin/ are on the path so these are good locations to link or copy the script to.
ln -s /path/to/your/script /usr/local/bin
If you are not root you will either need to sudo that command or run it as the root user.

ssh not working correctly with sudo

Good morning everyone! I have a bash script starting automatically when the system boots via the .profile file in the users home directory:
sudo menu.sh
The script starts just as expected however, when calling things like ssh UN#ADDRESS inside the script, the known_hosts file gets placed in the /root/.ssh directory instead of the user account calling the script! I have tried modifying .profile to call 'sudo -E menu.sh' and 'sudo -H menu.sh', but both fail to have the known_hosts file created in the users home directory that's calling the script. My /etc/sudoers is as follows:
# Declarations
Defaults env_keep += "HOME USER"
# User privilege specification
root ALL=(ALL) ALL
user ALL=NOPASSWD: ALL
Any help would be appreciated!
Thanks
Dave
UPDATE: so what I did as a work around is go through the script and add 'sudo -u $USER' before specific calls (since sudo is supposed to keep the $USER env var). This to me seems like a very bad way of resolving this problem. It sudo is supposed to keep the USER and HOME directory variables upon launching menu.sh, why would I need to explicitly call sudo once again as a specific user in order to retain that information (even though sudo is being told to keep it via the /etc/sudoers file). No clue, but wanted to update this post for anyone that comes across it until a better solution can be found.
Regarding OpenSSH, the default location for known_hosts is ~/.ssh/known_hosts. Ssh doesn't honor $HOME when expanding a "~" in a filename. It looks up the user's actual home directory and uses that. When you run ssh as root, it's going to interpret that pathname relative to root's home directory no matter what you've set HOME to.
You could try setting the ssh parameter UserKnownHostsFile to the name of the file you'd like to use:
ssh -o UserKnownHostsFile=$HOME/.ssh/known_hosts user#host...
However, you should test this. Ssh might complain about using a file that belongs to another user, and if it has to update the file then the file might end up being owned by root.
Really, you're best off running ssh as the user whose .ssh folder you want ssh to use. Running processes through sudo creates a risk that the user can find a way to do things you didn't intend for them to do. You should limit that risk by using the elevated privileges as little as possible.

Resources