четверг, ноября 15, 2007

Шифрование паролей с помощью PHP

Если вы разрабатываете вебсайты которые требуют регистрации пользователей - ваша обязанность заключаеться в безопасном сохраниении паролей пользователей. И если вы храните пароли в открытом виде - вы не делаете свою работу качественно. Можно согласиться, что хранить пароли в открытом виде удобно, но что делать если важу базу данных с паролями украли? Это означает что можно получить доступ к данным пользователей не только на вашем сайте, но и на других так как большинство пользователей используют одинаковые пароли.

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

Хеширование

Хеш - это строковые данные получаемые из оригинального пароля с помощью одностороннего алгоритма. Другими словами достаточно легко получить хеш из оригинала, но гораздо труднее (при определенных условиях практически не возможно) получить оригинал из хеша. Вы храните хеш в базе данных и когда пользователь авторизуется в системе просто сравниваете его с хешем полученным от введенного пользователем пароля. Например так:

if( $user->passwordhash == sha1( $_POST['password'] ) )

Таким образом вы никогда не будете хранить настоящие пароли пользователей.

Сушествует несколько алгоритмов хеширования в PHP среди которых md5 и sha1 наиболее распространенные. К сожалению они не настолько безопасны, как ожидалось. Будет лучше использовать более безопасный метод хеширования, и если у вас есть расширение Hash для PHP (поумолчанию с версии 5.2.1) то вы будете иметь доступ к более широкому кругу алгоритмов. Более лучший пример будет выглятеть так:

if( $user->passwordhash == hash( 'whirlpool', $_POST['password'] ) )
Радужная таблица

Но существует другая проблема. После того, как ваша база данных украденна, злоумышленник имеет достаточно времени чтобы взломать пароли используя радужные таблицы. Это выглядит прмерно следующим образом: создается большой набор хеш сумм на основе какого либо набора слов и затем полученные хеш суммы в разных комбинациях сравниваються с имеющимися в бд хеш суммами. И через час или около того примерно поливина всех ваших паролей будет расшифрованна.

Чтобы избежать этого вам стоит модифицировать пароли добавляя к ним случайную строку ( называемую salt или nonce). Основную часть времени расшивровки паролей с помощью радужных таблиц составляет построения набора хеш сумм. Добавление случайной строки к паролю повлечет за собой переформирование словарей хеш сумм с учетом случайной строки, что приведет к большим затратам времени. Каждый пароль должен иметь уникальную случайную строку.

Решение

Для обеспечения повышенной безопасности вам нужен код аналогичный следующему:

// Получим случайную строку
function getPasswordSalt()
{
return substr( str_pad( dechex( mt_rand() ), 8, '0', STR_PAD_LEFT ), -8 );
}

// Вычислим хеш
function getPasswordHash( $salt, $password )
{
return $salt . ( hash( 'whirlpool', $salt . $password ) );
}

// Сравниваем палоь и хранимый хеш
function comparePassword( $password, $hash )
{
$salt = substr( $hash, 0, 8 );
return $hash == getPasswordHash( $salt, $password );
}

// Получим хеш для пароля
$hash = getPasswordHash( getPasswordSalt(), $password );

Вам не обязательно добавлять строку к хеш сумме и вы можете хранить их раздельно. Так же строка не обязательно должна быть в шеснадцатиричном виде. Итак вы не будете иметь самый быстрый алгоритм шифрования, но будете иметь более безопасный.

Cookie HttpOnly

Теперь куки могут быть недоступны для клиентских скриптов (JavaScript) во избежание кражи важных данных. Как известно, файлы cookies, сохраняются на клиентской машине пользователя и могут быть доступны не только из PHP-скриптов, но и из JavaScript. Таким образом, JS-скрипты могут быть использованы для кражи информации из Cookie.
Нововведения предназначены для предотвращения такой возможности и могут быть использованы в функциях setcookie() и setrawcookie() в дистрибутивах PHP 5.2. В ранних версиях можно использовать опцию следующим образом:
header("Set-Cookie: hidden=value; httpOnly");
Изменения коснулись и механизма сессий, так как он тесно связан с cookie. Привести механизм в действие можно будет так:
ini_set("session.cookie_httponly", 1);
или
session_set_cookie_params(0, NULL, NULL, NULL, TRUE);
Такой подход пока еще не будет работать во всех браузерах и актуален только для IE.

XSS & PNG

Хоть это и кажется бредом но это возможно. Делается это простым дописыванием html-кода в конец PNG-файла. В итоге браузер выплёвывает текстовое содержимое файла наружу и код выполняется. Неудобств у этой атаки 3:

  1. Атакуемый должен обратится непосредственно к картинке, а не к страничке её содержащую. Например www.server.com/image1.png.
  2. Многие популярные движки хранят расширение файлов в базе, а сами файлы лежат переименованные в отдельной папке с одним и тем же расширением (например '.ext').
  3. Такие атаки проходят только с браузером Internet Explorer. Тот -же FireFox просто пишет что изображение повреждено.
Как видите ограничения хоть и есть, но они не слишком значительны(кроме второго). Теперь разберём всё на практике. Давайте напишем небольшой скрипт который будет отвечать за аплоад картинок на сервер и форму в которой пользователь будет выбирать какую картинку загрузить.

index.html:
<form enctype="multipart/form-data" action="upload.php" method="post">
Отправить этот файл: <input name="userfile" type="file" />
<input type="submit" value="Send File" />
</form>
upload.php:
<?php
// Изображения сохраняем в папку images
$upload_dir = "images/";
$upload_file = $upload_dir . basename($_FILES['userfile']['name']);
move_uploaded_file($_FILES['userfile']['tmp_name'], $upload_file);
?>
У нас есть самый простой аплоадер картинок. Теперь нарисуйте в любом редакторе картинку (например точку) и сохраните. Далее откройте эту картинку простым текстовым редактором и допишите в конец текст <script>alert(1)</script>. Если всё нормально то обратившись к этому изображению с помощью IE Вы увидите окошко с цифрой 1 и кишки картинки в виде обычного набора странных символов. Теперь нужно поставить фильтр на этот аплоад что бы он не пропускал опасные картинки. Давайте сделаем это на примере тега ''. Мы будем действовать следующим образом:
  1. Сохраним загруженное изображение
  2. Откроем как текстовый файл и возьмём внутренности
  3. В получившемся тексте будем искать <script
  4. Если данное выражение найдётся то удалим файл и сообщим об этом.
Вот код который нужно добавить в аплоадер после загрузки файла:
// Открываем файл для чтения
$handle = fopen($upload_file, "r");
// Читаем весь полностью
$file_text = fread($handle,filesize($upload_file));

fclose($handle);
// Если обнаружился <script
if (strpos($file_text,'<script')>-1)
{
// то удаляем этот файл и сообщаем пользователю
unlink($upload_file);
print 'XSS image!';
}
Теперь создайте ещё одно изображение только полностью безопасное и попробуйте загрузить его на сервер. У меня всё прошло нормально, а вот на загрузку опасного файла скрипт выругался. Естественно надо фильтровать не только тег но и тэги типа <embed>,<applet> и т.д.. Так же нужно не забывать о фильтрации полного слова javascript. А перед проверкой лучше текстовые внутренности перевести через функцию strtolower() так как могут попасться и <script></script> и JAvAscRIpT:alert(1)
И ещё. Не вздумайте проверять изображения на наличие '<' и '>' так как эти символы присутствуют в коде каждой картинки и каждое PNG-изображение будет считаться опасным. Удачи!

среда, ноября 14, 2007

Уязвимость Cross Server Scripting (XSS) в Macromedia Flash Player

Macromedia стало известно о уязвимости в безопасности. Когда содержимое Macromedia Flash (SWF) загружаеться с другого, отличного от текущего домена, создаеться возможность чтения и передачи данных, таких как куки и html.

Важным моментом безопасности на стороне клиента являеться то, что скрипту не разрешается проверять, изменять или иным образом взаимодействать с данными, которые поступают из web, кроме текущего домена. Когда Flash анимация находиться внутри HTML страниц они могут определять свой собственный код и подключать сторонние сценарии используя функцию ActionScript getURL() . Когда это происходит, нарушаеться кросс-доменная безопасность в отношении flash роликов и HTML страниц на которых они располагаються. Это означает что у авторов flash роликов появляется возможность взаимодействовать с HTML кодом текущей страницы через ролик, используя скрипты расположенные на других доменах. Эта проблема возникает с ActiveX версией Macromedia Flash Player для Internet Explorer и Netscape плагином для Netscape Navigator. Эта проблема может повлиять только сайты, содержащие страницы с flash роликами, подгружаемыми с других доменов и/или могут быть написаны лицами, не обладающими доверием владельцем веб-сайта. Такими сайтами могут являться каталоги flash роликов сторонних разработчиков или форумы с "подписями" / аватарами на основе Macromedia Flash.

Простое решение - хранить загруженные сторонними авторами ролики на отдельном хосте с отдельным доменным именем и размещать их на странице внутри обвертки (отдельное окно или iframe). Такой вариант хорош тем что flash ролик будет иметь доступ к телу iframe через который он загрузился. То есть имеется в виду что он будет находится как бы в песочнице, из которой на главный сайт он не как не выберется. Например, если ролик распологаеться на главной странице www.macromedia.com, песочницу следует разместить на external.macromedia.com и это предотвратило бы любой доступ к даным основной страницы www.macromedia. com. Это не очень удобно так как есть браузеры не поддерживающие этот тэг, либо тэг может блокироваться файрволом (например Outpost Firewall).

Второй способ заключаеться в том что Macromedia выпустила обновленный Macromedia Flash Player, который поддерживает простой способ контроля содержимого. Веб-страницы с flash анимацие могут принимать новый параметр HTML кода (тег PARAM Internet Explorer, тег EMBED для Netscape Navigator). Этот параметр называется "AllowScriptAccess". Он может иметь два возможных значения: "always" и "never".
  • AllowScriptAccess - "never", функция ActionScript getURL не сможет выполниться.
  • AllowScriptAccess - "always", функция ActionScript getURL сможет выполниться..
  • AllowScriptAccess не указана в HTML страницы, то значение по умолчанию "always".
За дополнительной информацией по вопросам безопасности в Macromedia посетите: http://www.macromedia.com/security.

Онлайн переводчики

Пара сайтов предоставляющие онлайн переводчики:

Онлайн сервис tadalist.com для организации списков дел

tadalist.com предоставляет онлайн сервис для ведени собственных списков дел. Основные моменты:
  • Чекбоксы и ajax. Когда закончите, просто поставьте галочку и на этом.
  • Списки любой тематики. Списки необходимых дел, любимой музыки, домашних дел...
  • Экспорт. Поделитесь списками с друзьями, коллегам или оставте их личными.
  • Широкая поддержка браузеров. работает в самых популярных браузерах (IE 6 / 7, Firefox 2, и Safari 2) на Mac, PC и iPhone.
Здесь можно зарегистрировать аккаунт.

Сжатие JavaScript кода

Онлайн компрессор js кода www.javascriptcompressor.com, еще не тестировался.