False positive. It's unclear what version of phpseclib you're using but let's assume you're using the latest 2.0 release (2.0.34). call_user_func
only occurs on line 2946:
https://github.com/phpseclib/phpseclib/blob/2.0.34/phpseclib/Net/SSH2.php#L2946
default:
if (is_callable($callback)) {
if (call_user_func($callback, $temp) === true) {
$this->_close_channel(self::CHANNEL_EXEC);
return true;
}
} else {
$output.= $temp;
}
It's in the exec() method. $callback
is a parameter who's purpose is discussed at https://phpseclib.com/docs/commands#callbacks . The 3.0 branch does $callback($temp)
instead of callback_user_func($temp)
but it's the same basic idea. Probably $callback($temp)
doesn't work on older versions of PHP whereas callback_user_func($temp)
does.
call_user_func_array
is called twice in SSH2.php. Once on line 2227 and once on line 3375.
Line 2227 is in the login
method. Here's what that method does:
function login($username)
{
$args = func_get_args();
$this->auth[] = $args;
// try logging with 'none' as an authentication method first since that's what
// PuTTY does
if (substr($this->server_identifier, 0, 15) != 'SSH-2.0-CoreFTP' && $this->auth_methods_to_continue === null) {
if ($this->_login($username)) {
return true;
}
if (count($args) == 1) {
return false;
}
}
return call_user_func_array(array(&$this, '_login'), $args);
}
In phpseclib 3.0.11 it's doing return $this->sublogin($username, ...$args);
but the basic idea is that it's taking each element of $args
and passing it as an individual parameter to $this->_login
. Like if you did $this->_login($args)
then _login
would only be taking a single parameter. PHP 5.6 introduced the splat (...) operator but phpseclib 2 runs on PHP 5.3 so you have to do call_user_func_array
or just use a single parameter and that's it.
Here's the other instance of call_user_func_array
:
function _reconnect()
{
$this->_reset_connection(NET_SSH2_DISCONNECT_CONNECTION_LOST);
$this->retry_connect = true;
if (!$this->_connect()) {
return false;
}
foreach ($this->auth as $auth) {
$result = call_user_func_array(array(&$this, 'login'), $auth);
}
return $result;
}
So same thing.
So like I said, this is a nothing sandwich. A false positive.