| RSS



Меню

Bookmark and Share


Статистика
Ваш IP: 18.118.122.46
Вы используете: v





Сейчас на сайте:

Тех поддержка ->

Облако тэгов
ОС видио Tor Обратная сторона антенна 4.6 PHP Эксплоит Windows Server 2008 qip Virtual chroot kernel proc sysctl tune FreeBSD bridge Boot Disk Bluetooth GEO game directx Emulator Python Shell DDoS червь Conficker вирус троян Лаборатория Касперского пиратство apple iPhone ИТ-отрасль Щеголев Microsoft экономический кризис Twitter социальная сеть анонимность Лицензия Open Source ASP.NET MVC уязвимость MySQL база данных файлообмен закон франция пират Skype мобильный Deutsche Telekom Хакер киберпреступник Trend Micro кибератака Германия робот утечка данных персональные данные ноутбук интернет Китай цензура ядро Linux Торвальдс Windows Vista Acer Linux патент браузер Firefox Internet Explorer Opera Net Applications Safari Intel Linux Foundation Moblin Oracle патч банкомат кардер HSM IBM X-Force Cofee сша кибервойна Эстония Dell ИТ-специалист хакерские атаки Pirate Bay контроль кибербезопасность язык программирования The Pirate Bay Пиратская партия утечка информации приговор Mozilla Chrome безопасность Госдума СМИ Windows 8 Баллмер взлом Пентагон ботнет Украина Facebook Cisco cloud Windows XP нетбук торрент музыка биометрический nokia ФБР IP-адрес CIPAV Comcast sms RSA java Google CAPTCHA Symantec спам конфиденциальная информация инсайдер Perimetrix антивирус тест Anti-Malware Windows 7 операционная система Windows провайдер авторское право RapidShare UNIX свиной грипп шантаж дети EFF BluWiki копирайт экстремизм Panda Security cloud computing McAfee Cybercrime Response Unit Bottle Domains HTTPS ICANN студент шпионское ПО Норвегия школьник New York Times XSS YouTube Warner Music кибершпионаж КНДР Ubuntu свободное ПО AMD ATI касперский Россия РФ сервер хостинг фальшивый антивирус Comodo CA Wi-Fi D-Link суд пароль блог фишинг Одноклассники медведев контрафакт мошенник штраф Sony GPS по Gumblar JAVASCRIPT хакеры вредоносное ПО Yahoo ФАС компьютер Софт MPAA кибероружие PandaLabs Red Hat Минкомсвязи сбой ASUSTeK Computer мошенничество Доктор Веб ВКонтакте Cyber-Arc исходный код PCI DSS МВД фильтр порнография BREIN свобода слова Казахстан GEMA Autodesk сисадмин Gmail кредитная карта кибермошенник LiveJournal шифрование криптография Deep Purple банк нанотехнологии Wikipedia zero-day ColdFusion выборы кража данных DNS BIND Android BASIC атака Black Hat Mac OS X Click Forensics Clampi домен фсб Прокуратура Уголовное дело icq Barrelfish киберпреступность Sophos AT&T ошибка Electa Gamma Knife OpenBSD DARPA военные Сайт Visual Studio 2010 .NET Framework 4 Chrome OS электронная почта турция конференция спамер FTC полиция российская ОС Koobface Великобритания БЕЛОРУССИЯ грузия BSA Bittorrent облачные вычисления Azure Европа Dr.Web Билл Гейтс спецслужбы Cryzip Живой Журнал Royal Bank of Scotland смартфон Canonical Pwn2Own F-Secure Symbian Hotmail фильм

Главная » Статьи » Общие Статьи

Digest аутентификация в PHP
Digest vs Basic

При использовании метода Digest, как уже было сказано, пароль не передается, и его невозможно отснифить, однако есть и другая сторона проблемы. Для того, чтобы проверить пароль, сервер должен вычислить ответ и сравнить его с ответом клиента, следовательно, на сервере должен храниться пароль или зависящие от него данные, необходимые для прохождения аутентификации. Отсюда следует, что человек, получивший права на чтение аккаунтов (например, с помощью SQL-injection), сможет получить доступ к страницам, защищенным методом Digest. При использовании метода Basic возможно хранение хешей вместо паролей, что не дает поднять права, прочитав эти хеши (ниже мы увидим, что в Digest тоже могут храниться хеши, но такие, что их знания достаточно для вычисления ответа). Таким образом, перед нами дилемма: либо наш пароль отснифят, либо получат через web-уязвимость, которую кто-нибудь обязательно отыщет, потому что кто ищет, тот всегда найдет. Есть метод аутентификации без обоих этих недостатков - метод аутентификации на основе открытого ключа: для проверки нужен открытый ключ, а для прохождения проверки - секретный, однако в HTTP 1.1 такой метод не предусмотрен. RFC 2069 рекомендует использовать SSL, если защита так важна. Защищается только передача пароля, а контент не шифруется, так что нет смысла защищать этим методом ресурсы, откуда пользователь получает секретную информацию. Для них необходим SSL. А имеет смысл защищать, например, форум или заливку контента на сайт. Итак, если хостинг не поддерживает SSL, а аутентификация должна быть безопасной, то будем использовать Digest. В Apache предусмотрен модуль mod_digest. Для его использования в конфиге (или в .htaccess) пишем:

AuthType Digest
AuthUserFile <файл>
AuthName <название защищаемой области>
Require valid_user


Файлы пользователей создаются утилитой htdigest. Про mod_digest одно время появлялись сообщения, что он уязвим, так что, возможно, там еще какие-нибудь проблемы обнаружатся. Кроме того, когда я попытался его использовать у себя дома, получил ошибку 500 Server Internal Error. Кроме того, если добавление аккаунтов должно происходить автоматически, и их должно быть много, они должны храниться не в конфиге Апача, а в MySQL. Решение - использовать PHP. В PHP нет встроенной поддержки этого метода, поэтому его придется реализовать. Для этого необходимо изучить этот метод подробно. Сразу замечу, что приведенная в этой статье реализация работает только на Apache, так как полный доступ к заголовкам запроса (функция apache_request_headers) работает только в Apache, а на других серверах может отсутствовать. Нам же просто необходимо прочитать заголовок Authorization.

Описание метода

Полностью описание метода можно прочитать в RFC 2069, а если вкратце, то метод работает так. Когда сервер получает запрос, относящийся к защищенной области, он выдает ошибку 401 Authorization Required и заголовок с запросом аутентификации такого вида:

WWW-Authenticate: Digest realm="secure area", nonce="123456123456"

realm - это название защищенной области, а nonce - одноразовое значение. Есть еще необязательные параметры, которые мы обсуждать не будем. Клиент повторяет запрос, добавив к нему заголовок такого вида:

Authorization: Digest realm="secure area", username="123", uri="/index.php", nonce="123456123456", response="1234567890abcdef1234567890abcdef"

Параметр uri должен совпадать с URI в запросе, а response - это ответ, который вычисляется так:

response = H(H(A1) + ":" + nonce + ":" + H(A2))
H - хеш-функция, по умолчанию MD5
A1 = логин + ":" + realm + ":" + пароль
A2 = метод запроса + ":" + URI
метод запроса - это GET, POST и тд.

Как видим, A1 не зависит ни от запроса, ни от одноразового значения, поэтому на сервере может храниться не пароль, а H(A1). Именно так это реализовано в mod_digest в Apache. Однако этих же данных достаточно и клиенту. Злоумышленник, получив этот хеш, может вычислить ответ по приведенным выше формулам и сформировать HTTP-запрос, например, с помощью программы AccessDriver и ее инструмента HTTP Debugger. Подробнее этот процесс будет показан ниже. Сервер должен проверить, является ли одноразовое значение тем, которое было ранее выдано клиенту и не устарело ли оно. Если ответ соответствует параметру nonce, но значение этого параметра не актуально, выдается описанный выше ответ с кодом 401 с той лишь разницей, что в заголовок WWW-Authenticate добавляется параметр stale=true, указывающий, что в доступе отказано лишь по этой причине, и следует повторить попытку, не запрашивая у пользователя новый пароль. Это, имхо, неудобно, поскольку если такая ситуация возникнет при запросе POST или PUT с большим блоком данных, то клиенту придется передать все данные дважды. Во избежание этого стандартом предусмотрен заголовок Authentication-Info, в котором сервер может при ответе на успешный запрос сообщить клиенту следующее одноразовое значение. Синтаксис такой же, как у WWW-Authenticate, кроме того что nonce заменяется на nextnonce. Однако, судя по результатам моих экспериментов, Opera игнорирует этот заголовок. Другое решение: в соответствии с RFC 2068 (HTTP/1.1), сервер может ответить раньше, чем завершится запрос, чтобы клиент прервал ненужную передачу данных, но на Apache+PHP это не реализуется, поскольку скрипт начинает выполняться только после того, как Apache полностью получит и пропарсит запрос.

Хранение данных между запросами

В реализации метода challenge/response на PHP есть тонкий момент. Одноразовый параметр формируется и выдается клиенту в одном ответе, а проверяется уже в другом сеансе работы скрипта. То есть его необходимо сохранить от одного вызова скрипта до другого, и для этого придется  использовать файлы или БД. В моем примере используются файлы с именами, соответствующими одноразовым значениям, а в самих файлах записаны IP-адреса клиентов, которым они выданы. В примере не реализован сбор мусора: надо периодически удалять старые файлы.

Разбор кода

Этот скрипт проверяет только пароль, и работает независимо от
логина. В зависимости от успешности проверки выдаются простые ответы.

<?php

$realm = 'secure area'; //
Название защищаемой области
$pass = 'pass'; //
Пароль
$fileprefix = './'; //
Путь для файлов-меток, обозначающих валидность nonce

/* Сконструируем одноразовый параметр так, как рекомендуется в RFC2069, хотя можно и по-другому. Параметр, по рекомендации, должен зависеть от адреса клиента, текущего времени и секретной строки. */ 
$nonce = md5($_SERVER['REMOTE_ADDR'] . ':' . time() . ':MyCooolPrivateKey');

//
Получаем заголовки
$headers = apache_request_headers();

//
Флаг, который мы установим в TRUE при успешной проверке
$auth_success = FALSE;
$stale = "";

//
Если нет заголовка Authorization, то нечего и проверять
if (isset($headers['Authorization']))
{
$authorization = $headers['Authorization'];

/*
Пропарсим заголовок с помощью регулярного выражения. Заголовок содержит слово "Digest" и список пареметров вида param="value" или param=value через запятую. Это регулярное выражение соответствует одному такому параметру. */
preg_match_all('/(,|\s|^)(\w+)=("([^"]*)"|([\w\d]*))(,|$)/', 
$authorization, $matches, PREG_SET_ORDER);

/*
Теперь сформируем для удобства дальнейшей обработки массив, где ключи - названия параметров, а значения элементов массива - значения параметров. */ 
$auth_params = Array(); 
for ($i = 0; $i < count($matches); $i++)
{
$match = $matches[$i];

/*
Название всегда во второй группе скобок, в значениев зависимости от того, в кавычках оно или нет, может быть в 4-й или 5-й группе. Для групп скобок, попавших в нереализованную ветвь, в массиве пустая строка, поэтому можно просто сложить значения. */
$auth_params[$match[2]] = $match[4] . $match[5];
}

/*
Вычислим ответ, который соответствует логину, введенному пользователем, нашему паролю и одноразовому параметру, переданному пользователем. */
$a1 = $auth_params['username'] . ':' . $auth_params['realm'] . ':' . $pass;
$a2 = $_SERVER['REQUEST_METHOD'] . ':' . $_SERVER['REQUEST_URI'];
$resp = md5(md5($a1) . ':' . $auth_params['nonce'] . ':' . md5($a2));

//
Проверяем ответ.
if ($resp == $auth_params['response'])
{
//
Проверяем актуальность одноразового параметра
$fn = $fileprefix . $auth_params['nonce'];
if (@file_get_contents($fn) == $_SERVER['REMOTE_ADDR'])
{
unlink($fn); //
Больше этот параметр неактуален
$auth_success = TRUE; //
Аутентификация пройдена
} else
{
//
Одноразовый параметр неактуален
$stale = ", stale=true";

}
}


if ($auth_success)
{
print("<html><head><title>Digest auth test</title></head><body><pre>");

print("Successfully authenticated\n");
var_dump($auth_params);

print("</pre></body></html>");

} else
{
file_put_contents($fileprefix . $nonce, $_SERVER['REMOTE_ADDR']);

$proto = $_SERVER['SERVER_PROTOCOL'];
Header("$proto 401 Not Authorized");
Header("WWW-Authenticate: Digest realm=\"$realm\", nonce=\"$nonce\"$stale");

print("<html><head><title>Digest auth test</title></head><body><pre>");
print("You must authenticate with Digest method");
print("</pre></body></html>");
}

?>



Прохождение Digest Auth при известном H(A1)

Покажу на примере, как проходить проверку, если пароль неизвестен, но известен H(A1). Для этого, как уже было сказано, понадобится AccessDriver. Расчеты хешей я буду делать вызывая из командной строки PHP CLI. Защищенная страница пусть находится по адресу http://mrblack.local/auth1.php, а хеш H(A1) равен "a8fb5b2d780a7bf0782207a51a013f04".

Открываем AccessDriver->Tools->HTTP Debugger и вбиваем адрес "http://mrblack.local/auth1.php". Жмем "Connect". Получаем:

HTTP Header[0] = HTTP/1.1 401 Authorization Required
HTTP Header[1] = Date: Mon, 04 Jul 2005 08:09:17 GMT
HTTP Header[2] = Server: Apache/1.3.31 (Win32) PHP/5.0.2
HTTP Header[3] = X-Powered-By: PHP/5.0.2
HTTP Header[4] = WWW-Authenticate: Digest realm="secure area", nonce="5925bea78552224abda11bfe318a8a03"
HTTP Header[5] = Connection: close
HTTP Header[6] = Content-Type: text/html


Открываем консоль, переходим в папку с PHP и вбиваем такую команду:

php -r "print md5('a8fb5b2d780a7bf0782207a51a013f04: 5925bea78552224abda11bfe318a8a03: '.md5('GET:http://mrblack.local/auth1.php'));"

Получаем искомый Digest-ответ: c6d0af0db239d75c 3f59640a4896d096
Теперь в AccessDriver ставим галочку "Header Data", копируем в появившееся поле заголовки, которые были посланы в прошлом запросе, и дописываем к ним Authorization. Вот что получается:

GET http://mrblack.local/auth1.php HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*
Accept-Language: en-us,en;q=0.5
User-Agent: Mozilla compatible
Host: mrblack.local
Pragma: no-cache
Authorization: Digest username="mrblack", realm="secure area", nonce="5925bea78552224ab da11bfe318a8a03", uri="http://mrblack.local/auth1.php", response="c6d0af0db239d75c3f59 640a4896d096"


Жмем "Connect". Получаем результат:

HTTP Header[0] = HTTP/1.1 200 OK
HTTP Header[1] = Date: Mon, 04 Jul 2005 08:12:11 GMT
HTTP Header[2] = Server: Apache/1.3.31 (Win32) PHP/5.0.2
HTTP Header[3] = X-Powered-By: PHP/5.0.2
HTTP Header[4] = Connection: close
HTTP Header[5] = Content-Type: text/html


Авторизация пройдена, получен положительный ответ.
Категория: Общие Статьи | Добавил: aka_kludge (26.01.2009)
Просмотров: 2877 | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
    Главная      
...
На службе : дней

16:46
Обновить


Пользователи
aka_kludge
qwerty
LeadyTOR
aka_Atlantis
AdHErENt
mAss
Sissutr
hiss
DrBio
tHick

Поиск


Copyright tHR - TeAM 2024 г. admin: aka_kludge (ICQ:334449009) Moderator's: LeadyTOR, ... Яндекс.Метрика