Dauntless auth php. HTTP Инсталиране на защита на страница с помощта на MySQL и PHP. Приложение. Изходни текстове на скриптове
За да изпратите съобщение „Изисква се удостоверяване“ до браузъра на клиента, което от своя страна ще доведе до диалогов прозорец за въвеждане на потребителско име и парола. След като клиентът въведе своето име и парола, скриптът ще бъде извикан отново, но с предварително дефинираните променливи PHP_AUTH_USER, PHP_AUTH_PW и AUTH_TYPE, които съответно съдържат потребителско име, парола и тип удостоверяване. Тези променливи могат да бъдат намерени в масивите $_SERVER и $HTTP_SERVER_VARS. В момента се поддържа само "Основно" удостоверяване. Можете също така да прочетете по-подробно описание на функцията заглавка () .
Пример за фрагмент от скрипт, който принуждава клиента да влезе, за да види страницата:
Пример за HTTP удостоверяване
if (!isset($_SERVER [ "PHP_AUTH_USER" ])) ( Здравейте ($_SERVER["PHP_AUTH_USER"]). Вие въведохте парола ($_SERVER["PHP_AUTH_PW"]).
заглавка ( "WWW-Authenticate: Basic realm="Моето царство"");
ехо „Текстът да бъде изпратен, ако
ако потребителят щракне върху бутона Отказ";
изход;
) иначе (
ехо"
ехо "
}
?>
Бележка за съвместимост:Бъдете особено внимателни, когато задавате HTTP заглавки. За да се гарантира максимална съвместимост с най-голям брой различни клиенти, думата "Basic" трябва да бъде изписана с главна буква "B", регионът (realm) трябва да бъде ограден в двойни (не единични!) кавички и точно един интервал трябва да предшества код 401 в заглавието HTTP/1.0 401 .
Вместо просто да показвате променливите PHP_AUTH_USER и PHP_AUTH_PW на екрана, може да се наложи да проверите дали са правилни. За целта използвайте заявката база данниили потърсете потребител в dbm файл.
Можете да наблюдавате функциите на браузъра Internet Explorer. Той е много взискателен към параметъра на предаваните заглавки. Спецификация на заглавката WWW-удостоверяванепреди да изпратите HTTP/1.0 статус 401 е малък трик.
От PHP 4.3.0, за да се предотврати някой да напише скрипт, който разкрива паролата на страница, която използва външно удостоверяване, променливите PHP_AUTH не се задават, ако тази страницаизползва външно удостоверяване и е настроен на защитен режим. Независимо от това, променливата REMOTE_USER може да се използва за удостоверяване на външно удостоверен потребител. Така че винаги можете да използвате променливата $_SERVER["REMOTE_USER"].
Забележка: PHP използва директивата AuthType, за да посочи дали се използва външно удостоверяване или не.
Трябва да се отбележи, че всичко по-горе не предотвратява кражбата на пароли за страници, изискващи оторизация, от всеки, който контролира страници без оторизация, разположени на същия сървър.
Както Netscape Navigator, така и Internet Explorer изчистват кеша за удостоверяване на текущия прозорец за дадената област, когато са получени от сървъра. Това може да се използва, за да принудите потребителя да излезе и да покаже отново диалоговия прозорец за потребителско име и парола. Някои разработчици използват това, за да ограничат влизанията във времето или да предоставят бутон за излизане.
Пример за HTTP удостоверяване с принудително въвеждане на нова двойка потребителско име/парола
функция authenticate()(
заглавка ( "WWW-Authenticate: Basic realm="Тестване на система за удостоверяване"");
заглавие ("HTTP/1.0 401 неупълномощен");
ехо „Трябва да въведете валидно потребителско име и парола за достъп до ресурса \n“;
изход;
}
Ако (!isset($_SERVER [ "PHP_AUTH_USER" ]) || Добре дошли: ($_SERVER["PHP_AUTH_USER"])
($_POST [ "SeenBefore" ] == 1 && $_POST [ "OldAuth" ] == $_SERVER [ "PHP_AUTH_USER" ])) (
удостоверяване ();
}
иначе(
ехо"
"
ехо „Предишно влизане: ($_REQUEST["OldAuth"])";
ехо ";
ехо "\н";
ехо "\н";
ехо "\н";
ехо "
}
?>
Това поведение не е дефинирано от стандартите за основно HTTP удостоверяване, така че не трябва да разчитате на него. Както показаха тестовете, браузърът Lynx не изчиства кеша за оторизация при получаване на статус 401 от сървъра и чрез последователно щракване върху „Назад“ и след това върху „Напред“ е възможно да се отвори такава страница, при условие че изискваната атрибутите за оторизация не са променени. Потребителят обаче може да натисне клавиша "_", за да изчисти кеша за удостоверяване.
Също така имайте предвид, че преди PHP 4.3.3, HTTP удостоверяването не работеше на сървъри, изпълняващи Microsoft IIS, ако PHP беше инсталиран като CGI модул, поради някои IIS ограничения. За да се постигне правилна работав PHP 4.3.3+, трябва да редактирате конфигурационната настройка на IIS, наречена „Сигурност на директорията“. Щракнете върху етикета „Редактиране“ и поставете отметка на опцията „Анонимен достъп“, всички други полета трябва да останат немаркирани.
Друго ограничение, ако използвате IIS чрез ISAPI: променливите PHP_AUTH_* не са дефинирани, но променливата HTTP_AUTHORIZATION е налична. Примерен код, който можете да използвате: list($user, $pw) = explode(":", base64_decode(substr($_SERVER["HTTP_AUTHORIZATION"], 6)));
Забележка относно IIS:За да може HTTP удостоверяването да работи правилно в IIS, опцията cgi.rfc2616_headers в PHP конфигурацията трябва да бъде зададена на 0 (стойността по подразбиране).
Внимание:В случай, че се използва защитен режим, UID на текущия скрипт ще бъде добавен към областта на частта на заглавката WWW-Authenticate.
<<< Назад | Съдържание | Напред >>> |
Ако имате още въпроси или нещо не е ясно - заповядайте при нас | |
|
Ограничаването на достъпа до някаква област на сайта обикновено изглежда така
монотонен: всеки потребител получава потребителско име и парола или той самият
ги избира и трябва да ги въведете, за да влезете в защитената част на сайта. От техническа гледна точка проверката на паролата използва
различни методи. Може да се използва HTML формуляр за въвеждане на потребителско име и парола.
В този случай паролата се изпраща на сървъра в чист текст в POST заявката.
Това е неприемливо, ако потребителят е в LAN, където е възможно
с помощта на снифър. За решаването на този проблем е разработен метод
хеш автентификация, при която паролата не се предава, а
предава се хеш низ, в зависимост от паролата, някои еднократно
параметър и, евентуално, от всякакви други параметри. Този метод е все още
се нарича предизвикателство/отговор, защото когато го използвате, клиентът
получава заявка с еднократен параметър и изпраща отговор, съдържащ хеша. На ниво протокол HTTP 1.1 е възможно удостоверяване с помощта на метода
Основно, което е нищо по-добра употреба HTML форми и Digest, които
ще разгледаме подробно.
Когато използвате метода Digest, както вече споменахме, паролата
не се предава и не може да се надуши, но има и друга страна
проблеми. За да провери паролата, сървърът трябва да изчисли
отговор и го сравнете с отговора на клиента, следователно сървърът трябва
съхранява паролата или зависещите от нея данни, необходими за
преминаване на удостоверяване. От това следва, че лице, получило права
за четене на акаунти (например чрез SQL-инжекция), ще можете да получите
достъп до страници, защитени с метода Digest. При използване на метода
Основно е възможно да се съхраняват хешове вместо пароли, което не позволява повдигане на права,
след като прочетете тези хешове (по-долу ще видим, че Digest може също да съхранява хешове,
но такива, че знанията им да са достатъчни за изчисляване на отговора). По този начин сме изправени пред дилема: или нашата парола ще бъде проучена,
или ще го получат чрез уеб уязвимост, която някой определено ще открие,
защото който търси винаги намира. Има ли метод за удостоверяване без
и двата недостатъка - методът за удостоверяване с публичен ключ:
имате нужда от публичен ключ за проверка и таен ключ за проверка,
обаче HTTP 1.1 не предоставя такъв метод. RFC 2069
препоръчва използването на SSL, ако сигурността е толкова важна. Само предаването на паролата е защитено и съдържанието не е криптирано, така че
че няма смисъл да се защитават ресурсите с този метод, откъдето потребителят
получава класифицирана информация. Те изискват SSL. И има смисъл
за защита например на форум или качване на съдържание на сайт. Така че, ако хостингът не поддържа SSL, и удостоверяването трябва
за да сме сигурни, тогава ще използваме Дайджест. Apache има модул mod_digest. За да го използвате
в конфигурацията (или в .htaccess) пишем:
AuthType Digest
AuthUserFile<файл>
AuthName<название защищаемой области>
Изискване valid_user
Потребителските файлове се създават от помощната програма
htdigest. Mod_digest е докладван за известно време като уязвим, така че,
може би все още има някои проблеми за намиране. Освен това, когато
Опитах се да го използвам у дома, получих грешка
500 Вътрешна грешка на сървъра. Освен това, ако трябва да се извърши добавяне на акаунти
автоматично и трябва да са много, трябва
да се съхранява не в конфигурацията на Apache, а в MySQL. Решение -
използвайте php. PHP няма вградена поддръжка за това.
метод, така че ще трябва да се приложи. За това е необходимо да се учи
този метод в детайли. Веднага отбелязвам, че статията, представена в тази статия
внедряването работи само на Apache от пълния достъп до заглавките
заявка (функция apache_request_headers) работи само в Apache, но на
други сървъри може да не са налични. Трябва само да четем
Заглавка за оторизация.
Описание на метода
Пълното описание на метода може да се намери в RFC 2069 и ако
накратко, методът работи така. Когато сървърът получи заявка, свързана със защитена зона,
извежда грешка 401 Изисква се оторизация и заглавка на заявка
удостоверяване като това:
WWW-Authenticate: Digest realm="сигурна зона", nonce="123456123456"
realm е името на защитената зона, а nonce е еднократният път
значение. Има още незадължителни параметри, които обсъждаме
ние няма. Клиентът повтаря заявката със заглавие като това:
Упълномощаване: Digest realm="сигурна зона", потребителско име="123", uri="/index.php", nonce="123456123456", response="1234567890abcdef1234567890abcdef"
Параметърът uri трябва да съвпада с URI в заявката и отговорът е
отговорът, който се изчислява по следния начин:
отговор = H(H(A1) + ":" + nonce + ":" + H(A2))
H - хеш функция, по подразбиране MD5
A1 = вход + ":" + област + ":" + парола
A2 = метод на заявка + ":" + URI
методът на заявка е GET, POST и т.н.
Както можете да видите, A1 не зависи нито от заявката, нито от еднократната
стойности, така че сървърът може да не съхранява паролата, но
H(A1). Ето как се изпълнява в mod_digest в Apache.
Същите данни обаче са достатъчни за клиента. Нападателят, като е получил
този хеш, може да изчисли отговора с горните формули и
генериране на HTTP заявка, например с помощта на програмата
AccessDriver и неговия HTTP инструмент
дебъгер. Този процес ще бъде показан по-подробно по-долу. Сървърът трябва да провери дали стойността е еднократна
този, който е бил издаден преди това на клиента и дали е просрочен.
Ако отговорът съвпада с параметъра nonce, но със стойността на този параметър
не е от значение, отговорът, описан по-горе с код 401, се издава само с
разликата е, че заглавката WWW-Authenticate се добавя с параметъра
stale=true, което показва, че достъпът е отказан само поради тази причина,
и трябва да опита отново, без да изисква от потребителя нова парола. Това, IMHO, е неудобно, защото ако възникне такава ситуация
когато иска POST или PUT с голям блок от данни, клиентът ще трябва
прехвърлете всички данни два пъти. За да се избегне това, стандартът предвижда
заглавката Authentication-Info, в която сървърът може, когато отговаря
успешна заявка информира клиента за следващия nonce.
Синтаксисът е същият като WWW-Authenticate, с изключение на nonce
се заменя със nextnonce. Въпреки това, съдейки по резултатите от моята
експерименти, Opera игнорира това заглавие. Друго решение: според
RFC 2068 (HTTP/1.1), сървърът МОЖЕ да отговори преди заявката да завърши,
така че клиентът да прекъсва ненужния трансфер на данни, но на Apache+PHP това
не се изпълнява, тъй като скриптът започва да се изпълнява едва след
как Apache ще получи напълно и анализира заявката.
Съхраняване на данни между заявките
Има един тънък момент в изпълнението на PHP на метода предизвикателство/отговор.
Еднократният параметър се формира и издава на клиента в един отговор и
проверени вече в друга сесия на скрипта.
Тоест, трябва да бъде запазен от едно извикване на скрипт в друго и за това трябва да го направите
използвайте файлове или база данни. Моят пример използва файлове с имена,
съответните еднократни стойности, а самите файлове съдържат
IP адресите на клиентите, на които са издадени. Колекцията не е реализирана в примера
боклук: трябва периодично да изтривате стари файлове.
Разбор на код
Този скрипт проверява само паролата и работи независимо от
Влизам. В зависимост от успеха на проверката се издават прости отговори.
$realm = "сигурна зона"; // Име на защитена територия
$pass = "пропуск"; // Парола
$fileprefix = "./"; // Път за файлове с етикети, указващи валидността на nonce
/*
Нека конструираме еднократен параметър, както се препоръчва в RFC2069, въпреки че е възможно по друг начин. Параметърът, според препоръката, трябва да зависи от адреса на клиента, текущото време и секретния низ. */
$nonce = md5($_SERVER["REMOTE_ADDR"] . ":" . time() . ":MyCooolPrivateKey");
// Получаване на заглавки
$headers = apache_request_headers();
// Флаг, който ще зададем на TRUE при успешно валидиране
$auth_success = FALSE;
$stale = "";
// Ако няма заглавка за оторизация, тогава няма какво да се проверява
if (isset($headers["Authorization"]))
{
$authorization = $headers["Authorization"];
/* Анализирайте заглавието с помощта на регулярен израз. Заглавието съдържа думата „Дайджест“ и списък
параметри във формата param="стойност" или param=стойност, разделени със запетаи. Този регулярен израз съответства на един такъв параметър. */
preg_match_all("/(,|\s|^)(\w+)=("([^"]*)"|([\w\d]*))(,|$)/",
$авторизация, $съответствия, PREG_SET_ORDER);
/* Сега, за удобство на по-нататъшната обработка, ще формираме масив, където ключовете са имената на параметрите, а стойностите на елементите на масива са
стойности на параметрите. */
$auth_params = масив();
за ($i = 0; $i< count($matches); $i++)
{
$match = $matchs[$i];
/* Името винаги е във втората група скоби, зависи дали е в кавички или не, може
бъдете в 4-та или 5-та група. За групи скоби уловени
към нереализиран клон, празен низ в масива,
така че можете просто да добавите стойностите.*/
$auth_params[$match] = $match. $съвпадение;
}
/* Изчислете отговора, който съвпада
данните за влизане, въведени от потребителя, нашата парола и еднократния параметър, подаден от потребителя.
*/
$a1 = $auth_params["потребителско име"] . ":". $auth_params["realms"] . ":". $pass;
$a2 = $_SERVER["REQUEST_METHOD"] . ":". $_SERVER["REQUEST_URI"];
$resp = md5(md5($a1) . ":" . $auth_params["nonce"] . ":" . md5($a2));
// Проверяваме отговора.
ако ($resp == $auth_params["отговор"])
{
//
Проверка на уместността на еднократен параметър
$fn = $fileprefix. $auth_params["nonce"];
if (@file_get_contents($fn) == $_SERVER["REMOTE_ADDR"])
{
прекратяване на връзката ($fn); //Тази опция вече не е актуална.
$auth_success = TRUE; //Удостоверяването премина
) друго
{
//
Еднократният параметър е без значение
$stale = ", stale=true";
}
}
}
ако ($auth_success)
{
печат ("
print("Успешно удостоверено\n");
var_dump($auth_params);
печат ("");
) друго
{
file_put_contents($fileprefix. $nonce, $_SERVER["REMOTE_ADDR"]);
$proto = $_SERVER["SERVER_PROTOCOL"];
Header("$proto 401 не е упълномощен");
Header("WWW-Authenticate: Digest realm=\"$realm\", nonce=\"$nonce\"$stale");
печат ("
");");
print("Трябва да се удостоверите с метода Digest");
печат ("
}
Преминаване на 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". Кликнете върху „Свързване“. Получаваме:
HTTP Header = HTTP/1.1 401 Изисква се оторизация
HTTP заглавка = дата: Mon, 04 Jul 2005 08:09:17 GMT
HTTP хедър = сървър: Apache/1.3.31 (Win32) PHP/5.0.2
HTTP Header=X-Powered-By: PHP/5.0.2
HTTP Header = WWW-Authenticate: Digest realm="сигурна зона", nonce="5925bea78552224abda11bfe318a8a03"
HTTP Header = Връзка: затваряне
HTTP Header = Content-Type: текст/html
Отворете конзолата, отидете в папката с PHP и въведете следната команда:
php -r "print md5("a8fb5b2d780a7bf0782207a51a013f04:
: ".md5("GET:http://mrblack.local/auth1.php"));"
Получаваме желания отговор на Digest: c6d0af0db239d75c
3f59640a4896d096
Сега в AccessDriver поставете отметка в квадратчето „Header Data“, копирайте го в появилото се
заглавките на полетата, които са били изпратени в предишната заявка, и добавете към тях
Упълномощаване. Ето какво се случва:
ВЗЕМЕТЕ http://mrblack.local/auth1.php HTTP/1.1
Приемам: изображение/gif, изображение/x-xbitmap, изображение/jpeg, изображение/pjpeg, приложение/x-shockwave-flash, */*
Език за приемане: en-us,en;q=0.5
Потребителски агент: съвместим с Mozilla
Хост: mrblack.local
Pragma: без кеш
Упълномощаване: Дайджест потребителско име="mrblack", realm="сигурна зона", nonce="5925bea78552224ab
da11bfe318a8a03", uri="http://mrblack.local/auth1.php", response="c6d0af0db239d75c3f59
640a4896d096"
Кликнете върху „Свързване“. Получаваме резултата:
Понякога е необходимо да се затвори от външен достъп PHPстраница, ако направите затворена зона на сайта. Може да е някакъв вид скрита информация за вашите клиенти или посетители на сайта, някакъв вид администраторски интерфейс за вас и т.н. Можете да измислите стотици различни задачи, които изискват ограничения за достъп.
Можете да затворите такава страница по няколко допълващи се начина:
- Защита с парола (вход/парола) с помощта на променливи $_SERVER["PHP_AUTH_USER"]и $_SERVER["PHP_AUTH_PW"].
- Защита от IPклиентски адрес с помощта на променлива $_SERVER["REMOTE_ADDR"].
- Защита от MACадрес в локални мрежи (в допълнение към защитата от IP).
Нека първо анализираме първия метод, който е основният. Тя ви позволява да затворите достъпа до страницата чрез потребителско име и парола, така че само хора, които знаят потребителското име и паролата, могат да получат достъп. Освен това те могат да бъдат разделени според този признак и съответно да дават различна информация за всеки. Реализира се чрез издаване на специални полета в заглавката на протокола HTTP. Нека създадем функция auth_send():
" ,"
Грешка при удостоверяване
" ,"Свържете се с вашия администратор за потребителско име и парола.
" ,""; изход; ); ?>Тази функция информира браузъра, че за достъп се изисква оторизация чрез потребителско име и парола. И също така въвежда страницата HTMLза потребителя.
" ,"
Добре дошли!
" ,"Вие сте влезли с потребителското име ",$auth_user," и паролата ",$auth_pass,".
" ,""; ?>Кодът за проверка на вход и парола в този случай не е твърде сложен, тъй като се прилага за един човек. Операционната логика е проста, ако няма променлива $_SERVER["PHP_AUTH_USER"]и $_SERVER["PHP_AUTH_PW"]или техните стойности не съвпадат с желаните, тогава извикайте функцията auth_send(). Не забравяйте, че се обажда в края изход, така че програмата се прекратява.
Следващото ниво на защита се реализира чрез филтриране IPсвързващ клиентски адрес. Разбира се, в интернет много доставчици издават IPадреси за известно време и е безполезно да се използва тази защита, но ако говорим за корпоративни локални мрежи, тогава тази проверка ще осигури допълнителна защита.
Вашият IP не беше намерен!!!"; изход; ); ?>
Тук на линията $allowed_ipsразделени с интервал IPадреси, до които е разрешен достъп. След това получаваме масив с помощта на експлодирам ()и направете търсене за адреса на клиента от $_SERVER["REMOTE_ADDR"]. Използвах функцията за търсене array_search(), тъй като е малко вероятно нейният код, внедрен в C, да работи малко по-бързо от това, което можем да напишем в PHPс помощта на цикли заили за всеки. Но тук бързината не е най-важното :)
И последната стъпка на защита е проверката MACадреси. Той принадлежи към категорията на параноичните и трябва да се използва, ако влизате от локалната мрежа и данните, които защитавате, са наистина много важни. Досега съм прилагал тази проверка само в системата linuxпоради относителната лекота на изпълнение. Но можете да опитате да го приложите за всяка друга платформа. Пишем функция:
Както линуксоидите вече разбраха, той се основава на ARPсистемна таблица, която може да бъде достъпна чрез файла /proc/net/arp. Функцията търси необходимите низове IPадрес и го върнете MACадрес:
Вашият IP=192.168.10.15 и MAC=00:04:31:E4:F8:37
В системата Windowsможе би има други начини за получаване MACпо-прости, но от тези, които наистина работят, това е заключението ARPсистемни таблици с командата:
C:\WINDOWS\>arp -a Интерфейс: 192.168.10.15 на интерфейс 0x1000003 IP адрес Тип физически адрес 192.168.10.1 00-50-22-b0-6a-aa динамичен 192.168.10.2 00-0f-38-68-e9- e8 динамичен 192.168.10.3 00-04-61-9e-26-09 динамичен 192.168.10.5 00-0f-38-6a-b1-18 динамичен
Можете сами да внедрите защита въз основа на този адрес, ако наистина имате нужда от нея :) Но не забравяйте, че ако имате неуправляемо оборудване във вашата мрежа без възможност за свързване MACадреси към порта, тази защита може да не работи, тъй като е възможно да се фалшифицират всички ваши идентификационни данни, използвани за защита (вход, парола, IP и MAC адрес).