I'm creating a web app (php) that handles the creation of Drupal sites on a live server.
The system is able to create new sites and give some maintenance on existing ones. And, as this is a web-hosting environment, each folder may belong to a different user.
In order to do that properly I need to let the apache user run some commands as some other user.
What I do to create new files (and interact with git/drush/etc) is something similar to:
$some_command = `echo "PASSWD" | sudo -u USER -S do_something 2>&1; echo $?;`;
I already have a set of commands on the sudoers file that the apache user can run as the git user.
My issue now is that I need to let apache run as ANY user that may have a hosting account on the server.
My idea was to create a apache ALL=(ALL) ALL entry on the sudoers file. I would still leave all those commands asking for the users password.
With that in mind, is this wise to go with this approach? And if not, maybe I could apply the "allow all" policy only to the users that have a hosting account. If so, how do I narrow the policy to only one group?
Thanks
Edit: I though on using suPHP for this, as it allows apache to run each PHP script as its owner. But I would still need to run some other commands as another user (as creating files in someone else's home folder/public_html), so it seems that it isn't an option.
Based on our discussion in comments, I would advise installing something like suPHP so that each of your user's scripts are owned by their actual user and not Apache.
I figure you are having this issue is (maybe) because you want to be able to perform the administrative functions of other user's sites from a web interface. If you have a generic user like apache that other users can run scripts as, allowing that user automatic sudo permission is a bad idea since it could easily be exploited to gain unauthorized access.
To get around that, make sure you run your administrative functions as a special admin user that has permission to modify other people's files. Also make sure to chown any files you create as the appropriate user so they can read/write them. And as long as no other users can access that admin account or run PHP scripts as them, you should be much safer.
If you're running the admin functions from the console then it should be even easier, otherwise just set up a suPHP user to run your master functions from the web and use good credentials for the account.
Doing something like that will be more secure and should allow you to do everything you need without opening things up more than necessary.
Related
I am currently attempting to write a simple web page to store emails in a database. I am on a server which is not mine (but does run Apache), so I do not have root access, so I have opted to use SQLite3. The goal is to use PHP to INSERT into the database, however, I continue to encounter the issue with the database being owned by me and the PHP attempting to access using the user "apache" which leads to a "readonly" error. Since I am not root, I cannot chown the database file and even when I chmod 777, it has no effect. The conclusion I came to was to have the PHP script create the database itself (under the user apache) but now I do not have write access to the file. Is it okay for me to just allow apache to own the database or is there some better way to do this?
SQLite is a library, i.e., it's just a bunch of code that runs inside the web server process. This means that accesses to the database file behave just like any other file access from Apache.
The web server process needs to be able to access the file itself, and to create the journal rollback file in the same directory.
chmod 777 is a bad because every user on that machine can do anything to the database. It would be a better idea to have the database file and the directory belong to a group that has you and apache as members.
If the server's administrator will not create such a group, then you could have apache as the owner, and add a backdoor (sufficiently protected) to your web app to allow overwriting the database with a new file.
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"
Solved
I figured out who the current user was using PHP and managed to set the new directories' owner to be the user the PHP scripts are executed from. However, this was still causing issues as some other commands (used to determine who the current user was) weren't working. This highlighted that the problem was that my PHP distribution was configured to be in safe mode.
I disabled safe mode and the commands provided by Ed Manet allowed me to add/edit/remove the files as desired, without the shortcut of just having everything be 777 permissions.
Thanks for the help!
Original Post
I have a web application that stores some data on the server. This involves creating and removing both directories and files (as well modifying existing files) in PHP. The main problem I'm having is do with the permissions required to perform such actions.
If I set existing files' permissions to 777, then the PHP script can edit them just fine (although I know this isn't an optimal solution as it's insecure). The script can also create and remove directories just fine (when they have 777 permissions at least), but no matter what I do I cannot get the script to create new files.
I've done some searching around and it appears that I need to elevate the PHP "user" to a user that has the required priviliges. However, when it comes to server configuration and permissions I'm essentially a beginner. How would I change to a different user to perform the required actions? Is it possible to do this mid-script and use PHP's fopen() and chmod() functions as normal? Or would I have to spawn an entirely new process using a shell command, somehow getting that external program executing with the correct privileges?
To summarise, I need a new of creating, modifying and deleting files/directories in a we b server using PHP, by assigning adequate permissions to the files and privileges to the PHP user. I am unsure on how to do this.
Thank you.
What I would do is change ownership of the folder that the PHP has to create files in to the account that runs the PHP process. Then you don't need to open up permissions so much.
So if this is a Linux system and the webserver is run by a user called "apache":
chown -R apache /path/to/the/files
Then change permissions to owner read/write
chmod -R 644 /path/to/the/files
How can you allow a PHP script to write to a file with high-security restrictions, such as only allowing a single user to write to it?
The difficulty seems to be that a PHP script is running as a low-permissions user (maybe apache, or www, or nobody?), and even if I chown apache the_writable_file, the directory it's in might not be writable for the low-level user. In general, what's the usual way that PHP can work with local files in a secure way?
Unfortunately, in shared hosts that use mod_php, there is no way to restrict access to secure files to your web app and login user.
The solution is to run your web app as your login user. When you do that, UNIX file permissions can correctly lock everyone else out. There are several ways to implement that, including SuExec, suPHP, or running PHP with FastCGI with mod_fcgid or mod_proxy_fcgid. FastCGI is my favorite way.
Another solution is to use a dedicated host or virtual private server.
Sure, chgrp apache the_writable_file and chmod g+w the_writable_file. After that, only your secure user and the apache user will be able to write to the file. Since the apache user is typically forbidden from logging in, you only have to worry about web users writing to your secure file using through the http daemon.
All the containing folders need to have execute permissions.
For example, if the file's in /foo/bar/the_writable_file, the directories "foo" and "bar" both need to have executable permission to access the_writable_file, even if they don't have read/write permission.