I am a newbie here, I am having a bash script which can be executed through terminal with sudo permission only. I want to run it from PHP with proper security. I dont know where to start to accomplish this considering security in mind. Should I create a additional user or what Will be the better way to achieve this. I got a reference with Running command-line application from PHP as specific user, but I am using Nginx and the mentioned solution does not work for me.
NGINX is a web server and not the interpreter. It is not very relevant.
In the standard NGINX + PHP-FPM setup, you should have a separate system user for your website anyway. So you don't need to create an extra user just for that command.
Simply ensure that this "website user" is able to sudo run your script, without being prompted for their password. This is achieved by visudo.
example ALL=/path/to/your/script
Where example is the PHP-FPM pool user, aka, the "website user" and the owner of the website's files.
Related
My company have a cloud dedicated server, hosted in google cloud, running centos 7 with apache2, php5.5 and mariadb running.
The webserver is running a private application for business clients and companys. Every client has his own database and subdomain, so they, and their own clients can access his applicacion going to http://theirname.example.net/
I've created an interactive command line script for client creation. It creates user and secure password, ftp custom folder, create mysqldatabase and populate it with a sql file, create subdomains and other thing. Also i've made another version of this script with no user interaction, receiving parameters as the client name via command line arguments ( /path-to/script.sh usertocreate mysqluser mysql pass).
So, here is the deal, i want to create a web interface, password protected, just available for my company IP address, this interface should be able to run these SH scripts (not the interactive ones) with sudo permissions.
I was thinking on create a subserver in other port (like http://example.org:2501) using another instance of apache (or other webserver) which runs with a specified user with sudo permissions enables only in the neccesary folders.
Before doing anything, i've created a PHP script which runs commands to console, and tried to run SUDO commands with that. Allowing apache user to sudoers list (just to make it work during develop). I could run these scripts from my web app without SUDO permissions, but they where not working at 100% (since some commands require SUDO). When i try with sudo i receive a code 127 error responde (permission problem).
I stopped there and decided to investigate the best way to do this.
I have full control of the server machine. Apache2 and everything normal is running well. (mariadb, proftpd with passive mode active -100 ports added- )
SELINUX is DISABLED. Firewalld Running
SSH is available for use
I can install another webserver in another port to accomplish this. If a lot of HTTPD configurations should be changed to accomplish this, i will preffer to install another webserver
I can also install any 3rd party software.
I'm a PHP Developer with low experience in other programming languages, if it's necesary to invoke any other programming language to do this (maybe like Python) i would love some docummentation links
Access to this web application would be limited only to my company's static ip address and will be protected
Any thoughts/ideas ? Thanks in advance
PS: If someone want to edit my text and add some colours and format, edition will be aprovved
EDIT TLDR: I want to run another httpd in another with a webapi. This webapi should can run console commands as SUDO. Access to this webserver will be limited to my company's IP. I'm not sure if this is the best way to do it and i want opinions. Also, i'm not pretty sure if its possible to run sudo commands from php without any trouble.
So I have a PHP script that needs to change a Linux user password programatically.
The script is running as www-data (which is the username given to apache2). I execute chpasswd with popen, and then fwrite the username:password pair. This causes an error.
Dropping down to a bash shell, I try to see what's going on here. Naturally, I suspect it's some kind of permissions issue. So, I change users to www-data and try to execute chpasswd manually:
# su www-data
$ /usr/sbin/chpasswd
jsmith:mysecretpassword
Changing password for jsmith.
chpasswd: (user jsmith) pam_chauthtok() failed, error:
Authentication token manipulation error
chpasswd: (line 1, user jsmith) password not changed
So this reveals why PHP is unable to execute the command. The error message is not exactly straightforward, but I suppose the gist of it is that a PAM authentication problem occurred (which I assume basically means a Linux permissions problem). So, if I su to root, I'm successfully able to change the password via chpasswd.
So obviously the problem here is that apache2 (user www-data) doesn't have sudo privileges. Is the only solution here to add www-data to the sudo group? Because I'd rather not do that. But I don't see any other option here.
More generally speaking - apart from the specifics of this situation - how is it even theoretically possible for a web program that might need to change user passwords to be able to do so without having sudo privileges? But if the web program has sudo privileges, then isn't that a major security problem?
I would likely setup a queuing system that runs as root and have the php script add to the queue instead of having PHP have access to any privilege escalation. This will also close some security holes although having web interface to changing linux user passwords still sounds like a bad idea.
Look into this and this. The second alternative, even though they have a "security" section at the bottom with suggestions, doesn't seem safe to me, but it's just a feeling.
I'd go for web-chpass.
I'm working on a VPN signup site, which is written in PHP and runs on the same Ubuntu server that the VPN server runs on. It allows users to sign up for VPN services, but currently it just emails the support staff their information, and they manually edit the config files on the server. I'm using PPP to handle authentication, so I have a file containing information like below:
# user server password ip
test l2tpd testpassword *
In order for a new user to be added to the VPN service, their details must be appended to the above table, and the command
sudo /etc/init.d/xl2tpd restart
run in order to apply the new changes. What I am looking to do is automate the process. From what I can tell, there are two options. One is to create a shell script, and then use shell_exec('./adduser test testpassword');. The other is to do it directly in PHP, by opening the file, modifying it and saving it again.
From a security and speed point of view, which approach is better, or is there another one which I haven't thought of?
sudo can be configured to execute just a specific command for a specific user, so modifying your sudoers file can mean you can use sudo in a more secure way to execute specific commands.
You could combine this with a wrapper script so that php was only executing a localised script with limited rights.
So your wrapper script, let's call it 'restart_auth.sh` may contain:
#!/bin/sh
sudo /etc/init.d/xl2tpd restart
You would then shell_exec('restart_auth.sh') from php to run that script.
You would edit your sudoers file to allow the user that the script was run as (your php user) to run /etc/init.d/xl2tpd. so if your php user is www_data edit sudoers (using visudo ) to contain:
user host = (www_data) NOPASSWD: /etc/init.d/xl2tpd
Provided no tainted data - that is unvalidated information that may contain shell escape characters - is passed through to a shell exec command then it is secure.
As someone else suggested it may be better to write the data to a pending list then read from that, rather than passing it on a shell_exec() line. However that can still introduce insecurities, so making sure the values you are writing to the file are untainted is the most important thing.
Also never run that full script as root even as a cron job, but instead use the same approach with sudoers to only permit the running script to execute specific commands as root. For instance you could allow sudo "cat changes.txt >> auth_file"
I would like to know if it is possible to restart the Linux server using PHP script? In related to changing IP Address from Static to DHCP, I need to reboot the system so that it will take effect.
i tried this code:
system("/usr/bin/reboot");
error message is :
reboot: must be useruser
here'e the another:
system('/etc/init.d/network restart');
the error is:
Shutting down loopback interface: [FAILED] Bringing up loopback interface: [FAILED]
Hope you can help me in this.
Thank you!
Regards to all.
You can restart it if the program-users-context of your interpreter, webserver has the rights to execute these commands. A webserver or php interpreter should not be run as root. You may use sudo, sudoers in order to escalate privileges in these both cases.
You will need to use sudo like this:
system("sudo /usr/bin/reboot");
in your /etc/sudoers add the following:
apache ALL=(ALL) NOPASSWD: /usr/bin/reboot
Where apache is the username under which the PHP script runs.
Be aware of the security impication of doing this - anyone with access to PHP scripts on the server to reboot the server.
In related to changing IP Address from Static to DHCP, I need to reboot the system
No you don't. This is not Microsoft Windows. But the command for remapping the network interfaces varies from distribution to distribution - and you don't say which this is. Similarly, access the reboot, shutdown, init and telinit commands varies by distribution.
I am working in local server
So why not just do it via ssh or at the console?
Since you have stated that you're a newbie to Linux, I feel that it's worth pointing out that it's much much less common to need to reboot a Linux box compared to a Windows one.
You shouldn't need to reboot even after updating core software packages. Even if something crashes badly, you can ususally recover without a reboot.
You haven't stated why you'd want to be doing a reboot, but rebooting the whole box really should be an absolute last resort. In fact, rebooting simply to clear an issue is consdered very bad practice for a Linux administrator because it tends to wipe out evidence of what caused the problem, and does nothing to prevent the problem from recurring.
On Linux, most issues that would require a Windows box to be rebooted only require the individual program or service to be restarted.
Finally, a note on security: Doing major system operations such as this via a PHP program is bad security practice because it exposes root level functionality to non-root users. I assume (well, I hope!) that you're planning to lock down access to this PHP page, but even the best secured web page should not be considered secure enough to be running root-level operations.
In short, my advice is that you shouldn't do this. If you must do it, #qbert220's answer should work, but please don't do it.
[EDIT]
With specific regard to changing the IP address from DHCP to static, this should not require a server reboot in Linux. You simply need to restart the networking interface.
Once you've changed the config, something like this should be enough to restart your network interface with the new IP address in place:
sudo /etc/init.d/networking restart
You haven't specified what variety of Linux you're using, but here's a link to a page which details how to do it from the commandline in Ubuntu.
It does require root priviledges though, so you would need to use sudo to achieve it and to add your web user to the sudoers list, which as I said before is really not great from a security point of view.
Script must be set to run as root:
reboot.php
<?php
exec("reboot -d -f -i");
?>
Meke it a root script:
chown root.root reboot.php
chmod 700 reboot.php
But why do this with php? Just make a script in sh like so:
#! /bin/sh
PATH=/sbin:/usr/sbin:/bin:/usr/bin
reboot -d -f -i
I have a local server which needs to make changes to a virtual hosts apache config file and then restart apache so the new config takes effect.
Can PHP do this? I tried passthru and exec but they didn't work. Maybe the problem is that I'm trying to restart PHP's parent process?
Thanks for any help!!
I've used a cron script (written in PHP, not executed from the webserver) to check a server is up and restart the server.
However, I wouldn't do this from a server-created process, because you know you're about to kill the parent process, which has bad implications for the child.
The simplest method would be to have a file /tmp/RESTART_APACHE which PHP can create, and which the cron script checks for. If the cron script sees the file /tmp/RESTART_APACHE then it does a proper restart of Apache.
Using a cron script will introduce a delay (up to 60s if you run it each minute), but apart from that should work as you want.
Depending on how you intend using this, that may do the trick.
(You probably want to use a different directory than /tmp/ to set permissions and prevent anyone on the server being able to create the file.)
EDIT: Please see Aaron H's comment to this post. I agree with what he says: you really do want to be careful that the ability to restart your webserver is not a service generally available to the public.
Restrict access to the system which can trigger the restart; ensure that the file which triggers the restart has restrictive permissions so only the web process can create that file, and generally be smart.
I've done this for the very exactly thing. However it was solely for a development environment, to quickly create virtual host for our developers on demand. Worked very pleasing well so far.
My approach was to create a new user on the system, give this user sudo rights to reload apache and from Apache->PHP I used SSH to localhost with an authorized key without passphrase to that user, issuing the command.
The reason for this was that I didn't wanted to give the apache user (usually www-data) the power in general to reload itself. I named the new user wwwctrl.
The command I used was:
ssh -i /path/to/key-file wwwctrl#localhost sudo /etc/init.d/apache2 reload
I had to execute this command manually one time as wwwctrl user to have the local host key being added to ~wwwctrl/.ssh/known_hosts.
I used proc_open() to watch the execution of the command.
In fact I was generating a batch of virtual hosts for different Apache installations on different systems so on every system I had this wwwctrl user to reload Apache, basically doing this in a "foreach hosts as host do ... wwwctrl#host#".
Wouldn't you want to pass a 'reload' instead of a 'restart?'
To do this you would need to edit the sudo file and then execute the restart command that is used on your system, using sudo of course. If you give details, I could tell you but do you even have access to do that? Is it hosted? Cron would probably be a better choice here though.
at will be able to do that, not sure if you can schedule down to the second but I guess that depends on the implementation
I would create a daemon to monitor the sites-enabled directory and restart Apache when files are added or modified. Then you don't have to wait up to 60 seconds as with a cron job.
This sorta thing violates the standard chain of command since apache invokes php, not the other way around. I second the cron suggestion. Just set a cron job with sufficient privileges to check for changes to the host file, and restart apache if any are found.