Протокол защищенной HTTP-авторизации
Предлагаю реализацию протокола, идею которого предложил SATtva.
Ознакомиться с оригинальной идеей можно здесь "Защита HTTP-авторизации без SSL?".
Возможно, я частично продублирую изложенный в указанной статье материал. И все же это необходимо сделать для лучшего описания реализации протокола.
Так же есть реализация для "CMS Joomla!", доступна по адресу http://joomlaforum.ru/index.php/topic,11428.0.html
Условные обозначения
A – пользователь.
B – сервер.
u – идентификатор (имя) пользователя.
p – пароль пользователя.
p_h – хеш пароля.
p6 – хеш пароля хранимый в base.php.
ip1 – ip-адрес определенный сервером на 1 этапе протокола.
ip4 – ip-адрес определенный сервером на 4 этапе протокола.
k – секретный показатель, известный только B.
t1 – метка времени начала исполнения протокола.
H() – операция хеширования.
Описание сценариев и файлов
initialization.php – страница инициализации протокола.
form.html – форма для ввода имени имени и пароля.
webtoolkit.md5.js – java-скрипт клиентской стороны.
login.php – сценарий обработки формы для ввода имени и пароля.
validate.php – сценарий проверки имени и пароля по базе данных (base.php).
base.php – файл с зарегистрированными пользователями и их паролями (пароли в хешированном виде).
config.php – конфигурационный файл.
initialization.php
В момент открытия этой страницы пользователем A происходит инициализация протокола.
Еще до загрузки формы для ввода имени и пароля (form.html) этот сценарий проделывает следующие операции:
- открывает гостевую сессию со следующими параметрами:
- ip-адрес пользователя;
- временная метка начала протокола;
- генерирует r=H(k, t1, ip1);
Далее, когда все необходимые операции проведены, на клиентскую сторону передается java-скрипт webtoolkit.md5.js и форма form.html.
Форма, помимо полей для ввода и кнопки, содержит скрытое поле r_type, в которое записывается сгенерированное сервером r.
- передача на сторону клиента form.html и webtoolkit.md5.js;
Теперь A видит форму и может ввести u и p.
webtoolkit.md5.js
Загруженный клиенту webtoolkit.md5.js перехватывает событие нажатия кнопки.
- При нажатии кнопки берет значения полей p_type (пароль) и r_type.
- Вычисляет p_h=H(u).
Операция H(u) производится т.к. в базе паролей на сервере (base.php) хранятся не сами пароли, а их хешированные значения. Возможно это бесполезный "наворот", т.к. в этом случаи получается, что роль паролей играют их хешированные значения.
Т.е. пользователь мог бы вводить как пароль значение хеша (идентичного хранимому в base.php) и тогда операцию H(u) можно было бы не производить. Однако в этом случае все пароли должны были бы быть длинной 128 бит (если используется md5). (Дайджест любого сообщения прошедшего md5 имеет длину 128 бит.)
- Вычисляет h=H(r, p_h, p). Записывает h в r_type.
- Очищает поле в которое введен пароль p_type.
- Отправляет форму (возвращает событие).
Теперь начинается следующий этап протокола (в статье "Защита HTTP-авторизации без SSL?" 4 этап).
login.php
- сценарий проверяет, стартовала ли гостевая сессия, если да то исполнение сценария продолжается;
- берет из переменных сессии t1';
- определяет интервал между текущим временем и временем начала использования протокола. Если интервал не превышен, исполнение протокола продолжается;
- В отправленной форме сценарий получает u.
Сценарий login.php передает идентификатор пользователя (u) сценарию проверки имени и пароля по базе данных validate.php.
- Если validate.php возвращает не 0, то определяет ip4.
- Вычисляет h'=H(H(k, t1, ip4), u4, p6).
- Сравнивает значения h и h'
- Если значения совпали присваивает A идентификатор авторизованной сессии sid'.
initialization.php
<?php
/*
протокол авторизации MAS
*/
session_start();
/*Праметры неавторизованной гостевой сессии*/
$_SESSION['nominee']='guest'; //индентификатор неаторизованной гостевой сессии (sid)
$_SESSION['ip']=getenv ("REMOTE_ADDR"); //определение и запись ip-адреса пользователя (ip1)
$_SESSION['timestamp']=time(); //временная метка начала протокола (t1)
require "config.php"; //подключение конфигурациоонного файла
/*вычисление хеша*/
$r = md5($k.$_SESSION['timestamp'].$_SESSION['ip']);
/*Вывод формы и передача скрипта*/
require "form.html";
echo $r;
echo " | ";
echo md5('user1_password');
echo " | ";
echo $REMOTE_ADDR;
?>
form.html
login.php
<?php
/*
протокол авторизации MAS
*/
/*Проверка старотвала ли гостевая сессия*/
if (! isset( $_REQUEST[session_name()] ))
{
echo "сессия не стартовала";
exit;
}
session_start(); //стартуем сессию
require "config.php"; //подключаем конфигурационный файл
/*Проверка получен ли ответ в допустимом временном интервале*/
if ( (time() - $_SESSION['timestamp']) > $access_interval)
{
echo "превышен временной интервал ответа";
exit;
}
/*Извлечение хеша пароля из БД*/
require "validate.php"; //подключаем файл с функцией для извленчения хеша пароля
if (validate($name) == "NULL")
{
echo "пользователь с таким именем не зарегистрирован";
exit;
}
if ( md5( md5($k.$_SESSION['timestamp'].$_SESSION['ip']).$name.validate($name)) == $r_type)
{
echo "Вы авторизированы";
exit;
}
echo "Пароль не тот";
?>
webtoolkit.md5.js
validate.php
<?php
function validate($name){
require "base.php";
if (!isset($base[$name])){
return "NULL";
}
return $base[$name];
}
?>
config.php
<?php
$k = "server_secret"; //секретный показатель, известный только серверу
$access_interval = 60; //временной интервал в течении которого должен быть получен ответ, в секундах
?>
base.php
В оригинале статьи файл имел расширение .txt, что позволяло тривиально считать его содержимое, просто открыв его в браузере (если только файл не лежал за пределами публичной дериктории сервера).
SATtva (30/03/2007 13:16)
<?php
$base['user1'] = "b4ca6e90dcef1196a20930c2d9ecfbc0";
?>
Защита от компрометации базы – все те же MD5();
А, вот, зачем навешивать все это на html? Если, допустим, тем же сниффером перехватить пароль (пусть он и будет хешем MD5), то ничто не мешает любому пользоваться хешем, вместо пароля.
*и я не силен в JS* Правильно ли я понял, что webtoolkit.md5.js реализует ф-цию MD5?
комментариев: 11558 документов: 1036 редакций: 4118
1. сервер выдает клиенту нечто
2. клиент это нечто подписывает хэшем пароля
3. сервер сверяет подпись
получается что
для захвата объекта авторизации теперь достаточно знать хэш пароля
что приравнивается к хранению паролей в открытом виде
комментариев: 11558 документов: 1036 редакций: 4118
Не верно. "сопли" важная часть, нельзя их убирать.
Да, и + внизу корявенькая функция SendForm().
хранение ключей доступа в открытом виде, которое в данном случае косвенно НАВЯЗЫВАЕТСЯ как панацея от прослушки без ssl, подставляет сразу всю базу ключей.
в применении к сайту с sql-хранилищем банальная sql-inj ЛИБО банальный идиотизм админа сервера при наличии на сервере других пользователей (достаточно доступа на ЧТЕНИЕ чужих файлов) приведет к тому, что прав на ЧТЕНИЕ базы будет достаточно для полного контроля системы авторизации посторонним лицом БЕЗ каких-либо внешних признаков.
комментариев: 11558 документов: 1036 редакций: 4118
Это вы где такое прочитали?
Какое отношение имеет надёжность фронт-энда к криптопротоколу?
В БД нужно хранить Hash(Hash(pwd)), и взломщик с доступом на чтение пойдёт лесом.
Учите матчасть, осенью придёте на пересдачу.
А вообще действительно:
"В браузере введенный пароль хешируется и складывается со строкой переданной сервером (это строка каждый раз разная):
md5 ( md5(введенный_пароль) + строка_от_сервера) = хеш_пароля_и_строки_сервера"
Тогда тот кто знает md5(введенный_пароль) знать сам пароль вовсе и не должен, и это не помешает ему авторизоваться по данному протоколу...
Каким образом тогда сервер проверитчто от клиента пришла нужная строка?
комментариев: 11558 документов: 1036 редакций: 4118
Сервер дважды хэширует пароль, присланный клиентом, и сравнивает результат.
md5( md5(пароль) + строка_от_сервера)
комментариев: 11558 документов: 1036 редакций: 4118
и дальше проделавает манипуляции с этим хешем что бы получить строку и сравнить стой что прислал клиент
В изначальных измышлениях
"Борис самостоятельно вычисляет
h' = H( H(k, t1, ip4), u4, p6)"
где p6 – это пароль алисы, который Боб Хранит в открытом виде и он ему известен
комментариев: 11558 документов: 1036 редакций: 4118
неужели так трудно просто включить мозги?
вопрос: что хранит сервер?
ответ: хэш пароля
вопрос: что происходит в процессе авторизации?
ответ: сервер передает клиенту СЛУЧАЙНЫЙ набор данных, клиент подписывает эти данные КАКИМИ-ТО данными, полученными на основе ЧИСТОГО ПАРОЛЯ, после чего сервер сверяет подпись
вопрос: ЕСЛИ СЕРВЕР МОЖЕТ ПРОВЕРИТЬ ПРАВИЛЬНОСТЬ ПОДПИСИ ПРОИЗВОЛЬНЫХ ДАННЫХ, ОБЛАДАЯ ТОЛЬКО ХЭШЕМ ПАРОЛЯ, КАКИХ ДАННЫХ ДОСТАТОЧНО ДЛЯ ПРОХОЖДЕНИЯ АВТОРИЗАЦИИ?
ответ: ДОСТАТОЧНО ХЭША ПАРОЛЯ
ВЫВОД: ТАКОЙ СПОСОБ АВТОРИЗАЦИИ ЭКВИВАЛЕНТЕН ХРАНЕНИЮ ПАРОЛЕЙ В ОТКРЫТОМ ВИДЕ
в данном случае – непосредственное.
защищая единицы от ВЕРОЯТНОЙ прослушки, вся авторизационная база подвергается необоснованному риску.
mov al, шило
mov ah, мыло
xchg al, ah
пару дней сайт читаю и меня удивляет, что такие банальные вещи приходится разжевывать. неужели поголовно все от паранойи избавились?
комментариев: 11558 документов: 1036 редакций: 4118
Альтернативы помимо клиентских сертификатов X.509?
Ну так просвятите.