Users will be remotely accessing ***nix based machines via SSH and I need to determine the fastest way to check if the username that they are currently using has NOPASSWD access in the /etc/sudoers file.
Possible options:
grep for the username in /etc/sudoers, parse command prompt output to determine if it has NOPASSWD, if not, remove the line then append the new permissions
Just append a permission string to the file regardless (bad idea).
Attempt to sudo into a protected file and see if it prompts me for a password.
I'm hoping for something easier, but my google-fu hasn't come up with any answers.
If sudo -v succeeds, the user has been authorized to use sudo; if it fails, then the user has not been authorized to use sudo.
# su user -c 'setsid sudo -v </dev/null'; echo $?
[sudo] password for user:
1
# su root -c 'setsid sudo -v </dev/null'; echo $?
0
Without setsid, sudo will try to ask for the password interactively even if stdin/stdout/stderr have all been redirected. If you don't have a controlling terminal, this isn't needed, but you will probably need something other than su to change user permissions, like fork+setreuid.
If you indeed need "the fastest way", I guess you're building a webserver that would handle many concurrent requests.
This raises another problem - the concurrency issue. Generally, many process reading and writing to the same important file is a recipe for a catastrophe.
Build a small independent process to handle the task. It should have a minimal interface that will receive requests from the clients, and updates for the the /etc/sudoer file. Something like has_NOPASSWD_access() and set_NOPASSWD_access(). It should read the file only when it needs to be written, so you'll greatly reduce the I/O time required to serve a request.
Pros -
Fast : No I/O needed for just reading the file, because it is stored in the buffer since the initial read
Thread safe: Only one server writes and reads the sudoer file
Single choice principle - only this process handles the sudoer file
Elegant (I hope) :-)
Cons -
- List them in the comments, and I'll add.
Related
I'm driven here by my weak Google-fu. I found this question to be extremely difficult to search.
I wrote a bash script that checks for package updates to my Debian Wheezy load. This is not a cron job. I want the user to be able to run the script manually whenever she suspects (via an email, for example) that package updates may be available and then be able to actually download and install same.
If the script is run and updates are found, I want the script to then ask the user for the root password, then open Aptitude, so the user can see what package updates are available.
I have the script running on several hosts, but on one of the hosts, I want to have the script alert me if the host does not currently have a network connection before checking for updates. For this, I use the "route" command, which requires root privileges to run. I don't, however, wish to put "route" into said host's sudoers file. So, on the particular host that I need network connectivity confirmation, I have referenced the script itself in that host's sudoers file:
booboo ALL = NOPASSWD: /home/booboo/Scripts/chk4updates.sh
Here is a look at an outline of what the script does:
host=$(hostname)
if [ $host = travel ] ; then
...check for a connection, using the "route" command...
fi
...check for package updates...
if [ ...updates are found... ] ; then
gksu aptitude
fi
For all of the non-problem hosts, if updates are found, I get the gksu window that asks for the root password so that "aptitude" can be opened. But, for the host named "travel", the script opens aptitude without asking for a root password. I don't want this to happen.
I've tried a few things, but nothing has worked for me. Do I need to modify the problem host's sudoers file, or can I add a command to the script that will give me my desired behavior? Something like:
...
...check for package updates...
if [ ...updates are found... ] ; then
if [ $host = travel ] ; then
...some command so that a root password is required to open aptitude...
else
gksu aptitude
fi
fi
TIA!
When you are root, you can switch to a regular user at any point with su.
if [ -z "$SUDO_USER" ]; then
gksudo aptitude
else
su -c 'gksudo aptitude' "$SUDO_USER"
fi
Your setup seems extremely brittle and convoluted, though. There really is no such thing as a safe sudo shell script. The requirement to not add route to the sudoers file seems suspicious. Is there really no way you can refactor this so that the special case is handled on travel somehow? Maybe write a wrapper for route which you can put in sudoers and which checks that it's called from the right script, for example.
However, I would actually go with ping instead of route -- after all, route only tells you whether the route is set up locally, but won't reveal if there is a connectivity problem to the outside world. Then the rest of your question is moot.
(Or maybe even use something like cron-apt and remove the whole problem completely.)
I have a Perl CGI that is supposed to allow a user to select some files from a filesystem, and then send them via Rsync to a remote server. All of the HTML is generated by the Perl script, and I am using query strings and temp files to give the illusion of a stateful transaction. The Rsync part is a separate shell script that is called with the filename as an argument (the script also sends emails and a bunch of other stuff which is why I haven't just moved it into the Perl script). I wanted to use sudo without a password, and I setup sudoers to allow the apache user to run the script without a password and disabled requiretty, but I still get errors in the log about no tty. I tried then using su -c scriptname, but that is failing as well.
TD;DR Is it awful practice to use a Perl CGI script to call a Bash script via sudo, and how are you handling privilege escalation for Perl CGI scripts? Perl 5.10 on Linux 2.6 Kernel.
Relevant Code: (LFILE is a file containing the indexes for the array of all files in the filesystem)
elsif ( $ENV{QUERY_STRING} =~ 'yes' ) {
my #CMDLINE = qw(/bin/su -c /bin/scriptname.sh);
print $q->start_html;
open('TFILE', '<', "/tmp/LFILE");
print'<ul>';
foreach(<TFILE>) {
$FILES[$_] =~ s/\/.*\///g;
print "Running command #CMDLINE $FILES[$_]";
print $q->h1("Sending File: $FILES[$_]") ; `#CMDLINE $FILES[$_]` or print $q->h1("Problem: $?);
However you end up doing this, you have to be careful. You want to minimise the chance of a privilege escalation attack. Bearing that in mind….
sudo is not the only way that a user (or process) can execute code with increased privileges. For this sort of application, I would make use of a program with the setuid bit set.
Write a program which can be run by an appropriately-privileged user (root, in this case, although see the warning below) to carry out the actions which require that privilege. (This may be the script you already have, and refer to in the question.) Make this program as simple as possible, and spend some time making sure it is well-written and appropriately secure.
Set the "setuid bit" on the program by doing something like:
chmod a+x,u+s transfer_file
This means that anyone can execute the program, but that it runs with the privileges of the owner of the program, not just the user of the program.
Call the (privileged) transfer program from the existing (non-privileged) CGI script.
Now, in order to keep required privileges as low as possible, I would strongly avoid carrying out the transfer as root. Instead, create a separate user who has the necessary privileges to do the file transfer, but no more, and make this user the owner of the setuid program. This way, even if the program is open to being exploited, the exploiter can use this user's privileges, not root's.
There are some important "gotchas" in setting up something like this. If you have trouble, ask again on this site.
I'm writing a bash script that requires root access and so what I need to do is write something like
$my_psswd >> sudo some_command parameter1 parameter2
to automate the process. I'm not concerned if this opens up security holes. This is more or less of an example that I can think of. But the problem is that when I initiate sudo anything, it asks for user input which I'm not sure how automate or provide as a variable.
I've tried things like
$my_psswd >1 sudo something
echo $my_psswd | sudo something
but none of this is what I want. Also this has to be a bash script, I can't use a program like expect. Thanks.
You need -S switch for sudo command:
-S The -S (stdin) option causes sudo to read the password from the standard input instead of the terminal device. The password must be followed by a newline character
I recommend against doing this at all. You will be storing your password in plain text which means other people may have access to it. Or it will be visible in process listings, again available to other users.
There are a couple of alternatives to prevent this:
Run the entire script using sudo. Do not use sudo in the script itself but run the entire things with elevated privileges. The downside is off course that your might be executing things with elevated privileges that do not require it but with no more background that's impossible to say.
Better would be to configure your account to execute those specific commands through sudo without providing a password. That way you can execute only the commands that need it with elevated prvileges without the problem of providing a password.
A workaround could be to run sudo -l before calling the script. That way sudo will have an active session and won't prompt for a password. This is only a workaround and would fail if one of the commands takes longer to execute than the configured grace time for sudo. But in small scripts this might be an easy fix.
Try echo $PW | sudo -S cmd
It may work for you.
you are not suppose to use sudo this way, use visudo to specify what commands are allowed to what users, then you don't need to worry about passwords.
I'm sure this question has been answered before, but I can't find an answer that I like. I would like to write a shell script that executes a very specific script as another user (I want anyone to be able to start postgres as the postgres user). The script will have 710 perms so it will be executable by a certain group but not readable or writable by that group.
Now, I'm pretty sure there's no way to use 'su' without an interactive password prompt. There are lots of good reasons for that and I don't need to be convinced of the merit of those reasons (I'm told that someone savvier than me could grab the password off the processes list which is bad).
Question is, more generally how would I accomplish what I want to do without abusing unix security paradigms? Is there a way to allow user to execute a very specific process as another user?
This sort of situation is exactly what sudo was designed for.
You can create an executable (not a shell script) that launches the script that should run as the postgres user. Change the owner of the executable to the postgres user, and set the setuid bit.
See Best practice to run Linux service as a different user to address Celada's concern.
Well, you could use a simple script to access programmatically to an user using sudo and then execute all code you want.
Here is a simple script:
if [ "$#" -ne 2 ]; then
echo "Usage: "
echo " suprompt <user> <password>"
else
echo $2 | sudo -sS su $1
sudo su $1
fi
This script uses two arguments. The first one is the user you want to be, and the second arg is the password.
It works automatically.
You can change the final statement and do: sudo su $1 -c <command>
I hope this will work for you.
I'm trying to run a bash script when my EC2 instances start up. All I want to do is start up GlassFish when the server starts. The command I'm trying to run is:
sudo /glassfish3/bin/asadmin start-domain
Which works when I enter it manually.
I have tried adding this command in a couple places with no luck:
at the end of /etc/rc.local
at the end of /etc/rc.d/rc.local
created my own script in /etc/init.d/
I have given every script 777 permissions.
Anyone have any ideas on what I'm doing wrong?
Unless oddly configured, sudo wants authentication when run. It is normally meant to be run interactively.
Assuming that the script /glassfish3/bin/asadmin is owned by root, you can set its file permissions to 6755. This does what you probably meant sudo to do. Of course, it can also be dangerous and may be a security risk.
(#jcomeau_ictx is right, incidentally. You should check logs as he suggests.)
Update for the benefit of archival: The above answer fortunately seems to have solved the OP's immediate problem, so we'll leave it at that. However, since this answer will remain archived and others may look it up later, I should add more to it.
One can change the file permissions of any executable to 6755, but such is not always a good practice. The effect of such permissions is (a) to let anyone run the executable with (b) the full privileges of the executable's owner. Sometimes, this is exactly what you want, but see: in the OP's case, /glassfish3/bin/asadmin with such permissions can now be called by anybody, with any arguments, with full root privileges. If that is not what you want, then you must take some additional care.
Several ways of taking additional care are possible. One is as follows.
Leave the executable with file permissions 755.
Write and compile a small wrapper, a program which uses execv() of unistd.h to launch the executable.
If practicable, do not let the wrapper take any arguments; otherwise, let its arguments be as restricted and inflexible as they can be. Let the wrapper strictly control the arguments passed to the executable.
Let the wrapper be owned by root, but use chown to assign it a suitable group whose membership includes no users. You may prefer to start a new group for this purpose but, if you scan the /etc/group file on your system, you are not unlikely to find an already existing group that suits. For reference, you can list commands already belonging to special-purpose groups on your system by ls -l /bin /usr/bin | grep -vE '^([^[:space:]]+[[:space:]]+){2}(root[[:space:]]+){2}' or the like.
Give the wrapper file permissions 6754, thus making it nonexecutable except to the group in question.
Admit the calling script to the group, and give the calling script file permissions 2755.
If the calling script already belongs to a group, you can probably just use the same group throughout.
Several variations of the technique are possible, and it is unlikely that you will use exactly the one listed above, but if you read the manpage and/or info entry on the chown command and learn the details of file permissions, and if you experiment a little, you should be able to craft a solution that works for you without posing a security risk.
Most probably it's JAVA_HOME issue, try using sudo -i, here is my working init script:
#!/bin/bash
# description: Glassfish Start Stop Restart
# processname: glassfish
# chkconfig: - 95 80
DOMAIN=domain555
GF_HOME=/opt/glassfish3
DOMAIN_DIR=/home/glassfish/domains
RUN_AS=glassfish
CMD_START="$GF_HOME/bin/asadmin start-domain --domaindir $DOMAIN_DIR"
CMD_STOP="$GF_HOME/bin/asadmin stop-domain --domaindir $DOMAIN_DIR"
function start() {
sudo -u $RUN_AS -i $CMD_START $DOMAIN
}
function stop() {
sudo -u $RUN_AS -i $CMD_STOP $DOMAIN
}
case $1 in
start)
start;
;;
stop)
stop;
;;
restart)
stop;
start;
;;
esac
exit 0
JAVA_HOME and PATH should be set in user's .bashrc or .bash_profile