1

I tried to run su command with PHP shell_exec function. At first I tried:

<?php
echo(shell_exec('echo \'password\' | su user -c \'whoami\' 2>&1;'));
?>

and I got:

su: must be run from a terminal

Then I've read about spawning terminal with python's pty and put it into the shell code:

<?php
echo(shell_exec('echo "if [ -t 1 ] ; then echo "terminal found"; fi; echo \'password\' | su user -c \'whoami\';  exit" | python -c \'import pty; pty.spawn("/bin/bash")\' 2>&1;'));
?>

and here's the output:

if [ -t 1 ] ; then echo terminal found; fi; echo 'password' | su user -c 'whoami';  exit
www-data@server:/some/directory$ if [ -t 1 ] ; then echo terminal found; fi; echo 'password' | su user -c 'whoami';  exit
terminal found
su: must be run from a terminal
exit

Any idea why pty isn't working or what other tool should I use to spawn a terminal? PHP runs behind Apache on Debian.

EDIT: I am searching for a workaround that doesn't require physical access to server or connecting via SSH. Suppose that I want to use su to start sshd and only working servers are FTP and Apache.

Patryk Hes
  • 43
  • 1
  • 1
  • 5

5 Answers5

5

The answer (not a solution) is simply you can't.

Good admin will prevent it always. It's a very bad idea and you know you should avoid it and use some better solution.

E.g. set just a flag via php (FTP or any other method)

I.e. schedule some actions (e,g. restart SSH server) when a specific flag is set via php (eg. file is present, json response or db value).

The trigger can by anything from PHP, but the key is that the action should be pre-defined and with solid, expected result, with a fallback when the php part fails (eg. when someone manages to trigger the php part without your permission).

Another solution might be to write bash scripts performing required actions, set up password-less access to those scripts (in sudoers file) and run them via php.

takeshin
  • 1,471
  • 3
  • 21
  • 28
2

It is a very bad idea to run anything su related via PHP on a web server. It opens up too many possibilities for server compromise.

If some particular executable needs to be run as root, you can use sudo mechanism to do that. Unfortunately configuring sudo takes quite much effort.

Tero Kilkanen
  • 36,796
  • 3
  • 41
  • 63
  • 1
    I know it's a bad idea, but sometimes it's necessary, like for restarting SSH. Suppose I accidentaly stopped SSH server and have only FTP - what should I do (except physical access to server, of course)? – Patryk Hes Mar 08 '14 at 18:33
  • @Patryk Hes In that case configure `sudo` something like this `www-data ALL=(ALL) NOPASSWD: /etc/init.d/ssh *` and then call `sudo /etc/init.d/ssh start|stop|restart` within your `php` code. – krisFR Mar 08 '14 at 18:44
  • Well, if you want to prevent "stop SSH server accidentally" from happening, then having a script to run the command is one way. Another way would be to have a cron job that checks for existence of some file, and if the file exists, SSH is restarted and file is deleted. FTP isn't secure either btw. – Tero Kilkanen Mar 08 '14 at 18:47
  • @TeroKilkanen using cron is a good idea. Still it can't help me in this situation. – Patryk Hes Mar 08 '14 at 19:49
2

If must to use su from your php program then the correct way is to use it through expect. You can use a small script:

#!/use/bin/expect -f

spawn "su some_user -c cmd.sh"
expect {
    ssword: { send "myStrongPass\r" }
}
interact

But, you should be aware that this creates a security risk - you are storing a clear text password of a user in a file readable by a webserver. And that user has access to sudo.. You should carefully think about it.

thor
  • 658
  • 1
  • 7
  • 18
  • Seems plausible, but you have to have installed expect first. Maybe it would help someone with expect installed and no netcat. – Patryk Hes Mar 09 '14 at 22:28
0

My friend have shown me how to get tty and then su.

<?php
shell_exec('nc -l -p 1234 -c /bin/sh');
?>

Then you have to telnet on port 1234 and enter those commands:

python -c 'import pty; pty.spawn("/bin/sh")'
tty

and it works just fine.

Patryk Hes
  • 43
  • 1
  • 1
  • 5
0

Instead of running su directly, run it via sudo made sure, you've given Apache's user permission to do that w/o password, so it'd be as simple as: sudo su …. You can also (and you'd better) limit what commands are to be run using sudo pattern matching and of course you can use sudo itself w/o making it invoke su.

poige
  • 9,448
  • 2
  • 25
  • 52
  • Mind the situation - I couldn't use sudo, because I couldn't edit sudoers file. That would require physical access or SSH connection. – Patryk Hes Mar 09 '14 at 12:30