( PHP simple security codding )
Здравейте,
В този урок ще се опитам да дам леки насоки за размисъл относно PHP сигурността. В този аспект могат да се кажат много неща, но аз ще бъда лаконичен и максимално четлив. Най-важните неща, които съм се старал да спазвам са:
1. лесна четимост на кода
2. простота
3. лесна употреба
4. максимална защита с минимални усилия
В кода ще използвам някои функции на php, които няма нужда да познавате, защото съм ги представил в натурален вид, готов за употреба, без да обръщам внимание на подробностите. Целта ми е с един поглед да става ясно какво върши всеки ред. Например: strcmp(), md5(), setcookie(), $var=<<<...
Този код съм го писал за да защитава админ панела на мой реален сайт. Не съм имал проблеми досега с него.
Нека започнем кодирането с създаването на добра парола. В случая аз съм използвал md5 сумирането за да защитя паролата и логина си. Конкретно за този урок юзера е admin, а паролата demo. Прекалено лесни за кракване, нали! Но не това е страшното. Страшното е когато не внимавате и напише код който дава достъп до php кода ви, дори повикването на една картинка може да покаже сорса на даден файл. И така с лек скрипт за криптиране аз извличам криптираните стойности на логина и паролата:
<?php
echo md5("admin");
echo md5("demo");
?> |
Разбира се този файл не бива да присъства по никакъв начин на сървара ви. Достатъчно е да го стартирате веднъж под конзола или CommnadPromt за да извлечете стойностите. От там нататък ще трябва да помните паролата и юзернейма си за логването. (този файл може да се намери в приложения архив на края на урока под името config.php)
След като вече сме извлекли криптирани параметри за логване можем да ги вкараме директно в php файла за логване.
Нека видим сорса на целия файл:
<?php
$user="21232f297a57a5a743894a0e4a801fc3"; // криптиран юзернаме
$pass="fe01ce2a7fbac8fafaed7c982a04e229"; // криптираната парола
if ($_COOKIE["Cookie"]){
echo "Имате забрана за логване в сайта за 2 мин. Моля бъдете търпеливи и опитайте отново!";
exit;
}
$errMsg = '';
if (isset($_POST['num'])){
$counterror = $_POST['num'] + 1;
if ($counterror>=4){
setcookie("Cookie", "Забрана за 2 мин.", time()+120);
echo "Имате забрана за логване в сайта за 2 мин.";
$counterror=0;
exit;
}
}
if (isset($_POST['txtUserid'])) {
if (!strcmp(md5($_POST['txtUserid']),$user) && !strcmp(md5($_POST['txtUserpw']),$pass)) {
setcookie("Loging", "True", time()+3600);
header('Location: index.php');
exit;
} else {
$errMsg = "Грешен <b>Потребител</b> или <b>Парола</b>. До сега сте пробвали <b>" . $counterror . "</b> пъти да влезете в системата. При въвеждане на 4 грешен пореден път ще бъдете принудени да изчакате 2 мин. преди да опитате отново.";
}
}
$html1 = <<< ___HTML___
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Login</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<link rel="stylesheet" href="style.css" type="text/css"></style>
</head>
<body>
<div class="outer">
<div class="header">
</div>
<div class="body">
<div class="log">
<div class="loginer">
Login
</div><!-- затваряме тага class="loginer" -->
<div class="textlog">
Вие все още не сте се идентифицирали в системата. <br />Моля въведете своето потребителско име и парола за достъп:
<div class="form">
<form form action="loging.php" method="post" name="frmCampaign" id="frmCampaign">
Потребител:<br /><input type="text" id="txtUserid" name="txtUserid" size='14'><br />
Парола:<br /><input type="text" name="txtUserpw" id="txtUserpw" size='14'>
<input type="hidden" name="num" value=$counterror />
<button type="Submit" name="Submit" value="Submit" style="font-weight: normal; margin-left: 10px; padding: 0px 10px 0px 10px;" id="Submit">Вход в системата!</button>
</form>
</div><!-- затваряме тага class="form" -->
</div><!-- затваряме тага class="textlog" -->
</div><!-- затваряме тага class="log" -->
</div>
<div class="footer">
</div>
<div class="mess">$errMsg $bbb</div>
</div>
</body>
</html>
___HTML___;
echo $html1;
?> |
Мисля, че няма нужда от много коментари, но все пак нека да видим какво се случва.
if ($_COOKIE["Cookie"]) - С това проверяваме дали има сложена бисквитка за предозиране на опитите за логване. С това неутрализираме brutalforce атаките, разбира се ако атакуващия не трие бисквитките след всеки опит. Аз поне така бих направил, но мога да ви кажа, че доста кракери не го правят. Нека видим и редовете, които вкарват тази бисквитка:
if ($counterror>=4){
setcookie("Cookie", "Забрана за 2 мин.", time()+120); |
Ясно е предполагам. Ако има повече от 3 опита за влизане с грешни данни ще бъде вкарана бисквитка, която ще контролира забавянето.
По същия начин действа и реда по-долу:
setcookie("Loging", "True", time()+3600); |
С тази бисквитка казваме на браузера да пази логина 1 час(3600 секунди), след което ще се наложи ново логване.
Как сравняваме истинската парола с подадената от потребителя? С функцията strcmp(). Тази функция връща "0" ако двата стринга съвпадат. Ето и примера:
strcmp(md5($_POST['txtUserid']),$user) |
Тук виждаме още една функция - md5(). Това е функцията която ще кодира подадените данни и ако те съвпадат с кодираните данни в началото на файла тогава ще имаме достъп до следващата страница, а това ще ни го осигури бисквитката "Loging".
Какво ли следва. След като веднъж сме се логнали с правилните данни:
Потребител: admin
Парола: demo
Следва да видим как страницата на която биваме прехвърлени от реда
header('Location: index.php');
след коректен логинг ще провери дали наистина сме се логнали. Файла index.php ни проверява като гледа за:
if (!$_COOKIE["Loging"]=="True"){
header('Location: loging.php');
exit;
} |
Т.е. ако имаме различна бисквитка от Loging="True", то тогава ще ни върне в страницата за логин.
Разбира се, това задаване на бисквитки е доста опростено и едва ли може да се нарече сигурно. Можете да използвате и задаване на домейн и директория, но за сега и това ще ни свърши работа.
Относно графичния дизайн и JScript-a надявам се да нямате забележки. Постарал съм се цялото кодиране да е по стандартите, без таблици и както си трябва - ясно и просто. Постарал съм се и да отделя PHP кодирането от XHTML кодирането, затова и използвах перфектността на Perl от която PHP толкова се възползва:
Надявам се урока да ви е полезен! Отворен съм за критика и ще се радвам да коментираме каквото и да било по кода.
Демо може да се види тук:
http://www.nediko.info/phpsecurity/loging.php
Сорса на файловете може да се изтегли от тук:
http://www.nediko.info/phpsecurity/PHP-simple_security_by_PhrozenCrew.zip
Урока е написан лично от мен и материалите, които съм използвал са основно от референции за PHP.
Недялко Войняговски [PhrozenCrew]
19.08.2007
Та сега идва въпроса как да прехвърля проверките вместо да са с бисквитки да са със сесии: $_SESSION. Ако някой разбира от PHP нека пише в тази тема. Ще ми е интересна всяка критика или коментар по темата.
Благодаря!