phpBB мод: шифрование паролей - encrypt passwords

Клиентское и серверное программное обеспечение

phpBB мод: шифрование паролей - encrypt passwords

Сообщение Serg » Пн дек 09, 2013 18:56

Изменить размер шрифта ↓ВернутьИзменить размер шрифта ↑Не секрет, что данные форм (в том числе пароли) отправляются на сервер незашифрованными. Поскольку использование протокола https порой невозможно или весьма затруднительно, в этом случае имеется реальная (не потенциальная) уязвимость. Пакет с данными формы можно перехватить (при определённых условиях), например, в локальной сети, при использовании открытого wi-fi, на сервере и др. Обычно это вопрос доверия провайдеру/хостеру/сисадмину.

Перспективным представляется использование асимметричного алгоритма шифрования - RSA. Его особенность - использование пары ключей: public и private. Генерируется пара ключей, в нашем случае public используется для шифрования на стороне клиента (javascript), private - для расшифровки на стороне сервера (php). Public-ключ может передаваться по открытым каналам передачи, поскольку с его помощью нельзя расшифровать им же зашифрованные данные, для этого нужен private-ключ. Подобный способ обсуждался разработчиками phpBB (см., например, http://area51.phpbb.com/phpBB/viewtopic ... 84&t=33024), но не думаю, что до версии 4 что-то будет сделано, хотя желание видеть такое в версии 3.1 было высказано. Однако, никто не мешает сделать (и использовать) такой мод.

Данный подход не гарантирует "абсолютную" защиту и неоднократно критиковался, дискуссии легко найти в сети, но достаточно весомых аргументов ни в одной из них я так и не нашёл...

Алгоритм работы мода:
  • хук-функция проверяет наличие на странице форм (возможно связанных с вводом паролей) по наличию определений S_FORM_TOKEN и S_LOGIN_ACTION, а также наличие DEBUG_OUTPUT, если нет - пароли шифроваться не будут
  • хук-функция генерирует пару ключей (private, public) и сохраняет их в базе данных
  • хук-функция добавляет на страницы (в DEBUG_OUTPUT) код javascript, ответственный за шифрование паролей (поиск тэгов "input" типа "password" в формах, добавление "onsubmit" к подходящим тэгам "form" и функции шифрования, дополнительного тэга "input" типа "hidden" со справочной информацией); таким образом, при передаче формы на сервер вместо паролей будет передан зашифрованный текст
  • при приёме запроса POST анализируется наличие зашифрованных паролей; при из наличии пароли расшифровываются и подменяются в запросе для дальнейшего использования

Установка:

1) Мод добавляет на все страницы с формами код javascript, это выполняет хук hook_encrypt_passwords.php, добавляя код в DEBUG_OUTPUT. Поэтому следует убедиться в наличии DEBUG_OUTPUT в стилях и при отсутствии восстановить.

Если Вы используете мобильный стиль, то следует выполнить следующее:

В мобильных стилях не определен DEBUG_OUTPUT, используемый модом. Ршение проблемы:

- проверить, определена ли в overall_footer.html DEBUG_OUTPUT

- если нет, то добавить строку
Код: Выделить всё
<!-- IF DEBUG_OUTPUT -->{DEBUG_OUTPUT}<!-- ENDIF -->
предпочтительно в блок
Код: Выделить всё
<div class="copyright">
или для стиля Artodia после
Код: Выделить всё
Powered by <a href="http://www.phpbb.com/">phpBB</a> &copy; phpBB Group.


2) Создать таблицу в базе данных (префикс "phpbb_" замените на требуемый), выполнив SQL-запрос:

Код: Выделить всё
CREATE TABLE IF NOT EXISTS `phpbb_encrypt_passwords` (
   `ep_id` int(11) unsigned NOT NULL auto_increment,
   `time` int(11) unsigned NOT NULL default '0',
   `privatekey` text collate utf8_bin NOT NULL default '',
   PRIMARY KEY  (`ep_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=0;


3) Добавить в includes/constants.php перед "?>":

Код: Выделить всё
// Begin Encrypt Passwords Mod
define('ENCRYPT_PASSWORDS_TABLE',          $table_prefix . 'encrypt_passwords');
define('ENCRYPT_PASSWORDS_SESSION_LIFE',    3600);
// End Encrypt Passwords Mod


4) Добавить в common.php перед "?>":

Код: Выделить всё
// Begin Encrypt Passwords Mod
// Get form data
$ep_openssl_ext = function_exists('openssl_public_decrypt') ? true : false;
for ( $ep_index=0 ; ; $ep_index++ )
{
   if ( !isset($_POST['encrypt_passwords_' . $ep_index]) ) break;
   if ( !$ep_openssl_ext && !isset($ep_id) )
   {
      require_once($phpbb_root_path . 'includes/encrypt_passwords/phpseclib/Crypt/RSA.' . $phpEx);
      $ep_rsa = new Crypt_RSA();
      $ep_rsa->setEncryptionMode(CRYPT_RSA_ENCRYPTION_PKCS1);
   }
   $ep_name = explode(':',$_POST['encrypt_passwords_' . $ep_index]);
   $ep_id = (int) $ep_name[0];
   $ep_inputname = $ep_name[1];
   if ( isset($_POST[$ep_inputname]) )
   {
      $sql = 'SELECT * FROM ' . ENCRYPT_PASSWORDS_TABLE . ' WHERE ep_id = ' . $ep_id;
      $result = $db->sql_query($sql);
      $row = $db->sql_fetchrow($result);
      $db->sql_freeresult($result);
      if ( $row )
      {
         $ep_b64ep = $_POST[$ep_inputname];
         $ep_ep = base64_decode($ep_b64ep);
         $ep_dp = '';
         if ( !$ep_openssl_ext )
         {
            $ep_rsa->loadKey($row['privatekey']);
            $ep_dp = $ep_rsa->decrypt($ep_ep);
         }
         else
         {
            $ep_openssl_privatekey = @openssl_get_privatekey($row['privatekey']);
            @openssl_private_decrypt($ep_ep,$ep_dp,$ep_openssl_privatekey);
            @openssl_free_key($ep_openssl_privatekey);
         }
         if ( empty($ep_dp) ) $ep_dp = '';
         $_POST[$ep_inputname] = $ep_dp;
         $GLOBALS['_REQUEST'][$ep_inputname] = $ep_dp;
         // debug...
         //   $mes = 'id = ' . $ep_id . '<br />inputname = ' . $ep_inputname . '<br />b64ep = ' . $ep_b64ep . '<br />dp = ' . $ep_dp . '<br />privatekey = ' . $row['privatekey'] . '<br />';
         //   trigger_error($mes);
      }
   }
}
// Delete old sessions
if ( isset($ep_id) )
{
   $sql = 'DELETE FROM ' . ENCRYPT_PASSWORDS_TABLE . ' WHERE ep_id = ' . $ep_id . ' OR time < ' . (time() - ENCRYPT_PASSWORDS_SESSION_LIFE);
   $db->sql_query($sql);
}
// End Encrypt Passwords Mod


5) Копировать файлы из root.encrypt_passwords/ с сохранением дерева каталогов в:
includes/encrypt_passwords/phpseclib/openssl.cnf
includes/encrypt_passwords/phpseclib/Crypt/RSA.php
includes/encrypt_passwords/phpseclib/Crypt/Hash.php
includes/encrypt_passwords/phpseclib/Crypt/Random.php
includes/encrypt_passwords/phpseclib/Crypt/Math/BigInteger.php
includes/hooks/hook_encrypt_passwords.php
styles/jsencrypt.min.js

6) Очистить кэш.

Примечания:

1) Поскольку передаваемый пароль подменяется на зашифрованный, функция браузера "запомнить пароль" работать не будет ! Вернее, будет запоминаться зашифрованный пароль)

2) Для создания ключей на стороне сервера используется phpseclib. Для шифрования на стороне клиента используется jsencrypt. Для расшифровки на стороне сервера используется расширение php openssl или, если оно не установлено, phpseclib (в этом случае дешифрование идёт не очень быстро, на слабом сервере может исчисляться единицами секунд, так, у меня тестовая площадка собрана на маршрутизаторе и дешифрование занимает около 5 секунд при загрузке процессора 25%).

Скачать:
Encrypt passwors mod v.1.0.1: encrypt_passwords_v_1_0_1.zip

P.S. Обнаружен конфликт с модом галереи: текущий путь отличается от корневого phpbb, вызывает ошибку require_once.

Исправление: в файле hook_encrypt_passwords.php найдите:
Код: Выделить всё
      $path = defined('ADMIN_START') ? './../' : './';
и добавьте ПОСЛЕ проверку:
Код: Выделить всё
      if(!file_exists($path . 'includes/encrypt_passwords/phpseclib/Crypt/RSA.php')) return;
Это отключит мод для всех случаев, когда не тот путь...
Аватара пользователя
Serg
Администратор
 
Сообщения: 88
Зарегистрирован: Ср янв 14, 2009 13:50
Имя: Сергей Юрьевич

Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1