PHP Secure the shell

From LXF Wiki

Revision as of 20:05, 2 Jul 2008; view current revision
←Older revision | Newer revision→

Extensions special script programming

(Original version written by Paul Hudson for LXF issue 81.)

Original article (PDF) (

Sick of people breaking through your elite rot26 encryption? Get some security skills with Paul Hudson.

Herodotus once said: “Call no extension happy until it’s being used.” Well, it went something like that, and either way it’s correct: PHP, through the PHP Extension Community Library (PECL), has hundreds of weird, wacky and wonderful extensions waiting for us to try out. But until you actually know about them – until you try them yourself – they might as well not exist.

This issue we’re going to look at one of the hidden gems of PECL: the SSH2 extension. This allows you to form secure, encrypted connections over the internet using PHP, and execute shell commands, transfer files and do whatever else you would normally do over SSH. Yes, this is potentially risky if you’re working over the web, but as long as you a) put a password on the web page and b) prompt people to enter their password for the SSH connection, you’re quite safe. On the other hand, if you’re writing scripts for local console use, this extension is a powerful tool for querying remote servers beyond the prying eyes of crackers.

Making the connection

You almost certainly don’t have the PHP SSH extension installed, which isn’t surprising: it’s not bundled with PHP, and its primary dependency (libssh2) is very rarely found in distros. Once you’ve gone through the steps in the Installation Guide box (below), we need to do a quick test connection to make sure you have it all set up correctly. Try this out:

$conn = ssh2_connect(“”, 22);
if (!$conn) die(“Could not connect!”);
echo ssh2_fingerprint($conn);

This introduces two of the SSH functions: ssh2_connect(), which forms an SSH connection with a server (parameter 1) on a specific port (parameter 2), and ssh2_fingerprint(), which takes a connection as its only parameter and prints out the MD5 fingerprint of the server. These fingerprints don’t change. As a result, it’s quite easy to spot man-in-the-middle attacks (where hackers intercept your connection to sniff your password), simply because their key will be different from expected.

Run the above script and you should see the fingerprint printed out. This will be the same thing you’d see if you had typed ssh localhost on the remote machine, except that the command line SSH usually breaks the fingerprint into twocharacter blocks separated by colons.

When you form a connection by providing only the IP address (or domain name) and the port number, the SSH library will automatically pick strong encryption and a strong keyexchange algorithm, but it will gracefully downgrade if your client or the server don’t support certain algorithms. You can override the requests by specifying connection methods, using the third parameter to ssh2_connect(). This should be an array, which can contain keys called “kex”, “client_to_server” and “server_to_client”. The first, “kex”, is the key exchange algorithm that you want to request. This can be diffie-hellman-group1-sha1, diffiehellman-group14-sha1 or diffie-hellman-group-exchange-sha1.

The “client_to_server” and “server_to_client” keys contain their own arrays defining what encryption algorithms (“crypt”), compression methods (“comp”) and MAC methods (“mac”) to advertise. For example, if you wanted to use a fairly insecure SSH connection (something for a trusted network where speed is key), you could request 3DES encryption rather than the AES default. Here’s the code:

$methods = array(
“client_to_server” => array(“crypt” => “3des-cbc”),
“server_to_client” => array(“crypt” => “3des-cbc”)
$conn = ssh2_connect(“”, 22, $methods);
if (!$conn) die(“Could not connect!”);
$methods_neg = ssh2_methods_negotiated($conn);
echo “Keys negotiated with: {$methods_neg[‘kex’]}\n”;
echo “Client-to-server uses these methods:\n”;
echo “ Encryption: {$methods_neg[“client_to_server”][“crypt”]}\n”;
echo “ Compression: {$methods_neg[“client_to_server”][“comp”]}\n”;
echo “Server-to-client uses these methods:\n”;
echo “ Encryption: {$methods_neg[“server_to_client”][“crypt”]}\n”;
echo “ Compression: {$methods_neg[“server_to_client”][“comp”]}\n”;

The $methods array contains “client_to_server” and “server_to_client”, which are themselves arrays that contain “3des-cbc” in the “crypt” key. CBC stands for Cipher Block Chaining, which breaks your transmissions down into small blocks and XORs each block against the block preceding it before it is encrypted, which makes it much less likely that two plain text blocks look the same in cypher text.

If you want to try setting “comp” to enable compression, just add the “comp” key to the “client_to_server” and “server_to_client” arrays, specifying “zlib” as its value.

Our new code introduces the ssh2_methods_negotiated() function, which returns an array containing the key exchange, encryption, compression and MAC (Message Authentication Code) algorithms that were agreed upon between our PHP script and the remote server. We’re just printing some of them out here, but you might want to perform your own checks at this point to ensure that you’re using a secure connection.

Installation guide

Eight steps to SSH on PHP

  1. Install OpenSSL and its development libraries: libssl-dev or libssl-devel.
  2. Snag libssh2 from the Magazine/PHP directory of your disc (look for libssh2-0.13.tar.gz). Unpack it and run ./configure, then switch to root and run make all install.
  3. Get the PHP SSH2 extension from the Magazine/PHP directory of your disc (look for ssh2-0.10.tgz), unpack it, run phpize, ./ configure --with-ssh2, then make. This creates the in the modules directory. Copy that into your PHP extensions directory.
  4. To find your extensions directory, run php –i | grep ini to find your php.ini file – it’s probably in /etc/php.ini or /usr/local/lib/php.ini. If you don’t have a php.ini file, you need to copy the php.ini-recommended over from the PHP source code for your version.
  5. Open up the php.ini file and look for the ‘extension_dir’ line. This should be set to something like /usr/local/lib/php/extensions/
  6. Still in the php.ini file, search for ‘dll”, and you’ll come to the extensions section. You need to add this line:
  7. Save the file, and now move the file modules/ to the location of your PHP extensions directory.
  8. Run php –m – you should see ssh2 in there. If not, you’ve mucked up one of the steps!

File it away