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

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:

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

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.

closed as off-topic by Iain, symcbean, mdpc, Ward, Katherine Villyard Mar 11 '14 at 19:01

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Questions must be relevant to professional system administration. Server Fault is dedicated to professional system and network administrators. End user and enthusiast questions are off-topic (contact your system administrator or hire a professional to help you out). Please see the Help Center for more information." – mdpc, Ward
If this question can be reworded to fit the rules in the help center, please edit the question.

  • 2
    You should take a look at sudo/ – Iain Mar 8 '14 at 18:40
  • sudo would be nice if www-data were in sudoers file. Unfortunately it isn't and I cannot change sudoers without root access or SSH connection. – Patryk Hes Mar 8 '14 at 19:43
  • What reason do you have to need to use the account of another user? – Matthew Ife Mar 8 '14 at 22:18
  • For example, restarting SSH server. First, I have to su on user that is in sudoers, then sudo. – Patryk Hes Mar 9 '14 at 12:32
  • 3
    This question appears to be off-topic because the OP doesn't appear to have sufficient access to the system to do it correctly. – Iain Mar 9 '14 at 17:14

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.

  • I can - please look at my answer. – Patryk Hes Mar 9 '14 at 22:29

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.

  • 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 8 '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 8 '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 8 '14 at 18:47
  • @TeroKilkanen using cron is a good idea. Still it can't help me in this situation. – Patryk Hes Mar 8 '14 at 19:49

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" }

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.

  • Seems plausible, but you have to have installed expect first. Maybe it would help someone with expect installed and no netcat. – Patryk Hes Mar 9 '14 at 22:28

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

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")'

and it works just fine.


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.

  • 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 9 '14 at 12:30

Not the answer you're looking for? Browse other questions tagged or ask your own question.