ПЕРЕЛІК ДИСЦИПЛІН:
  • Адміністративне право
  • Арбітражний процес
  • Архітектура
  • Астрологія
  • Астрономія
  • Банківська справа
  • Безпека життєдіяльності
  • Біографії
  • Біологія
  • Біологія і хімія
  • Ботаніка та сільське гос-во
  • Бухгалтерський облік і аудит
  • Валютні відносини
  • Ветеринарія
  • Військова кафедра
  • Географія
  • Геодезія
  • Геологія
  • Етика
  • Держава і право
  • Цивільне право і процес
  • Діловодство
  • Гроші та кредит
  • Природничі науки
  • Журналістика
  • Екологія
  • Видавнича справа та поліграфія
  • Інвестиції
  • Іноземна мова
  • Інформатика
  • Інформатика, програмування
  • Юрист по наследству
  • Історичні особистості
  • Історія
  • Історія техніки
  • Кибернетика
  • Комунікації і зв'язок
  • Комп'ютерні науки
  • Косметологія
  • Короткий зміст творів
  • Криміналістика
  • Кримінологія
  • Криптология
  • Кулінарія
  • Культура і мистецтво
  • Культурологія
  • Російська література
  • Література і російська мова
  • Логіка
  • Логістика
  • Маркетинг
  • Математика
  • Медицина, здоров'я
  • Медичні науки
  • Міжнародне публічне право
  • Міжнародне приватне право
  • Міжнародні відносини
  • Менеджмент
  • Металургія
  • Москвоведение
  • Мовознавство
  • Музика
  • Муніципальне право
  • Податки, оподаткування
  •  
    Бесплатные рефераты
     

     

     

     

     

     

         
     
    Прийоми безпечного програмування веб-додатків на PHP
         

     

    Інформатика, програмування

    Прийоми безпечного програмування веб-додатків на PHP

    Дана стаття не претендує на роль всеосяжного керівництва на тему "як зробити так, щоб мене ніхто не поламав ". Так не буває. Єдина мета цієї статті - показати деякі використовувані мною прийоми для захисту веб - додатків типу WWW-чатів, гостьових книг, веб-форумів та інших програм подібного роду. Отже, давайте розглянемо деякі прийоми програмування на прикладі певної гостьової книги, написаної на PHP.

    Першої заповіддю веб-програміста, що бажає написати більш-менш захищене веб-додаток, має стати "Ніколи не вір даними, що надсилаються тобі користувачем ". Користувачі - це за визначенням такі злісні хакери, які тільки й шукають моменту, як би напхати у форми введення всякую дрянь типу PHP, JavaScript, SSI, викликів своїх моторошно хакерських скриптів і тому подібних жахливих речей. Тому перше, що необхідно зробити - це жорстоким чином відфільтрувати всі дані, надіслані користувачем.

    Припустимо, у нас в гостьовій книзі існує 3 форми введення: ім'я користувача, його e-mail і саме по собі тіло повідомлення. Перш за все, обмежимо кількість даних, переданих з форм введення чим-небудь на кшталт:

    На роль цієї захисту, звичайно, це претендувати не може - єдине призначення цього елементу - обмежити користувача від випадкового введення імені довше 20-ти символів. А для того, щоб у користувача не виникло спокуси завантажити документ з формами введення і підправити параметр maxlength, встановимо де-небудь на самому початку скрипта, що обробляє дані, перевірку змінної оточення web-сервера HTTP-REFERER:

    Тепер, якщо дані передані не з форм документа, що знаходиться на сервері www.myserver.com, хацкеру буде видано деморалізуючий повідомлення. Насправді, і це теж не може служити 100%-ою гарантією того, що дані ДЕЙСТВИТЕЛЬНО передані з нашого документа. Врешті-решт, мінлива HTTP_REFERER формується браузером, і ніхто не може перешкодити хакеру підправити код браузера, або просто зайти Телнет на 80-ый порт і сформувати свій запит. Так що подібний захист годиться тільки від Ну Зовсім неосвічених хакерів. Втім, за моїми спостереженнями, близько 80% відсотків зловмисників на цьому етапі зупиняються і далі не лізуть - чи то IQ не дозволяє, чи то просто лінь. Особисто я просто виніс цей фрагмент коду в окремий файл, і викликаю його звідусіль, звідки це можливо. Часу на звернення до змінної йде трохи - А береженого Бог береже.

    Наступним етапом стане горезвісна жорстка фільтрація переданих даних. Перш за все, не будемо довіряти змінної maxlength у формах введення і ручками поріжемо рядок:

    $ username = substr ($ username, 0,20);

    Не дамо користувачеві використовувати порожнє поле імені - просто так, щоб не давати писати анонімні повідомлення:

    if (empty ($ username)) (

    echo "invalid username";

    exit;

    )

    Заборонимо користувачеві використовувати в своєму імені будь-які символи, крім літер російського і латинського алфавіту, знака "_" (почерк), пробілу та цифр:

    if (preg_match ("/[^( w) | (x7F-xFF) | (s )]/",$ username)) (

    echo "invalid username";

    exit;

    )

    Я волію скрізь, де потрібно що-небудь більш складне, ніж перевірити наявність патерну в рядку або поміняти один патерн на інший, використовувати Перл-сумісні регулярні вирази (Perl-compatible Regular Expressions). Те ж саме можна робити і використовуючи стандартні PHP-шні ereg () і eregi (). Я не буду наводити тут ці приклади - це досить докладно описано в мануалі.

    Для поля введення адреси e-mail додамо в список дозволених символів знаки "@" І ".", Інакше користувач не зможе коректно ввести адресу. Зате приберемо російські букви і пробіл:

    if (preg_match ("/[^( w )|(@)|(.)]/",$ usermail)) (

    echo "invalid mail";

    exit;

    )

    Поле введення тексту ми не будемо піддавати таким жорстким репресіям - перебирати всі розділові знаки, які можна використовувати, просто лінь, тому обмежимося використанням функцій nl2br () і htmlspecialchars () - це не дасть ворогові понатикати в текст повідомлення html-тегів. Деякі розробники, напевно, скажуть: "а ми все-таки дуже хочемо, щоб користувачі _моглі_ вставляти теги ". Якщо дуже кортить - можна зробити якісь тегозаменітелі, типу "текст, оточений зірочками, буде висвітлений bold'ом. ". Але ніколи не слід дозволяти користувачам використання тегів, які мають на увазі підключення зовнішніх ресурсів - від тривіального до супернавороченого.

    Якось раз мене попросили потестувати html-чат. Першим же поміченим мною багом було саме дозвіл вставки картинок. З огляду на ще кілька особливостей будови чату, через кілька хвилин у мене був файл, в якому акуратно були перераховані IP-адреси, імена та паролі всіх присутніх у цей момент на чаті користувачів. Як? Та дуже просто - чату був посланий тег, в результаті чого браузери всіх користувачів, які були присутні в той момент на чаті, викликали скрипт myscript.pl з хоста myserver.com. (там не було людей, що сиділи під lynx'ом :-) ). А скрипт, перед тим як видати location на картинку, звалив мені в лог-файл половину змінних оточення - зокрема QUERY_STRING, REMOTE_ADDR та інших. Для кожного користувача. З вищезазначеним результатом.

    Тому моя думка - так, дозволити вставку html-тегів в чатах, форумах і гостьових книгах - це красиво, але гра не варта свічок - навряд чи користувачі підуть до Вас на книгу або в чат, знаючи, що їх IP може стати відомим першому зустрічному хакеру. Та й не тільки IP - можливості javascript'a я перераховувати не буду :-)

    Для примітивної гостьової книги перерахованих коштів вистачить, щоб зробити її більш-менш складною для злому. Однак для зручності, книги звичайно містять деякі можливості для модерування - як мінімум, можливість видалення повідомлень. Дозвіл, природно, вузькому (або не дуже) колу осіб. Подивимося, що можна зробити тут.

    Припустимо, вся система модерування книги також складається з двох частин - сторінки з списком повідомлень, де можна відзначати що підлягають видаленню повідомлення, і безпосередньо скрипта, що видаляє повідомлення. Назвемо їх відповідно admin1.php і admin2.php.

    Найпростіший і дуже надійний спосіб аутентікаціі користувача - розміщення скриптів в директорії, захищеної файлом. htaccess. Для подолання такого захисту потрібно вже не додаток ламати, а web-сервер. Що дещо складніше і вже, в усякому випадку, не вкладається в рамки теми цієї статті. Однак не завжди цей спосіб придатний до вживання - іноді буває треба проводити авторизацію засобами самого додатка.

    Перший, найпростіший спосіб - авторизація засобами HTTP - через код 401. При вигляді такого коду повернення, будь-який нормальний браузер висвітить віконце авторизації та попросить ввести логін і пароль. А надалі браузер при одержанні коду 401 буде намагатися підсунути web-серверу поточні для даного realm'а логін і пароль, і тільки в разі невдачі потребують повторної авторизації. Приклад коду для виведення вимоги на таку авторизацію є у всіх хрестоматіях і мануали:

    if (! isset ($ PHP_AUTH_USER)) (

    Header ( "WWW-Authenticate: Basic realm = "My Realm "");

    Header ( "HTTP/1.0 401 Unauthorized ");

    exit;

    )

    Розмістимо цей шматочок коду на початку скрипта admin1.php. Після його виконання, у нас будуть дві встановлені змінні $ PHP_AUTH_USER і PHP_AUTH_PW, в яких відповідно будуть лежати ім'я та пароль, введені користувачем. Їх можна, до Наприклад, перевірити по SQL-базі:

    *** Увага !!!***

    В наведеному нижче фрагменті коду свідомо допущена серйозна помилка в безпеки. Спробуйте знайти її самостійно.

    $ sql_statement = "select password from peoples where name = '$ PHP_AUTH_USER'";

    $ result = mysql ($ dbname, $ sql_statement);

    $ rpassword = mysql_result ($ result, 0, 'password');

    $ sql_statement = "select password ( '$ PHP_AUTH_PW')";

    $ result = mysql ($ dbname, $ sql_statement);

    $ password = mysql_result ($ result, 0);

    if ($ password! = $ rpassword) (

    Header ( "HTTP/1.0 401 Auth Required ");

    Header ( "WWW-authenticate: basic realm = "My Realm "");

    exit;

    )

    Згадана помилка, між іншим, дуже поширена серед початківців та неуважних програмістів. Колись я сам впіймався на цю вудку - на щастя, особливого шкоди це не принесло, не рахуючи надісланих хакером у стрічці новин декількох нецензурних фраз.

    Отже, розкриваю секрет: припустимо, хакер вводить свідомо неіснуюче ім'я користувача і порожній пароль. При цьому в результаті вибірки з бази мінлива $ rpassword приймає пусте значення. А алгоритм шифрування паролів за допомогою функції СУБД MySQL Password (), так само, втім, як і стандартний алгоритм Unix, при спробі шифрування порожнього пароля повертає порожнє значення. У підсумку - $ Password == $ rpassword, умова виконується і зломщик отримує доступ до захищеної частини програми. Лікується це або забороною пустих паролів, або, на мій погляд, більш правильний шлях - вставкою наступного фрагмента коду:

    if (mysql_numrows ($ result)! = 1) (

    Header ( "HTTP/1.0 401 Auth Required ");

    Header ( "WWW-authenticate: basic realm = "My Realm "");

    exit;

    )

    Те є - перевіркою наявності одного і тільки одного користувача в базі. Ні більше, ні менше.

    Точно таку ж перевірку на авторизацію варто вбудувати і в скрипт admin2.php. По ідеї, якщо користувач хороша людина - то він приходить до admin2.php через admin1.php, а отже, вже є авторизованим і ніяких повторних питань йому не буде - браузер нишком передасть пароль. Якщо ж ні - ну, тоді й посваритися не гріх. Скажімо, вивести ту ж фразу "hacker? He-he ...".

    До жаль, не завжди вдається скористатися алгоритмом авторизації через код 401 і доводиться виконувати її тільки засобами програми. У загальному випадку модель такої авторизації буде наступною:

    Користувач один раз авторизуйтеся за допомогою веб-форми і програми, яку перевіряє правильність імені та пароля.

    Решта скрипти захищеної частини програми яким-небудь чином перевіряють факт авторизованого користувача.

    Така модель називається сесійного - після проходження авторизації відкривається так звана "сесія", протягом якої користувач має доступ до захищеної частини системи. Сесія закрилася - доступ закривається. На цьому принципі, зокрема, будується більшість www-чатів: користувач може отримати доступ до чату тільки після того, як пройде процедуру входу. Основна складність даної схеми полягає в тому, що всі скрипти захищеної частини програми якимось чином повинні знати про те, що користувач, який посилає дані, успішно авторизуватися.

    Розглянемо кілька варіантів, як це можна зробити:

    Після авторизації всі скрипти захищеної частини викликаються з якимось прапорцем виду adminmode = 1. (Не треба сміятися - я сам таке бачив).

    Ясно, що будь-хто, кому відомий прапорець adminmode, може сам сформувати URL і зайти в режимі адміністрування. Крім того - немає можливості відрізнити одного користувача від іншого.

    Скрипт авторизації може яким-небудь чином передати ім'я користувача іншим скриптам. Поширена в багатьох www-чатах - для того, щоб відрізнити, де чиє повідомлення йде, поряд з формою типу text для введення повідомлення, пристроюється форма типу hidden, де вказується ім'я користувача. Теж ненадійно, тому що хакер може завантажити документ з формою до себе на диск і поміняти значення форми hidden. Деяку користь тут може принести вищезгадана перевірка HTTP_REFERER - але, як я вже говорив, жодних гарантій вона не дає.

    Визначення користувача по IP-адресою. У цьому випадку, після проходження авторизації, де-небудь в локальній базі даних (sql, dbm, та хоч в txt-файлі) зберігається поточний IP користувача, а всі скрипти захищеної частини дивляться в змінну REMOTE_ADDR і перевіряють, чи є такий адреса в базі. Якщо є - значить, авторизація була, якщо ні - "hacker? he-he ..." :-)

    Це більш надійний спосіб - не пройти авторизацію і отримати доступ вдасться лише в тому випадку, якщо з того ж IP сидить інший користувач, успішно авторизуватися. Однак, з огляду на поширеність проксі-серверів і IP-Masquerad'інга - це цілком реально.

    Єдиним, відомим мені простим і досить надійним способом верифікації особистості користувача є авторизація за допомогою random uid. Розглянемо її більш докладно.

    Після авторизації користувача скрипт, який провів авторизацію, генерує достатньо довге випадкове число:

    mt_srand ((double) microtime () * 1000000);

    $ uid = mt_rand (1,1000000);

    Це число він:

    а) заносить в локальний список авторизованих користувачів;

    б) Видає користувачеві.

    Користувач при кожному запиті, крім іншої інформації (повідомлення в чаті, або список повідомлень в гостьовій книзі), відправляє серверу свій uid. При цьому в документі з формами введення буде присутній, поряд з іншими формами, тег виду:

    Форма uid невидима для користувача, але вона передається скрипту захищеної частини додатки. Той звіряє переданий йому uid з uid'ом, що зберігаються в локальній базі і або виконує свою функцію, або ... "hacker? he-he ...".

    Єдине, що необхідно зробити за такої організації - періодично чистити локальний список uid'ов та/або зробити для користувача кнопку "вихід", при натисканні на яку локальний uid користувача зітреться з бази на сервері -- сесія закрита.

    Деякі програмісти використовують як uid не "одноразове" динамічно генерований число, а пароль користувача. Це допустимо, але це є "поганим тоном", оскільки пароль користувача звичайно не змінюється від сесії до сесії, а значить - хакер зможе сам відкривати сесії. Та ж сама модель може бути використана скрізь, де потрібна ідентифікація користувача - В чатах, веб-конференціях, електронних магазинах.

    В закінчення варто згадати і про таку корисної речі, як ведення логів. Якщо в кожну з описаних процедур вбудувати можливість занесення події в лог-файл із зазначенням IP-адреси потенційного зловмисника - то в разі реальної атаки обчислити хакера буде набагато простіше, оскільки хакери зазвичай пробують послідовно ускладнюються атаки. Для визначення IP-адреси бажано використовувати не тільки стандартну змінну REMOTE_ADDR, але і менш відому HTTP_X_FORWARDED_FOR, яка дозволяє визначити IP користувача, що знаходиться за проксі-сервером. Природно - якщо проксі це дозволяє.

    При ведення лог-файлів, необхідно пам'ятати, що доступ до них повинен бути тільки у Вас. Найкраще, якщо вони будуть розташовані за межами дерева каталогів, доступного через WWW. Якщо немає такої можливості - створіть окремий каталог для лог-файлів і закрийте туди доступ за допомогою. htaccess (Deny from all).

    Список літератури

    Для підготовки даної роботи були використані матеріали з сайту http://www.hostmake.ru/

         
     
         
    Реферат Банк
     
    Рефераты
     
    Бесплатные рефераты
     

     

     

     

     

     

     

     
     
     
      Все права защищены. Reff.net.ua - українські реферати ! DMCA.com Protection Status