Why do my setuid root bash shell scripts not work? - bash

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)

Related

Using source command for other users logged in

My problem is about using the source command for everyone logged in.
Let's say I have a file with the content:
#!/bin/bash
alias ha='echo test'
Now if I source it and write ha, I'd get the message test.
Now what if there's someone else logged in, and I want it to be sourced for his account? Can you write something like source (username) (filename)?
Provided that other uses have read permission to your script, and read permissions to its directory and parent directories, they can source that file. Assuming your user name is "thesourcequestion", and you are keeping the alias file (let's call it alias ) in your home directory, other users can source it with the following command:
source ~thesourcequestion/alias
Or just (same thing):
. ~thesourcequestion/alias
Incidentally, some shells only accept the source keyword (like c-shell IIRC).
If you are the admin of the box, consider the solution presented here:
https://askubuntu.com/questions/610052/how-can-i-preset-aliases-for-all-users/986053
In short, there are system files that can be modified that will create the alias for users. The alias will be available to them next time they login.
Don't overlook the part of my answer about providing permissions to your file. For example, you can give read permissions to the file this way:
chmod a+r ~thesourcequestion/alias
The above syntax adds (+) the read attribute (r) to all (a).

run shell script in one line from applescript and provide input

I'm trying to automate the installation of a program that needs to be run from the Terminal on MacOS. This seems simple enough but the installation script expects needs to run as root (or sudo) and find files from the root directory that it's running from and then looks for the user to provide a password as terminal input before it completes. I don't mind providing the password in a readable format as we will only be using it internally and the password will be changed soon after we're finished with this project.
I have the following so far and it's not working because it doesn't seem to accept my input from the response file. I'm using the sleep to wait the few moments that it takes to execute that first step.
do shell script "cd ~/Desktop/; ./setup; /bin/sleep 5; ~/Desktop/MyApp/Tools/RunThis_WithVarialbles -s blah.com -someOtherVaiable -u uName#blah.com < ~/Desktop/sccm/Tools/response.txt" password "passwdIDCisVisible`enter code here`" with administrator privileges
The error I get from Script Editor is:
error "/bin/sh: ./setup: No such file or directory
ERROR 2 when mkdir in CreateDirectory - No such file or directoryERROR 2 when mkdir in CreateDirectory - No such file or directory
Please enter your password.
(null)(null)(null)(null)(null)" number 8
I'll be the first to admit that I'm a total Noob! Thanks for your patience!
Ok, so I can see a couple of wrongs in your command already. And it still seems pretty unclear what you are trying to achieve. Yet, instead of asking a lot of questions and causing confusion, let's just stick to the first step.
The first part of your error message reads: error "/bin/sh: ./setup: No such file or directory. So this could indicate that:
~/Desktop/setup does not exist. (Check if it does).
~/Desktop/setup is not properly specified and you need to add a file extensions (e.g. like ~/Desktop/setup.sh)
You do not have the proper rights to execute the file. So you should execute something like chmod u+x to give execution rights to your current user. (And sudo chmod u+x for root).
See if you can get passed that first. Learning to code usually means taking baby steps at first.
Good luck.

assistance with postinstall script on Mac

New at this. I need to use a postinstall script to move a file and a folder to the user's Application Support folder on a Mac. For the file I only want to move it if the file doesn't already exist. I do not want to overwrite it if if does exist. Here is my script. It runs but nothing gets copied. I'm using the Packages app, btw, and this script is loaded into the postinstall script tab.
#!/bin/sh
if ! "/Library/Application Support/MyApp/MyApp user dict"; then
mv "$1/Contents/Resources/MyApp user dict" "/Library/Application Support/MyApp/.";
fi
mv "$1/Contents/Resources/Spellcheck Dictionary" "/Library/Application Support/MyApp/.";
exit 0
User-specific tasks generally do not belong in installer scripts -- remember that there may be multiple users on a machine, and that some of them may not be accessible when your installer is running. (For example, users may have encrypted home directories, or may not exist until after your installer is run.) If your application needs to copy files to the user's home directory, it should probably do this when it is first launched.
Nevertheless, I see several specific issues with this script:
Your script refers to $1 in several places. Are you sure that your script has an argument passed to it on the command line?
The correct syntax to test if a file does not exist is:
if [ ! -f "/path/to/file" ] ; then …
Your script is missing the square brackets and -f condition. (For details, see man test.)
Assuming that $1 is supposed to be the path to the current user's home directory, you have the arguments to mv backwards. The destination comes last, not first. (The syntax is essentially mv from to.)

Escalate to glob a directory?

On OS X, I'm writing a bash script to be run as a user, not root. Every so often I need to escalate to root to run certain commands.
In one section I'm trying to iterate over the contents of a directory owned by root with the permissions drwx------, which means I can't glob the contents of the directory as a normal user.
This doesn't work:
sudo for files in "/System/Library/User Template"/*
do
some command "$files"
done
What I would like to do is this:
for files in "/System/Library/User Template"/*
do
sudo some command "$files"
done
This is a new system bootstrap script, so I'd like to keep everything in one script and I definitely cannot run the whole thing as root. I'm wondering:
If there's a proper way to escalate to glob a directory in a for loop.
If I should change the permissions as root, run the code, change the permissions back.
I think you can only consider calling another script that's meant to run as root instead and use sudo with it.
Although maybe you can run bash reading commands from input:
sudo bash -s <<'EOD'
for files in "/System/Library/User Template"/*; do
some command "$files"
done
EOD

Executing a command from the current directory without dot slash like "./command"

I feel like I'm missing something very basic so apologies if this question is obtuse. I've been struggling with this problem for as long as I've been using the bash shell.
Say I have a structure like this:
├──bin
├──command (executable)
This will execute:
$ bin/command
then I symlink bin/command to the project root
$ ln -s bin/command c
like so
├──c (symlink to bin/command)
├──bin
├──command (executable)
I can't do the following (errors with -bash: c: command not found)
$ c
I must do?
$ ./c
What's going on here? — is it possible to execute a command from the current directory without preceding it with ./ and also without using a system wide alias? It would be very convenient for distributed executables and utility scripts to give them one letter folder specific shortcuts on a per project basis.
It's not a matter of bash not allowing execution from the current directory, but rather, you haven't added the current directory to your list of directories to execute from.
export PATH=".:$PATH"
$ c
$
This can be a security risk, however, because if the directory contains files which you don't trust or know where they came from, a file existing in the currently directory could be confused with a system command.
For example, say the current directory is called "foo" and your colleague asks you to go into "foo" and set the permissions of "bar" to 755. As root, you run "chmod foo 755"
You assume chmod really is chmod, but if there is a file named chmod in the current directory and your colleague put it there, chmod is really a program he wrote and you are running it as root. Perhaps "chmod" resets the root password on the box or something else dangerous.
Therefore, the standard is to limit command executions which don't specify a directory to a set of explicitly trusted directories.
Beware that the accepted answer introduces a serious vulnerability!
You might add the current directory to your PATH but not at the beginning of it. That would be a very risky setting.
There are still possible vulnerabilities when the current directory is at the end but far less so this is what I would suggest:
PATH="$PATH":.
Here, the current directory is only searched after every directory already present in the PATH is explored so the risk to have an existing command overloaded by an hostile one is no more present. There is still a risk for an uninstalled command or a typo to be exploited, but it is much lower. Just make sure the dot is always at the end of the PATH when you add new directories in it.
You could add . to your PATH. (See kamituel's answer for details)
Also there is ~/.local/bin for user specific binaries on many distros.
What you can do is add the current dir (.) to the $PATH:
export PATH=.:$PATH
But this can pose a security issue, so be aware of that. See this ServerFault answer on why it's not so good idea, especially for the root account.

Resources