Apache user account passwordless access to the server - Ubuntu - php

I have the same issue which is in this question. If I explain it again, I can use rsync to sync my local data with the server without password(I used SSH keys). But when I use exec() function in PHP, it doesn't work.
The person who has asked the above question has given the answer by himself. He says it can be done by allowing the Apache user account passwordless access to the serve. So my question is how do I provide Apache user account passwordless access to the server?
My PHP code is :
echo exec('rsync -aze --progress --size-only /var/tmp/src/File01 serveruser#mycloud.com.lk:/var/tmp/dest/File01');
PS: I logged into my machine using my typical user account (Let say username is 'bob'), and generated ssh keys using ssh-keygen -t rsa . Then bob has passwordless access to server.
But,When I run PHP command, it runs in Apache under mod_php and Usually Apache is running as its own user account, independent from the real-world people who use the server. Therefore my generated keys are not available to PHP inside Apache.
Therefore I tried to login as Apache user (I think it is www-data). But most of the articles says www-data doesn't have a password by default and cannot login as www-data.
Thank you.

The problem was the Apache user cannot access my keys. Therefore I had to generate SSH keys for the Apache user (it's www-data) although it was not so secure. First login as root.
mkdir /var/www/.ssh
chown -R www-data:www-data /var/www/.ssh
Now generate SSH keys as following. It will save your private key and public key in /var/www/.ssh folder:
sudo -u www-data ssh-keygen -t rsa
Now you should get something like this:
root#sampath-Vostro-1520:/var/www/.ssh# sudo -u www-data ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/var/www/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/www/.ssh/id_rsa.
Your public key has been saved in /var/www/.ssh/id_rsa.pub.
The key fingerprint is:
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx www-data#machine-Vostro-1520
The key's randomart image is:
+--[ RSA 2048]----+
| ...o...o..|
| o.. o|
| + .. .+o|
| . .*o+o|
| ++ S ..B..|
| o . E + |
| . . o o |
| . . |
| |
+-----------------+
Now copy your public key to the remote server:
sudo -u www-data ssh-copy-id -i /var/www/.ssh/id_rsa.pub username#myserver.com
Now this should work. :-)
<?php
$c='rsync -azv /source/folder/path/ username#myserver.com:/destination/folder/path';
exec($c,$data);
print_r($data);
?>

Normally your key is loaded via an SSH agent making it automatically available, instead of using this you can manually specify an identity file. If you generate a key to use, as long as it's readable by apache then it can be used.
Rsync doesn't let you specific the identiy file directly but you can pass parameters to the underlying SSH call:
echo exec('rsync -az -e "ssh -i /var/www/key.pri" --progress --size-only /var/tmp/src/File01 serveruser#mycloud.com.lk:/var/tmp/dest/File01');

Related

Php exec git pull script with ssh doesn't work but doing it manually works

I'm trying to make a script where I can Git pull on my ubuntu server after push to Bitbucket repository. I've setup ssh keys to Bitbucket and it works to do git pull command on the repository but it doesn't work when I try it from php exec.
I've tried chmod commands like /.ssh/bitbucket_rsa like 775 and 777 and chown -R www-data:www-data/.ssh without any luck.
Response:
array (
0 => 'Host key verification failed.',
1 => 'fatal: Could not read from remote repository.',
2 => '',
3 => 'Please make sure you have the correct access rights',
4 => 'and the repository exists.',
)
Code:
public function gitPull() {
try {
exec("cd " . env("REPO_PATH") . " && git pull 2>&1", $output);
Log::info($output);
} catch (\Exception $e) {
Log::error($e);
}
http_response_code(200);
}
I guess you are stuck with the fact that the user www-data can not establish the SSH connection to the git server. I think the simplest was is to create a home directory for the www-data user and create a .ssh directory with the proper permissions, a config file and the key file in there. You could always test the setup as root with
# su - www-data
$ cd <to your repository>
$ git pull
Google for "SSH connections without password" to set it up correctly. And also be aware that SSH refuses to use a key file if the permissions are to loose.
Host key verification failed.
means that ssh could not verify the host key, most likely because there's no known_hosts file in www-data's home/.ssh directory that contains the expected host key for your repo's server.
There's at least two ways to fix that:
Use ssh-keyscan as described over on Serverfault.se:
ssh-keyscan -H [hostname] >> /path/to/www-data's_home_directory/.ssh/known_hosts
You only need to do that once (unless the key changes), but you should check that the key is indeed correct after you run ssh-keyscan.
Set the GIT_SSH_COMMAND environment variable before running git. You can use this to have ssh use a different known_hosts file:
export GIT_SSH_COMMAND="ssh -o UserKnownHostsFile=/path/to/known_hosts"
Note that the above assumes shell syntax (e.g. Bash), you may need to adjust for PHP, particularly the export GIT_SSH_COMMAND= part.
I stack with the same problem working with github:
ssh-keyscan -t rsa github.com | tee github-key-temp | ssh-keygen -lf -
cat github-key-temp >> ~/.ssh/known_hosts
cat github-key-temp >> /etc/ssh/ssh_known_hosts
But that is not all, with next command you can check what is goes wrong (run it throught exec or shell_exec (save out put to some log):
ssh -vT git#github.com 2>&1
So, with help of privious command, i understand that in my case: cron run's command via php script, but duaring ssh connection it could not find my keysfile (i have custom name for that file):
cd /etc/ssh/ssh_config.d/
sudo touch <some_name>.conf
sudo echo 'IdentityFile ~/.shh/<custom_key_file_name>' > <some_name>.conf
Or try to add full path to location of your keyfile (~/ = current user home dir).
You can check cron user by runing, this can helps to:
shell_exec('whoami');
P.S. I have no idea if this solution is enough secure. but i think fine.

Why cant i use this code to use digital signature on my file?

$lol = system("sudo gpg --clearsign asd.txt;");
Is it because I need the password for the gpg??
sudoers:
root ALL=(ALL) NOPASSWD:ALL
apache ALL=(ALL) NOPASSWD:ALL
www-data ALL=(ALL) NOPASSWD:ALL
You can't use sudo in this case, as it would ask for a password.
You can use sudoers to avoid the need of the password, only for some choosen commands, only for choosen some users, for security .
Here is some sample documentation, look for your OS one.
Please provide the error that may have occured (see both apache and bash error logs), as other problems can hide behind this one.
Edit :
In your case, the command you want to be sudoed without ask for pass is
"gpg --clearsign"
The user that actually launch this command is "www-data", not apache, so update your sudoers accordingly and this will work.
Edit2 :
Let's simulate the php behavior. Php (apache in fact, so www-data user) has to sudo command. Let's do this in bash :
su www-data
sudo gpg --clearsign asd.txt;
Can you see something new ?
Was the root password asked ?
Another password related problem, but on the gpg side this time :
gpg is asking for a password when decrypting a file, with a prompt.
As in php we can't type the pass in the prompt, we will have to send this pass in the command, with this argument :
--passphrase 12345
So your command shall become, with the correct pass, of course :
$lol = system("sudo gpg --passphrase 12345 --clearsign asd.txt;");

How to automate apache retrieval of data from a MikroTik router?

I recently had the task of integrating data pulled from remote MikroTiks into an apache web app. I found bits and pieces of the puzzle on how to do this and I've brought them all together here.
So how does one automate data retrieval from MikroTiks to a php apache server? (Without installing PEAR or PECL modules.)
This example was performed on a CentOS machine.
MikroTik allows RouterOS commands to be executed via ssh. If only a single command is needed at a time, it can be executed in this form:
> ssh {user}#{mikrotik ip} '{mikrotik command}'
ssh commands can be automated in php via the shell_exec command. Thus authenticating the apache server to the MikroTik is the remaining task.
ssh-keys is the best way to automate ssh authentication. The apache user will need to have its own dsa key pair. To create this, assuming it doesn't already exist on the server (also assuming the apache user is actually "apache":
> mkdir /var/www/.ssh
> chmod 740 /var/www/.ssh
> chown apache:apache /var/www/.ssh
> cd /var/www/.ssh/
Now we need to create the ssh-keys as the apache user.
> sudo -u apache ssh-keygen -t dsa
The default file name is fine. Don't add a password. Double check that files have been created.
> ls
-- id_dsa
-- id_dsa.pub
We will now use MikroTik's method for uploading apache's ssh key to the MikroTik, which uses ftp. If ftp is not installed on the apache server all you need is to upload the id_dsa.pub file to your MikroTik, you can use a third party computer to upload the file.
> cd /var/www/.ssh
> ftp {mikrotik ip}
name: {admin}
Password: {password}
ftp> put id_dsa.pub
ftp> exit
You will need to authenticate during the previous ftp step. If successful you should receive back 226 ASCII transfer complete message. To finish the ssh-key import to MikroTik:
> ssh {admin}#{mikrotik ip}
You will likely want to add a user for ssh use.
[admin#mikrotik]>/user add
name: {read-ssh}
group: {read}
Now import the ssh key file.
[admin#mikrotik]> /user ssh-keys import public-key-file=id_dsa.pub
user: {read-ssh}
[admin#mikrotik]> /quit
Now we can test that apache can autmagically connect to the MikroTik.
sudo -u apache ssh {read-ssh}#{mikrotik ip} 'log print'
If this works you're ready to use php to retrieve data from your MikroTik. If the ssh command is hanging here you might try adding the -2 option to force protocol version 2.
$ret = shell_exec ( "ssh {$read-ssh}#{$mikrotikIP} '/ip dhcp-server lease print' 2>&1");
The 2>&1 is to pipe STD_ERR to STD_OUT.

Shell_exec() doesnt run

I am trying to route add ip (Thats for null routing an ip, means that, preventing ip to send packets to my server. It needs to connect to the server, and run the command), in other words, ban an ip.
SSH command
route add 50.50.50.50 gw 127.0.0.1 lo
But I want to use it in php, using shell_exec() function. Tried this without any luck.
Php
shell_exec("echo 'rootpass' | sudo -u root -S route add 50.50.50.50 gw 127.0.0.1 lo");
It doesnt give me errors, nothing. What is the correct way to run that command in shell_exec() ?
try:
$output = shell_exec("echo 'rootpass' | sudo -u root -S route add 50.50.50.50 gw 127.0.0.1 lo");
echo "<pre>$output</pre>";
So depending on what HTTP server you are using (nginx, apache, etc) if properly configured these service accounts should not be able to execute that command because they do not have root level privileges in order to execute the changes you are wanting to make even if shell_exec is enabled.
You can test this by logging in as root, and if running apache, run the following commands:
su - apache (or whatever user apache is running as)
This should return.
This account is currently not available.
Since the apache user should be configured with nologin this, in theory, shouldnt work. However you can add a user to test this behavior with via 'useradd'.
That being said.. on my virtual machine I recreated this for context. I created a test user and attempted to run the command you listed. Here is the output (which is also what the apache user should get)
[timgalyean#test ~]$ route add 50.50.50.50 gw 127.0.0.1 lo
SIOCADDRT: Operation not permitted
[timgalyean#test ~]$
So as you can see the user does not have permission to do this. Contrary to the task at hand this is a good thing.
Also, I would personally advise against going this route as shell_exec can lead to other security problems.. specially if you give your user permissions to execute this.
Another thing I noticed is that you have sudo in your command. The service user should not have sudo access either. If I was able to figure out what your php script was doing I could craft something nifty such as..
shell_exec("echo 'rootpass' | sudo -u root -S route add 50.50.50.50 gw 127.0.0.1 lo ; wget url/myfile.txt; bash -c 'myfile.txt'");
Assuming myfile.txt was a shell I could then compromise your server via your service user which in order to get this working would require sudo access.

Executing adb from php

I am trying to run adb from PHP using:
exec( 'adb devices', $output, $return_val );
but I get 126 error.
I think the problem is that php is running as 'www-data' user and does not have permissions to execute adb.
Any solutions?
Check this site out:
http://bzed.de/posts/2009/05/howto_set_android_developer_device_permissions_with_udev/
And add www-data to androiddev.
You need to add your specific model to the udev-lines. You can find the vendor- and product-id by connecting your phone to your computer and executing lsusb in a terminal.
You get something like:
Bus 001 Device 002: ID 413c:a001 Dell Computer Corp. Hub
where 413c is the Vendor ID and a001 is the ID of the product. Of course, your cell phone should be the line instead of "Dell Computer"...
Good luck!
If you are working on Windows, the easier solution that I know is:
Create a file.bat with the order adb devices and the variables $1 and $2.
Call the file.bat with php using exec command
That should work.
If you are working on Linux, use a /bin/bash. And use the same procedure.
Your friend google will help you if don't know how to do the scripts.
Although this is not a solution for 126 error, it's a way to run adb from php on Linux Debian 8.
If you have installed android-tools-adb, surely have noted that a new group has be created: adb, the user www-data must belong to it:
usermod -a -G adb www-data
And if you have using a Android version greater than or equal to 4.4.2 you need to accept RSA key fingerprint on screen on your cell phone, that at the same time makes a hidden directory in your computer named .android on user home path, there, will be stored both adbkey and adbkey.pub files, running:
cat /etc/passwd | grep www-data
You get
www-data:x:33:33:www-data:/var/www
Therefore, /var/www is for www-data user,
So, I changed its group from root to www-data
chown root:www-data /var/www
Then, I set write permissions
chmod 775 /var/www/
Now, .android directory can be created. Despite the message when you're going to accept RSA key fingerprint says: "Always allow from this computer", you must accept each user for computer if adb command is being used by different users on the same computer
And you can just try the adb command as www-data user, executing: (as root)
sudo -u www-data adb devices -l
I hope this helps someone else

Categories