I am trying to write a simple php web interface to control some services running on my home server/raspberry pi. The web interface is only reachable from the local network, but I am still trying to secure it as good as possible. Who knows where I can use it in some time. Of course its protected by a login, but with this thread I'd like to hear your thoughts concerning this case:
In order to start/restart/stop a service like OpenVPN you have to be root or another user with sudo access to /etc/init.d/openvpn . This causes me a lot of worry ...
I'd never grand the user www-data sudo access to anything. So how do I restart the service? Here I mention two methods I came up with searching the Internet, but I think they are still very vulnerable. Do you have any ideas to strengthen the security of my thoughts or other concepts leading to my goal, which do not cause me sleepless nights in case of potential vulnerable holes? Maybe every approach has its shady side, but I'm searching for a working solution with preferably good security from attacks, where the invader already gained some access to the user www-data.
First approach:
Create a shell script, running as (root as) cronjob every minute, checking if the content of a certain text file like control.txt changes from "openvpn=" to "openvpn=restart" and then react specifically to the change. Here the text file already exists, only the content changes. (negative: time to wait till the service really restarts; potentially dangerous code implemented in control.txt will be able to contaminate the entire system)
shell script cronjob:
Code:
#!/bin/bash
control_file="/some/dir/www-data/has/access/control.txt"
function openvpn {
if [ "$1" == "restart" ]; then
service openvpn restart
elif [ "$1" == "start" ]; then
service openvpn start
elif [ "$1" == "stop" ]; then
service openvpn stop
fi
#TODO remove $1 from text file
}
while true; do
while IFS= read -r line; do
#search current line for specific term
if [[ $line == *"openvpn="* ]]; then
#call function (parameter: everything following the = symbol)
openvpn "${line:8}"
sed --in-place -e "s/$line/openvpn/g" $control_file
fi
done <"$control_file"
done
In the worst case we have to assume a potential third person has full access to www-data (however she/he did it). She/He could edit the control.txt, so I can't trust anything the cron read from it. How can I safely evaluate the content without running potentially harmful code (which would run as root)? What security enforcement would you add?
Second approach:
Create another user which has sudo privileges only to /etc/init.d/openvpn and run a simple C program (or maybe a shell script like above which sleeps for 60 seconds every time it checkt). This program (or script) would wait for the file control.txt to be created by www-data with the FileSystemWatcher and then when the file exists and is finally readable we can continue our checks and then execute "/etc/init.d/openvpn start/stop/restart" (if it's a script, the text file would still be existing and we would wait for changes like above).
I think this method (C program waiting for a file to be created) is more handsome in case of waiting for php to make a call.
I am open for any suggestions.
thanks