Журнал LinuxFormat - перейти на главную

LXF81:PHP

Материал из Linuxformat
Версия от 20:44, 8 марта 2008; Yaleks (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Содержание

PHP Безопасная оболочка

Устали от людей, взламывающих ваш элитарный шифр rot26? Пол Хадсон научит вас защищаться.

Геродот однажды сказал: “Ни одно расширение не зови счастливым, пока не начал его использовать”. Ну хорошо, он сказал не совсем так, но в любом случае это справедливо: в составе PECL (PHP Extention Community Library) можно найти сотни странных, удивительных и великолепных расширений, ждущих когда же мы их попробуем, однако, пока вы не узнаете о существовании одного из них, пока не попробуете сами им воспользоваться – оно для вас все равно что не существует.

Эта статья посвящена изучению одной из скрытых драгоценностей PECL – расширению SSH2. Оно позволяет вам создавать безопасные зашифрованные каналы связи через Интернет, используя PHP, а затем использовать их для выполнения команд оболочки, переноса файлов и всего остального, что обычно делается при помощи SSH. Да, в работе через Web содержится определенный риск, но если вы а) поместили поле ввода пароля на странице и б) требуете указывать его для установки SSH-соединения, то вы находитесь в относительной безопасности. С другой стороны, если вы пишите скрипты, которые будете вызывать из локальной консоли, это расширение оказывается мощным средством для выполнения автоматических запросов к удаленным серверам вдали от назойливых взглядов хакеров.

Подключение

Я почти уверен, что расширение PHP SSH у вас не установлено, что не удивительно, поскольку оно не распространяется вместе с PHP, а библиотека от которой оно зависит (libssh2) очень редко включается в состав дистрибутивов. После того, как вы пройдете все этапы установки (они описаны во врезке справа), вам потребуется выполнить маленький тест, просто чтобы убедиться, что все в порядке. Попробуйте что-то вроде:

<?php
$conn = ssh2_connect(“192.168.133.98”, 22);
if (!$conn) die(“Could not connect!);
echo ssh2_fingerprint($conn);
?>

Здесь вы видите две SSH-функции: ssh2_connect(), которая выполняет подключение к серверу (первый параметр) по указанному порту (второй параметр) и ssh2_fingerprint(), которая принимает подключение в качестве своего единственного параметра и выводит MD5-отпечаток сервера. Этот отпечаток никогда не меняется. В результате довольно легко опознать попытку атаки “man-in-the-middle” (при которой хакер пререхватывает ваше соединение вместо сервера, чтобы узнать пароль), поскольку полученное значение будет отличаться от ожидаемого.

Запустив этот сценарий, вы должны увидеть в качестве результата отпечаток для своего сервера. Он должен полностью совпадать с тем, который вы получаете, набрав ssh localhost на удаленной консоли за тем исключением, что при работе в командной строке SSH разделяет отпечаток на двухсимвольны блоки, отделенные двоеточиями.

Если вы подключаетесь, указав только IP-адрес (или доменное имя сервера) и порт, то библиотека SSH автоматически выберет устойчивое шифрование и устойчивый метод обмена ключами, но у вас есть возможность снизить планку, если клиент или сервер не понимают сильных алгоритмов. Чтобы изменить свойства подключения используется третий параметр функции ssh2_connect(). Он должен быть массивом, содержащим ключи “kex”, “client_to_server” и “server_to_client”. Значением первого ключа, “kex”, должен выступить алгоритм обмена ключами, который вы запрашиваете. Здесь можно указать diffie-hellman-group1-sha1, diffiehellman- group14-sha1 или diffie-hellman-group-exchange-sha1.

Параметры “client_to_server” и “server_to_client” сами являются массивами, определяющими объявленные алгоритм шифрования (“crypt”), метод сжатия (“comp”) и метод MAC (“mac”). Например, если вы хоти- те использовать довольно небезопасное SSH-соединение (это бывает возможно в доверенной сети, если для вас особенно важна скорость), то вы можете запросить шифрование по алгоритму 3DES вместо AES, используемого по умолчанию. Пример кода:

<?php
$methods = array(
“client_to_server” => array(crypt=> “3des-cbc”),
“server_to_client” => array(crypt=> “3des-cbc”)
);
$conn = ssh2_connect(“192.168.133.98”, 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”;
?>

Массив $methods содержит ключи “client_to_server” и “server_to_ client”, которые в свою очередь содержат массивы с ключом “crypt” и значением “3des-cbc”. CBC расшифровывается как Cipher Block Chaining (блочная передача зашифрованного текста), при его использовании передаваемые данные разбиваются на маленькие блоки и к каждому блоку перед шифрованием применяется операция XOR с предыдущим блоком, что приводит к тому что блоки, содержащие один и тот же зашифрованный текст оказываются совершенно непохожи друг на друга.

Если вы хотите попробовать настройку “comp”, укажите ее в мас- сивах “client_to_server” и “server_to_client”. В качестве значения используйте “zlib”.

В нашем коде появляется новая функция, ssh2_methods_ negotiated(). Она возвращает массив, содержащий описание алгоритмов обмена ключами, сжатия и MAC (Message Authentication Code, код подтверждения подлинности сообщения), которые были в реальности использованы при этом подключении к удаленному серверу. Затем мы просто вывели на печать некоторые из полученных значений, но вы, возможно, захотите выполнить какие-то свои проверки этих значений, чтобы убедиться, что уровень безопасности вас устраивает.

Отправьте этот файл

Как любой другой пакет SSH, расширение SSH для PHP поддерживает SFTP и SCP, методы безопасной передачи файлов. Оба они используют одни и те же алгоритмы шифрования и поэтому одинаково безопасны, вся разница в том, хотите ли вы полноценное соединение напоминающее FTP, или же вам нужно только читать и записывать файлы в стиле cp.

Давайте сначала посмотрим на реализацию SCP, который был разработан чтобы осуществлять копирование файлов по принципу команды cp, но только через защищенное интернет-соединение. Рассмотрим две новых функции: ssh2_auth_password() выполняет аутентификацию нашего соединения, а ssh2_scp_send() копирует локальный файл на удаленный сервер. Для начала давайте создадим локальный файл, выполнив следующую команду:

echo “Hello, world” > hello.txt

А теперь передадим наше приветствие на сервер. Вам потребуется указать имя пользователя и пароль для подключения к серверу, для этого просто замените в следующем сценарии строки “username” и “password” на правильные значения.

<?php
$conn = ssh2_connect(“192.168.133.98”, 22);
if (!$conn) die(“Could not connect!);
ssh2_auth_password($conn, “username”, “password”);
ssh2_scp_send($conn, “hello.txt”,/home/<имя удаленного
пользователя>/hello.txt”);
?>

Обратите внимание, вам нужно указать будущее местоположение файла на удаленном сервере, в нашем случае это /home/<имя удаленного пользователя>/hello.txt. Получение файлов происходит так же просто, достаточно использовать функцию ssh2_scp_recv() и поменять местами второй и третий параметры.

ssh2_scp_recv($conn,/home/yourremoteusername/hello.txt”,”hello.txt”)

Второй способ передачи файлов – это использование SFTP, который позволяет выполнять FTP-подобные команды (например, mkdir, stat и так далее) по защищенному SSH-каналу. И, что более важно, SFTP в PHP реализован как оболочка для fopen, что значит вы можете использовать любые файловые функции PHP. Например:

<?php
$conn = ssh2_connect(“192.168.133.98”, 22);
if (!$conn) die(“Could not connect!);
ssh2_auth_password($conn, “username”, “password”);
$sftp = ssh2_sftp($conn);
$file = file_get_contents(“ssh2.sftp://$sftp/home/paul/hello.txt”);
echo $file;
?>

Итак, мы подключились к удаленному серверу и авторизовались на нем, указав имя пользователя и пароль. Затем мы вызвали функцию ssh2_sftp() для полученного соединения, которая выполнила SFTP- подключение и вернула его дескриптор. Именно этот номер потребуется для использования обычных файловых функций, так что мы присвоили его переменной $sftp. Теперь мы можем вызвать функцию file_get_ contents(), указав в ssh2.sftp:// в качестве протокола, и PHP прочитает содержимое файла через прозрачное SSH-подключение. Значение переменной $sftp нам потребовалось, чтобы указать, из какого потока выполнять чтение. И обратите внимание на то, что нам вновь пришлось полностью указать полный путь, поскольку по умолчанию поиск выпол- няется в корневом каталоге.

Я заказал безопасный канал

Нашим последним SSH-трюком будет получение полноценной SSH- оболочки, которую мы можем читать и писать так, будто это обычный терминал. PHP вновь интерпретирует ее как локальный файл, так что мы сможем использовать функции fread() and fgets() обычным обра- зом. Требуется только придерживаться одного главного правила – нужно дать удаленному компьютеру время на то, чтобы выполнить нашу команду, иначе мы будем искать результат до того, как он будет готов. Итак, вот код:

<?php
$conn = ssh2_connect(“192.168.133.98”, 22);
if (!$conn) die(“Could not connect!);
ssh2_auth_password($conn, “username”, “password”);
$stdio = ssh2_shell($conn);
sleep(1);
while($line = fgets($stdio)) echo $line;
fwrite($stdio, “uname -a\n”);
sleep(1);
while($line = fgets($stdio)) echo $line;
fclose($stdio);
?>

Все вплоть до вызова ssh2_shell() остается прежним. Новая для нас функция ssh2_shell() принимает SSH-соединение в качестве параметра и возвращает дескриптор, который указывает на стандартный поток ввода и стандартный поток вывода SSH-оболочки, на который программы выводят результаты своей работы. Именно сюда мы должны писать команды и отсюда же читать результаты.

Для начала выполним главное правило – нам придется исполь- зовать функцию sleep(), чтобы прервать выполнение на 1 секунду и дать серверу время очистить соединение и вывести шапку (строку приветствия удаленного пользователя). Затем мы используем цикл while, состоящий из одной строчки, чтобы прочитать и показать весь текст, переданный сервером (“Welcome to XYZServer!” и так далее). После того, как приглашение прочитано, мы пишем нашу команду “uname –a”. Она показывает системную информацию о компьютере, на котором запущена, такую как версия ядра, архитектура процессора и так далее.

После второго ожидания, пока эта команда отработает, мы делаем еще один однострочный цикл while и показываем полученные от сервера данные. В конце мы закрываем поток командой fclose(), чтобы прибраться за собой и на этом наш сценарий заканчивается. Красиво, правда?


Инструкции по установке SSH для PHP

  1. Установите OpenSSL и его библиотеку разработчика: libssl-dev или libssl-devel.
  2. Вытащите libssh2 из каталога Magazine/PHP вашего диска (ищите файл libssh2-0.13.tar.gz). Распакуйте его, выполните команду ./configure, а затем переключитесь на суперпользователя и запустите make all install.
  3. Возьмите расширение PHP SSH2 из каталога Magazine/PHP вашего диска (файл ssh2-0.10.tgz), распакуйте и запустите phpize, ./configure --with-ssh2, и, наконец, make. В результате вы получите файле ssh2.so в каталоге modules. Его нужно будет скопировать в ваш каталог расширений PHP.
  4. Выполните php –i | grep ini. Эта команда покажет вам местоположение файла php.ini, скорее всего, он находится в /etc/php.ini или /usr/local/lib/php.ini. Если у вас нет php.ini, то вам потребуется скопировать php.inirecommended из исходного дистрибутива PHP установленной у вас версии.
  5. Откройте файл php.ini и найдите в нем строчку ‘extension_dir’. Скорее всего, она будет показывать на примерно такой каталог: /usr/local/lib/php/extensions/.
  6. Поскольку вы все еще находитесь в php.ini, поищите в нем слово ‘dll’, и вы попадете в подраздел с описанием расширений. Вам нужно добавить туда вот такую строчку: extension=ssh2.so.
  7. Сохраните php.ini, а затем перенесите файл modules/ssh2.so, полученный на третьем шаге в каталог с расширениями PHP
  8. Запустите команду php –m. В полученном списке вы увидите ssh2.

Если нет, то, видимо, один из шагов вам не удался...

Персональные инструменты
купить
подписаться
Яндекс.Метрика