am1
am1

Reputation: 347

Why is exec() not containing the output?

When i run the command echo /tmp/stderr{,.pub} | xargs -n 1 ln -sf /dev/stderr && yes | ssh-keygen -t ed25519 -C "" -N "" -f /tmp/stderr > /dev/null; rm /tmp/stderr{,.pub} on shell, it returned the private/public keypair as shown below (don't worry, the keypair isn't used):

blackbox /home/clock # echo /tmp/stderr{,.pub} | xargs -n 1 ln -sf /dev/stderr && yes | ssh-keygen -q -t ed25519 -C "" -N "" -f /tmp/stderr >/dev/null; rm /tmp/stderr{,.pub}
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACA1vZhl2jqtzhEqaqbKwYjLB1OIH8hMPtWB/PWhqeI/QQAAAIj4n5if+J+Y
nwAAAAtzc2gtZWQyNTUxOQAAACA1vZhl2jqtzhEqaqbKwYjLB1OIH8hMPtWB/PWhqeI/QQ
AAAEAtcSI3RLsOo0CXnat4Gs4JENGyDPbGojIT8GU0E+3vUDW9mGXaOq3OESpqpsrBiMsH
U4gfyEw+1YH89aGp4j9BAAAAAAECAwQF
-----END OPENSSH PRIVATE KEY-----
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDW9mGXaOq3OESpqpsrBiMsHU4gfyEw+1YH89aGp4j9B

But when i run the command thru exec() in PHP, it returned the command itself:

blackbox /home/clock # php -f key.php
Array
(
[0] => /tmp/stderr{,.pub} | xargs -n 1 ln -sf /dev/stderr && yes | ssh-keygen -t ed25519 -C "" -N "" -f /tmp/stderr > /dev/null; rm /tmp/stderr{,.pub}
)

The code i use:

<?php
$exec_output = '';
$exec_return = '';

// echo /tmp/stderr{,.pub} | xargs -n 1 ln -sf /dev/stderr && yes | ssh-keygen -t ed25519 -C "" -N "" -f /tmp/stderr > /dev/null; rm /tmp/stderr{,.pub}
$cmd = array('echo', escapeshellarg('/tmp/stderr{,.pub} |'), 'xargs -n 1 ln -sf /dev/stderr', escapeshellarg('&& yes |'), 'ssh-keygen -t ed25519', escapeshellarg('-C "" -N "" -f /tmp/stderr > /dev/null; rm /tmp/stderr{,.pub}'));

exec(implode(' ', $cmd), $exec_output, $exec_return);

print_r($exec_output);
?>

Why?

PS: I don't want to fill the generated keypair into a file, even not in /tmp.

Upvotes: 1

Views: 47

Answers (1)

vonschlager
vonschlager

Reputation: 324

  1. Shell path expansions won't work when passed as strings:

    echo '/tmp/stderr{,.pub}'

    instead you need to use unquoted ones

    echo /tmp/stderr{,.pub}

  2. You cannot quote argument with the program option itself, it will be treated like one argument.

  3. There is no user input here, so there is no need to escape anything.
  4. exec only catches stdout and you are redirecting yours into /dev/null.

Altered $cmd array looks like this:

$cmd = array(
  'echo',
  '/tmp/stderr{,.pub}',
  '|',
  'xargs -n 1',
  'ln -sf',
  '/dev/stderr',
  '&&',
  'yes 2>/dev/null',
  '|',
  'ssh-keygen',
  '-t',
  'ed25519',
  '-C',
  '""',
  '-N',
  '""',
  '-f',
  '/tmp/stderr',
  '2>&1',
  '>/dev/null',
  ';',
  'rm',
  '/tmp/stderr{,.pub}'
);

Upvotes: 1

Related Questions