Executing root-required script from non-root user - python

I'm using the Apache CGI mod to allow execution of python scripts via HTTP(S) request. The problem is that the script I want to be executed, backup.py, at one point executes a subprocess call where a mysqldump command is being piped into sudo -i. The problem is that the CGI "user", www-data, doesn't have root access, and I certainly don't want to give it that in general, just for this specific task. How can I allow www-data to perform only a mysqldump command only under sudo -i?

One way of elevating the permissions for a specific script, is to use the sudoers file.
Create a file containing the script you wan't to execute with root permissions, lets say at /path/to/script.sh.
Then, edit the sudoers file with sudo visudo, and add the following line:
www-data ALL = (root) NOPASSWD: /path/to/script.sh
where the the usernames and the path are set as appropriate.

Related

Bash script that can write and execute files only from certain directory

I need a bash (or python) script which will edit and execute files only in a certain directory and its subdirectories but has no permissions to do so in other directories. Any ideas how to set such permissions for a script?
the Apache webserver does a similar thing by creating its own user on linux, i.e. the user apache can access /var/www without being root :
https://support.rackspace.com/how-to/how-to-add-linux-user-with-document-root-permissions/
so you can create a new user and give this user only permissions for the particular directory
then any other user who needs to use the script can run it as the user you created :
https://www.cyberciti.biz/open-source/command-line-hacks/linux-run-command-as-different-user/
how to run script as another user without password

/dev/mem access denied on raspberry pi

I am working with my Raspberry Pi and I am writing a cgi python script that creates a webpage to control my gpio out pins. My script crashes when I try to import RPi.GPIO as GPIO. This is the error that I am getting:
File "./coffee.py", line 7, in <module>
import RPi.GPIO as GPIO
RuntimeError: No access to /dev/mem. Try running as root!
My code works perfectly when I use sudo to run my script, but when I am running from a URL from my apache2 server it says that I do not have access to /dev/mem. I have already tried editing visudo and that did not work. This is what my visudo file looks like:
#includedir /etc/sudoers.d
pi ALL=(ALL) NOPASSWD: ALL
www-data ALL=(root) NOPASSWD: /usr/bin/python3 /usr/lib/cgi-bin/coffee.py *
apache2 ALL = (root) NOPASSWD: /usr/lib/cgi-bin/coffee.py
There any way that I can run my script as root from a URL call? Can anyone tell me what I am doing wrong?
I found that adding www-data to the gpio user group worked fine:
sudo usermod -aG gpio www-data
You can also add www-data to the memory user group:
sudo usermod -aG kmem www-data
As mentioned, it is a bad idea, but for me it was necessary.
Your problem is that the script is not executed as root. It is executed as the user that apache runs as.
Your apache process runs as a specific user, probably www-data. You could change the user that apache runs as. You should be able to find this in /etc/apache2/envvars:
# Since there is no sane way to get the parsed apache2 config in scripts, some
# settings are defined via environment variables and then used in apache2ctl,
# /etc/init.d/apache2, /etc/logrotate.d/apache2, etc.
export APACHE_RUN_USER=www-data
export APACHE_RUN_GROUP=www-data
If you change that to root you should have access. Normally this would be a terrible security hole, but you are doing direct memory access already. Be very careful!
If you are uncomfortable with this then you need to update your command so it is executed as root (this is a good way, but it requires you understand what you are doing!). You can do this by altering the way you call it, or by wrapping the call in a script which itself changes the user, or by using setuid (this is very similar to the suEXEC approach mentioned earlier). Wrapping it in a script seems the best way to me, as that should allow your entry in sudoers to correctly apply the privilieges for only that command, and it doesn't require you to understand the full implications of setuid approaches.

Giving django app root access?

I am trying to build an api using django which should alter iptables using POST parameters. I am using django 1.4, djangorestframework, python-iptables. The problem I am facing is that python-iptables need root access to change iptables rules. I can change the iptables rules by doing $ sudo python and from the python shell I can change those rules. Also I can change those rules by using iptdump module which takes in iptables parameters and create those rules which I can later save in a file (iptables.rules.txt) and use fabric's local('sudo iptables-restore < iptables.rules.txt'). But this will always prompt the user for a root password. Is there a way I can give django app root privileges so that I can bypass sudo password prompt.
If you really need a part of the application to run as root, you could rewrite it as a daemon, and communicate with it from the main Django application as suggested in this answer. I would only recommend it if the alternative below does not suit your requirements.
The alternative sudo iptables-restore < iptables.rules.txt is much simpler, just tell sudo not to ask for the password for just this command by adding this to your /etc/sudoers file:
djangouser ALL=(ALL) NOPASSWD: /sbin/iptables-restore
Where djangouser is the user the Django process is running as.
EDIT: You can avoid writing an intermediate file by sending the new iptables directly to the iptables-restore process:
import iptdump
import subprocess
ipt = iptdump.Iptables()
proc = subprocess.Popen(['sudo', '/sbin/iptables-restore'],
stdin=subprocess.PIPE)
proc.communicate(ipt.dump())

Most pythonic way of running a single command with sudo rights

I have a python script which is performing some nagios configuration. The script is running as a user which has full sudo rights (the user can run any command with sudo, without password prompt). The final step in the configuration is this:
open(NAGIOS_COMMAND_FILE, 'a').write(cmdline)
The NAGIOS_COMMAND_FILE is only writable by root, so this command should be run by root. I can think of two ways of achieving this (both unsatisfactory):
Run the whole script as root. I do not like doing this, since any error in my script will be executed with full root rights.
Put the open(NAGIOS_COMMAND_FILE, 'a').write(cmdline) command in a separate script, and use the subprocess library to call that script, with sudo. I do not like creating an extra script just to run a single command.
I suppose there is no way of changing the running user just for a single command, in my current script, or am I wrong?
Why don't you give write permission on NAGIOS_COMMAND_FILE to your user who have all sudo rights?
Never, ever run a web server as root or as a user with full sudo privileges. This isn't a pythonic thing, it is a "keep my server from being pwned" thing.
Look at os.seteuid, the "principle of least privilege", and man sudoers and run your server as regular "httpd-server" where "httpd-server" has sudoer permission to write to NAGIOS_COMMAND_FILE. And then be sure that what you write to the command file is as clean as you can make it.
It is actually possible to change user for a single command.
Fabric provides a way to log in as any user to a server. It relies on ssh connections I believe. So you could connect to localhost with a different user in your python script and execute the desired command.
http://docs.fabfile.org/en/1.4.3/api/core/decorators.html
Anyway, as others have already precised, it is best to allow the user running the script permission to execute this one command and avoid relying on root for execution.
I would agree with the post above, either give your user write perms to the NAGIOS_COMMAND_FILE or add that use to a group that has those permissions, like nagcmd.

Replace bash shell with python program's cmdline interface

I have a program which uses python's cmd module for command line interfaces.
Now I want it to run on my Linux server whenever any normal user logs in to it,
in a way that user never gets the default Linux prompt (i.e he should not be able to kill the program or send it to background or any such stuff).
For security issues the program should never allow user to gain access of normal prompt. The user should always use program's cmdline to fire all commands. (The program has various filters built in it).
Tried putting the program execution command in /etc/password (replacing default bash shell with the program execution cmd) for the user & also tried to put it in users .bashrc file, but of no use; user can still gain access default prompt.
Any pointers for this can very helpful.
This probably belongs on superuser, but you should add it into /etc/shells file, and set a user's login shell to that one.
For example: sudo useradd -d /path/to/newuserhomedir -s /usr/sbin/nologin newusername would create a guy called newusername whose login shell would be the program /usr/sbin/nologin.

Categories