Простий приклад використання PHP та AJAX. Тестове завдання для PHP розробника на випробувальному терміні Випробування success php


У списку десяти найпоширеніших видів атак за версією OWASP перші два місця займають атаки з впровадженням коду та XSS (міжсайтовий скриптинг). Вони йдуть пліч-о-пліч, тому що XSS, як і ряд інших видів нападів, залежить від успішності атак з впровадженням. Під цією назвою ховається цілий клас атак, під час яких у веб-додаток впроваджуються дані, щоб змусити його виконати або інтерпретувати шкідливий код так, як це потрібно зловмиснику. До таких атак відносяться, наприклад, XSS, використання SQL, використання заголовка, використання коду і повне розкриття шляхів (Full Path Disclosure). І це лише мала частина.


Атаки з впровадженням – страшилка для всіх програмістів. Вони найбільш поширені та успішні за рахунок різноманітності, масштабності та (іноді) складності захисту від них. Всім програмам потрібно брати звідкись дані. XSS та UI Redress зустрічаються особливо часто, тому я присвятив їм окремі розділи та виділив їх із загального класу.


OWASP пропонує наступне визначення атак із впровадженням:


Можливості застосування - типу SQL, OS і LDAP - виникають тоді, коли інтерпретатор отримує ненадійні дані у вигляді частини командного запиту. Шкідливі дані можуть обдурити інтерпретатор та змусити його виконати певні команди або звернутися до неавторизованих даних.

Впровадження SQL

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


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


Якщо атака пройшла успішно, зловмисник може маніпулювати SQL-запитом так, щоб той виконував базу даних операції, які не передбачені розробниками.


Подивіться на цей запит:


$db = new mysqli("localhost", "username", "password", "storedb"); $result = $db->query("SELECT * FROM transactions WHERE user_id = " . $_POST["user_id"]);

Тут цілий ряд косяків. По-перше, ми не перевіряли вміст POST-даних щодо коректності user_id . По-друге, ми дозволяємо ненадійному джерелу повідомляти, який user_id використовувати: атакуючий може підсунути будь-який коректний user_id . Можливо, він утримувався в прихованому полі форми, яку ми вважали безпечною, тому що її не можна редагувати (при цьому забувши, що атакуючі можуть вводити будь-які дані). По-третє, ми не заекранували user_id і не передали його у запит у вигляді параметра (bound parameter), що теж дозволяє атакуючому впроваджувати довільні рядки, які маніпулюватимуть SQL-запитом, враховуючи, що ми не змогли перевірити його в першу чергу.


Це три недогляди часто зустрічаються у веб-додатках.


Щодо довіри до бази даних, то уявіть, що ми шукали транзакції за допомогою поля user_name. Імена мають широке охоплення і можуть містити лапки. Припустимо, атакуючий зберіг впроваджене рядкове значення в одному з імен користувача. Коли ми знову використовуємо це значення в одному з наступних запитів, воно буде маніпулювати рядком запиту, якщо ми вважали базу надійним джерелом, не ізолювали і не обмежили скомпрометований запит.


Також звертайте увагу на інший фактор застосування SQL: постійне сховище не завжди потрібно тримати на сервері. HTML 5 підтримує використання БД за клієнта, куди можна відправляти запити з допомогою SQL і JavaScript. Для цього є два API: WebSQL та IndexedDB. В 2010 W3C не рекомендував вибирати WebSQL; він підтримується WebKit-браузерами, що використовують SQLite як бекенд. Швидше за все, підтримка збережеться для зворотної сумісності, навіть незважаючи на рекомендацію W3C. Як випливає з його назви, цей API приймає SQL-запити, а значить, може бути метою атак з використанням. IndexedDB - це нова альтернатива, база даних NoSQL (не вимагає використання SQL-запросів).

Приклади застосування SQL

Маніпулювання SQL-запитами може переслідувати такі цілі:

  1. Витоку даних.
  2. Розкриття інформації, що зберігається.
  3. Маніпулювання збереженою інформацією.
  4. Обхід авторизації.
  5. Впровадження SQL за клієнта.

Захист від застосування SQL

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

Перевірка

Я не втомлююся повторювати: всі дані, які не були явно створені у вихідному PHP-коді поточного запиту, ненадійні. Строго перевіряйте їх та відхиляйте все, що не пройшло перевірок. Не намагайтеся виправити дані, можна внести лише легкі, косметичні зміни у формат.


До частих помилок відноситься перевірка даних для подальшого поточного використання (наприклад, для відображення на екрані або обчислень) і відсутність перевірки полів бази даних, в якій буде збережена інформація.

Екранування

За допомогою розширення mysqli ви можете ізолювати всі дані, включені до SQL-запиту. Це робить функцію mysqli_real_escape_string(). Розширення pgsql для PostgresSQL пропонує функції pg_escape_bytea() , pg_escape_identifier() , pg_escape_literal() та pg_escape_string() . У розширенні mssql (Microsoft SQL Server) немає ізолюючих функцій, а підхід із застосуванням addslashes() неефективний - вам знадобиться кастомна функція .


Щоб ще більше ускладнити вам життя, скажу, що ви не маєте права на помилку при ізолюванні даних, що вводяться в запит. Один промах – і ви вразливі для атаки.


Підведемо підсумок. Екранування – не кращий варіантзахисту. До нього варто вдаватися у крайньому випадку. Воно може знадобитися, якщо бібліотека БД, що використовується для абстракції, допускає налаштування голих SQL-запитів або частин запиту без примусової прив'язки параметрів. В інших випадках краще взагалі уникати ізолювання. Цей підхід складний, провокує помилки і залежить від розширення бази даних.

Параметризовані запити (заздалегідь підготовлені вирази)

Параметризація, або прив'язка параметрів, це рекомендований спосіб створення SQL-запитів. Усе хороші бібліотекиБД застосовують його за умовчанням. Ось приклад використання розширення PDO для PHP:


if(ctype_digit($_POST["id"]) && is_int($_POST["id"])) ( $validatedId = $_POST["id"]; $pdo = new PDO("mysql:store.db") $stmt = $pdo->prepare("SELECT * FROM transactions WHERE user_id = :id"); $stmt->bindParam(":id", $validatedId, PDO::PARAM_INT); ; ) else ( / / відхилити значення id і повідомити користувача про помилку )

Метод bindParam() , доступний для виразів PDO, дозволяє прив'язувати параметри до "місць для вставки" (placeholders), представлених у заздалегідь підготовленому виразі. Цей метод приймає параметри основних типів даних, наприклад PDO::PARAM_INT , PDO::PARAM_BOOL , PDO::PARAM_LOB і PDO::PARAM_STR . Для PDO::PARAM_STR це робиться за замовчуванням, якщо не встановлено інше, так що запам'ятайте і для інших значень!


На відміну від ручного ізолювання, прив'язка параметрів (або інший інший метод, що використовується вашою бібліотекою БД) дозволить коректно ізолювати дані, що автоматично прив'язуються, так що вам не доведеться згадувати, яку функцію застосовувати. Також узгоджена прив'язка параметрів набагато надійніша, ніж спроба не забути, що потрібно ізолювати все вручну.

Реалізація принципу найменших привілеїв

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


Якщо у користувача широкі привілеї, то атакуючий може видаляти таблиці та міняти привілеї інших користувачів, виконуючи від імені нові впровадження SQL. Щоб цього не сталося, ніколи не звертайтеся до БД з веб-програми від імені root'а, адміністратора або іншого користувача з високими привілеями.


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


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

Впровадження коду (відоме як віддалене включення файлу, Remote File Inclusion)

Впровадження коду - це будь-які способи, які дозволяють атакуючому додавати у веб-додаток вихідний код з можливістю його інтерпретувати та виконувати. При цьому не йдеться про впровадження коду в клієнтську частину, наприклад JavaScript, тут застосовуються вже XSS-атаки.


Можна впровадити вихідний код безпосередньо з ненадійного джерела вхідних даних або змусити веб-програму завантажити його з локальної файлової системи або зовнішнього ресурсу на кшталт URL. Коли код впроваджується внаслідок включення зовнішнього джерела, це зазвичай називають віддаленим включенням файла (RFI), хоча саме собою RFI завжди призначено запровадження коду.


Основні причини впровадження коду:

  • обхід перевірки вхідних даних,
  • впровадження ненадійних вхідних даних у будь-який контекст, де вони будуть розцінені як PHP-код,
  • зламування безпеки репозиторіїв вихідного коду,
  • вимкнення попереджень про завантаження сторонніх бібліотек,
  • переконфігурація сервера, щоб він передавав у PHP-інтерпретатор файли, що не належать до PHP.

Останній пункт приділяє особливу увагу: у цьому випадку ненадійні користувачі можуть завантажити на сервер будь-які файли.

Приклади застосування коду

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

Увімкнення файлу

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


Параметр path також може бути вразливим для атак обходу каталогу (Directory Traversal) або віддаленого включення файлу. Використання path комбінацій символів../ або… дозволяє атакуючому переходити майже до будь-якого файлу, до якого має доступ PHP-процес. Заодно в конфігурації PHP за замовчуванням наведені вище функції приймають URL, якщо не вимкнено allow_url_include.

Перевірка

Функція PHP eval() приймає рядок PHP-коду.

Впровадження регулярних виразів

Функція PCRE (регулярний вираз, сумісний з Perl) preg_replace() в PHP допускає використання модифікатора e (PREG_REPLACE_EVAL). Це означає рядок, що замінює, який після підстановки буде вважатися PHP-кодом. І якщо в цьому рядку є ненадійні вхідні дані, то вони зможуть впровадити PHP-код, що виконується.

Дефектна логіка увімкнення файлу

Веб-застосунки включають файли, необхідні для обслуговування будь-яких запитів. Якщо скористатися дефектами логіки маршрутизації, управління залежностями, автозавантаження та інших процесів, то маніпуляція шляхом проходження запиту або його параметрами змусить сервер включити конкретні локальні файли. Оскільки веб-програма не розрахована на обробку таких маніпуляцій, наслідки можуть бути непередбачуваними. Наприклад, програма мимоволі засвітить маршрути, призначені тільки для використання в командному рядку. Або розкриє інші класи, конструктори яких виконують завдання ( краще класитак не проектувати, але це все ж таки зустрічається). Будь-який з цих сценаріїв може завадити операціям бекенда програми, що дозволить маніпулювати даними або провести DOS-атаку на ресурсоємні операції, які не мають на увазі прямого доступу.

Завдання впровадження коду

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

Defenses against Code Injection

Command Injection

Examples of Command Injection

Defenses against Command Injection

Використання лога (відомо як використання лог-файлу, Log File Injection)

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


Вразливість логів залежить від механізмів контролю за записом логів, і навіть від поводження з даними логів як із ненадійним джерелом під час перегляду та аналізі записів.


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


sprintf("Failed login attempt by %s", $username);

А якщо атакуючий використовує у формі ім'я «AdminnSuccessful login by Adminn»?


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


Тут вся суть у тому, що атакуючий здатний додавати в балку всілякі записи. Також можна впровадити XSS-вектор і навіть символи, що ускладнюють читання консолі записів лога.

Завдання використання лога

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


$username = "iamnothacker! at Mon Jan 01 00:00:00 +1000 2009"; sprintf("Failed login attempt by %s at %s", $username,)

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

Захист від застосування лога

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


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

Обхід шляху (відомий як обхід каталогу, Directory Traversal)

Атаки з обходом шляху - це спроби вплинути на операції читання або запису файлів у веб-додатку. Робиться це за допомогою застосування параметрів, які дозволяють маніпулювати шляхами файлів, залучених до операції бекенда. Так що атаки цього типу полегшують розкриття інформації (Information Disclosure) та локальне/віддалене використання файлів.


Такі атаки ми розглянемо окремо, але в основі їхньої успішності лежить саме обхід шляху. Оскільки описані нижче функції характерні саме для маніпулювання шляхами файлів, варто згадати, що багато PHP-функцій не приймають шляхи до файлів у звичному сенсі слова. Натомість функції на кшталт include() або file() приймають URI.


Виглядає абсолютно неприродно. Але це означає еквівалентність двох наступних функцій викликів, які використовують абсолютні шляхи (наприклад, не покладаючись на автозавантаження відносних шляхів).


include('/var/www/vendor/library/Class.php'); include('file:///var/www/vendor/library/Class.php');

Справа в тому, що відносний шлях обробляється на стороні (налаштування include_path у php.ini та доступних автозавантажувачах). У таких випадках PHP-функції особливо уразливі для багатьох форм маніпуляцій з параметрами, включаючи заміну схеми URI файлу (File URI Scheme Substitution), коли атакуючий може впровадити HTTP або FTP URI, якщо початок шляху файлу впроваджені ненадійні дані. Докладніше про це ми поговоримо в розділі, присвяченому атакам із віддаленим включенням файлів, а поки що зосередимося на обходах шляхів файлових систем.


Ця вразливість має на увазі зміну шляху для звернення до іншого файлу. Зазвичай це досягається за допомогою впровадження серії послідовностей../ в аргумент, який потім приєднується до функцій або повністю вставляється у функції на кшталт include() , require() , file_get_contents() і навіть менш підозрілі (для когось) функції типу DOMDocument: :load().


За допомогою послідовності../ атакуючий змушує систему повернутися до батьківського каталогу. Так що шлях /var/www/public/../vendor насправді веде до /var/www/vendor . Послідовність../ після /public повертає нас до батьківського каталогу, тобто в /var/www. Таким чином зловмисник отримує доступ до файлів, розташованих поза каталогом /public, доступним з веб-сервера.


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

Examples of Path Traversal

Defenses against Path Traversal

Впровадження XML

Незважаючи на використання JSON як полегшений засіб передачі даних між сервером і клієнтом, XML залишається популярною альтернативою, API веб-сервісів часто підтримує її паралельно з JSON. Також XML застосовується для обміну даними, що використовують XML-схеми: RSS, Atom, SOAP та RDF тощо.


XML всюдисущий: його можна знайти в серверах веб-додатків, в браузерах (як кращий формат для запитів та відгуків XMLHttpRequest) та браузерних розширеннях. Враховуючи його поширеність і обробку за замовчуванням таким популярним парсером, як libxml2, використовуваним PHP в DOM і розширення SimpleXML і XMLReader, XML став метою для атак з впровадженням. Коли браузер бере активну участь у XML-обміні, необхідно враховувати, що за допомогою XSS авторизовані користувачі можуть передавати XML-запити, створені насправді зловмисниками.

Впровадження зовнішньої XML-сутності (XXE)

Такі атаки існують через те, що бібліотеки парсингу XML часто підтримують використання посилань на кастомні сутності. Ви познайомитеся зі стандартним XML-доповненням сутностей, його застосовують для представлення спеціальних символіврозмітки на кшталт > , < і '. XML дозволяє розширювати набір стандартних сутностей, визначаючи за допомогою самого документа XML кастомні сутності. Їх можна визначати, безпосередньо включаючи опціональний DOCTYPE. Розширене значення, що представляється ними, може посилатися на зовнішній ресурс, який повинен бути включений. XXE-атаки стали популярні завдяки можливості простого XML зберігати кастомні посилання, які можуть збільшуватися за рахунок вмісту зовнішніх ресурсів. За звичайних умов ненадійні вхідні дані ніколи не повинні непередбачено взаємодіяти з нашою системою. А більшість програмістів XXE майже однозначно не передбачають XXE-атаки, що викликає особливе занепокоєння.


Давайте, наприклад, визначимо нову кастомну суть harmless:


]>

XML-документ із цим визначенням тепер може посилатися на сутність скрізь, де взагалі дозволені сутності:


]> This result is

Коли XML-парсер на кшталт PHP DOM інтерпретуватиме цей XML, він опрацює цю кастомну сутність відразу ж, як завантажиться документ. Тому при запиті відповідного тексту поверне:


This result is completely harmless


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


]> &harmless;

Залежно від вмісту запитаного локального файлудані можуть використовуватись при розширенні сутності. А потім розширений контент може бути вилучений з XML-парсера і включений у вихідні дані веб-програми для аналізу атакуючим. Наприклад, для розкриття інформації. Вилучений файл буде інтерпретований як XML, хоча спеціальних символів, що ініціюють таке інтерпретування, немає. Це обмежує масштаб розкриття вмісту локального файлу. Якщо файл інтерпретований як XML, але не містить коректного XML, то, напевно, ми отримаємо помилку, що запобігатиме розкриттю вмісту. Однак у PHP доступний акуратний трюк, що дозволяє обійти обмеження масштабу, тому віддалені HTTP-запити впливають на веб-додаток, навіть якщо повернена відповідь не можна передати назад атакуючому.


У PHP часто зустрічаються три методи парсингу та використання XML: PHP DOM, SimpleXML та XMLReader. Всі вони використовують розширення libxml2, підтримка зовнішніх сутностей включена за умовчанням. Як наслідок, PHP за замовчуванням має вразливість до XXE-атак, яку дуже легко пропустити при розгляді безпеки веб-програми або бібліотеки, що використовує XML.


Не забувайте також, що XHTML та HTML 5 можуть бути серіалізовані як коректний XML. Отже, деякі XHTML-сторінки або XML-серіалізований HTML 5 можуть парситися як XML, з використанням DOMDocument::loadXML() замість DOMDocument::loadHTML() . Таке застосування XML-парсера теж уразливе до застосування зовнішніх XML-сутностей. Пам'ятайте, що libxml2 поки що навіть не розпізнає HTML 5 DOCTYPE, тому не може перевірити його як XHTML DOCTYPES.

Приклади застосування зовнішніх XML-сутностей

Вміст файлу та розкриття інформації

Вище ми розглянули приклад розкриття інформації, зазначивши, що кастомна сутність XML може посилатися на зовнішній файл.


]> &harmless;

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


]> &harmless;

PHP дає доступ до обгортки у вигляді URI, одного з протоколів, що приймається стандартними функціями роботи з файловою системою: file_get_contents() , require() , require_once() , file() , copy() та багатьма іншими. Обертання PHP підтримує ряд фільтрів, які можна застосовувати до конкретного ресурсу, щоб результати поверталися викликом функції. У цьому прикладі ми застосовуємо до цільового файлу, який хочемо прочитати, фільтр convert.base-64-encode .


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

Обхід контролю доступу

Доступ контролюється різними способами. Оскільки XXE-атаки проводяться на бекенді веб-програми, використовувати сесію поточного користувача не вдасться. Але атакуючий все ще може обійти контроль доступу до бекенд за допомогою запитів від локального сервера. Розглянемо такий примітивний контроль доступу:


if (isset($_SERVER["HTTP_CLIENT_IP"]) || isset($_SERVER["HTTP_X_FORWARDED_FOR"]) || !in_array(@$_SERVER["REMOTE_ADDR"], array("127.0.0.1", "::1 ",))) ( header("HTTP/1.0 403 Forbidden"); exit("Ви не можете використовувати цей файл."); )

Цей шматок PHP, як і безліч йому подібних, обмежує доступ до певних PHP-файлів на локальному сервері, тобто localhost. Однак XXE-атака на фронтенді програми дає атакувальному точні облікові дані, необхідні для обходу цього контролю доступу, тому що всі HTTP-запити XML-парсер будуть робитися з localhost.


]> &harmless;

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

DOS-атаки

Для DOS-атак можна використати майже все, що диктує споживання серверних ресурсів. За допомогою впровадження зовнішньої XML-сутності атакуючий отримує можливість робити довільні HTTP-запити, які за відповідних умов виснажують серверні ресурси.


Пізніше ми поговоримо про інші потенційні DOS-застосування XXE-атак з погляду розширення XML-сутностей.

Захист від застосування зовнішніх XML-сутностей

Такі атаки дуже популярні, тому вас здивує, як просто від них захиститися. Оскільки DOM, SimpleXML і XMLReader спираються на libxml2, можна лише застосувати функцію libxml_disable_entity_loader() , що відключає використання зовнішніх сутностей. Правда, це не відключить кастомні сутності, заздалегідь визначені в DOCTYPE, тому що вони не використовують зовнішні ресурси, що вимагають виконання HTTP-запиту або операції в файловій системі.


$oldValue = libxml_disable_entity_loader(true); $dom = new DOMDocument(); $dom->loadXML($xml); libxml_disable_entity_loader($oldValue);

Це потрібно зробити для всіх операцій, які передбачають завантаження XML з рядкових, файлів або видалених URI.


Там, де додатку ніколи не потрібні зовнішні сутності, а також для більшості його запитів, можна взагалі відключити завантаження зовнішніх ресурсів на більш глобальному рівні. У більшості випадків це набагато краще для визначення всіх «точок» завантаження XML, враховуючи, що багато бібліотек мають уроджені вразливості до XXE-атак:


libxml_disable_entity_loader(true);

Тільки не забувайте повертати значення TRUE після кожного тимчасового увімкнення завантаження зовнішніх ресурсів. Вона може знадобитися для таких нешкідливих завдань, як перетворення Docbook XML на HTML, коли застосування XSL-стилів залежить від зовнішніх сутностей.


Однак функція, що відключає libxml2 - не панацея. Проаналізуйте інші розширення та PHP-бібліотеки, які парсят або якось ще обробляють XML, щоб знайти їх «вимикачі» застосування зовнішніх сутностей.


Якщо це зробити неможливо, додатково перевірте, чи оголошує XML-документ DOCTYPE. Якщо і якщо при цьому зовнішні сутності відключені, то просто викиньте XML-документ, заборонивши ненадійний XML-доступ до потенційно вразливого парсера і журналюючи його як ймовірну атаку. Це необхідний крок, тому що інших ознак не буде – ані помилок, ані винятків. Встановіть цю перевірку у звичайну валідацію вхідних даних. Але цей метод далеко не ідеальний, так що вкрай рекомендується докорінно вирішити проблему зовнішніх сутностей.


/** * Attempt a quickie detection */ $collapsedXML = preg_replace("/[:space:]/", "", $xml); if(preg_match("/

Також бажано відразу видаляти підозрілі дані, які можуть бути результатом атаки. Навіщо працювати з чимось, що виглядає небезпечним? Так що комбінація з двох вищеописаних заходів дозволяє заздалегідь ігнорувати шкідливі дані, одночасно захищаючи себе на випадок, якщо видалити дані не вийде (наприклад, якщо це сторонні бібліотеки). Видаляти дані доводиться і тому, що libxml_disable_entity_loader() відключає не всі кастомні сутності, а ті, що посилаються на зовнішні ресурси. Що залишає можливість атаки з розширенням XML-сутності (XML Entity Expansion).

Розширення XML-сутності

Ця атака багато в чому аналогічна атаці з використанням XML-сутності. Але в даному випадку робиться акцент на DOS-атаку зі спробою виснажити ресурси серверного оточення цільової програми. У DOCTYPE XML створюється визначення кастомної сутності, яка, наприклад, може генерувати у пам'яті XML-структури набагато більшого розміру проти вихідної. Це призводить до заповнення пам'яті та зниження ефективності роботи сервера. Така атака застосовується і до XML-серіалізації HTML 5 у разі, якщо останній не розпізнаний розширенням libxml2 як HTML.

Приклади розширення XML-сутності

Є кілька способів розширити кастомні XML-сутності для бажаного виснаження серверних ресурсів.

Загальне розширення сутності

Інша назва – «атака квадратичного збільшення». Кастомна сутність визначається як дуже довгого рядка. Якщо багаторазово використовувати її в документі, вона щоразу збільшується, в результаті XML-структура споживає набагато більше оперативної пам'яті в порівнянні з вихідним XML.


]> Now include lots of times to expand the in-memory size of this XML structure Keep it going... ...

Якщо знайти баланс між розміром рядка кастомної сутності та кількістю використання в тілі документа, можна створити такий XML-файл або рядок, при розширенні яких вдасться прогнозувати споживання серверної пам'яті. Якщо заповнити її такими питаннями, що повторюються, то вийде справжня DOS-атака. Недолік підходу: початковий XML також має бути досить великим, оскільки споживання пам'яті залежить від простого ефекту множення.

Рекурсивне розширення сутності

У той час як загальне розширення вимагає використання спочатку великого XML, рекурсивне забезпечує набагато більший коефіцієнт збільшення. Цей метод заснований на експонентному розкладанні (resolve) наборів маленьких сутностей таким чином, щоб вони істотно збільшувалися в розмірах. Цілком логічно, що цей метод часто називають XML-бомбою та атакою мільярда смішків (Billion Laughs Attack).


]> Explode in 3...2...1...

Бомба XML не вимагає великого XML, розмір якого іноді може бути обмежений програмою. Атака призводить до того, що пам'ять забивається текстом, розмір якого в 2^100 рази перевищує розмір вихідного значення сутності - . Справжня бомба!

Віддалене розширення сутності

Обидві вищеописані атаки використовують локально певні сутності XML DTD. Але атакуючий може визначити сутність і віддалено, якщо XML-парсер може робити зовнішні HTTP-запити. Як ми бачили в описі XXE (використання зовнішньої XML-сутності), цю можливість потрібно заблокувати як базовий захід захисту. Таким чином, захищаючись від XXE, ми захищаємось і від цього виду атаки.


У будь-якому випадку: для цієї атаки XML-парсер повинен робити зовнішні HTTP-запити для отримання розширеного значення відповідних сутностей. У свою чергу вони самостійно визначать нові зовнішні сутності, до яких парсеру доведеться зробити додаткові HTTP-запити. Таким чином, парочка запитів, що безневинно виглядають, швидко вийде з-під контролю, збільшуючи навантаження на доступні серверні ресурси, що в результаті може призвести до рекурсивного розширення сутностей і погіршити ситуацію.


]> 3..2..1...&cascade

Вищенаведений код також дозволяє провести DOS-атаку хитрішим способом: зовнішні запити повинні бути адаптовані для локальної програми або будь-якої іншої програми, що спільно використовує серверні ресурси. В результаті система атакуватиме сама себе: спроби розкласти (resolve) зовнішні сутності за допомогою XML-парсера спровокують відправлення безлічі запитів до локальних додатків та споживання маси серверних ресурсів. Ця атака може використовуватися для посилення ефекту XXE-атаки, для подальшого виконання DOS-атаки.

Захист від розширення XML-сутностей

Методи захисту ті самі, що й у випадку з одиночними XXE-атаками. Потрібно відключити розкладання кастомних XML-сутностей у локальні файли, а також функції; відключити зовнішні HTTP-запити за допомогою наступної функції, що глобально застосовується до всіх XML-розширень PHP, заснованих на використанні libxml2.


libxml_disable_entity_loader(true);


Однак PHP не реалізовано очевидний засіб повного відключення визначення кастомних сутностей за допомогою XML DTD за допомогою DOCTYPE. PHP визначає константу LIBXML_NOENT , також є суспільна властивість DOMDocument::$substituteEntities , але вони не покращують ситуацію. Схоже, доведеться використовувати власні набори обхідних засобів захисту.


libxml2 має вроджену нетерпимість до рекурсивного розкладання сутностей, тому ваш лог помилок прикраситься, як новорічна ялинка. Тому ми не маємо особливої ​​потреби у реалізації специфічного захисту від рекурсивних сутностей; хоча потрібно щось зробити на той випадок, якщо libxml2 відбудеться рецидив.


Таким чином, первинна нова загроза – це грубі підходи з XML-бомбою чи загальним розширенням сутності. Для цих атак не потрібні локальні або дистанційні системні виклики, не потрібна рекурсія сутностей. По суті, єдиний засіб захисту – видалення чи очищення XML, якщо він містить DOCTYPE. Видаляти безпечніше, якщо нам не потрібно використовувати DOCTYPE і якщо ми не отримали його з довіреного надійного джерела, тобто через перевірене HTTPS-з'єднання. А якщо ні, то потрібно створювати самопальну логіку, тому що PHP не дає нам працюючої опції для відключення DTD. Якщо припустити, що ви можете викликати libxml_disable_entity_loader(TRUE) , то наступний код буде безпечним, тому що сутність не розшириться, поки немає доступу до зараженого розширення значення вузла (node ​​value). А під час цієї перевірки такого не станеться.


$dom = новий DOMDocument; $dom->loadXML($xml); foreach ($dom->childNodes as $child) ( if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) ​​( throw new \InvalidArgumentException("Invalid XML: Detected use of illegal DOCTYPE"); ) )

Звичайно, потрібно ще підстрахуватися і привласнити libxml_disable_entity_loader значення TRUE, щоб посилання на зовнішні сутності були розкладені (resolve) при первинному завантаженні XML. Це може бути єдино можливим захистом там, де XML-парсер не залежить від libxml2, якщо цей парсер не має вичерпного набору опцій управління розкладанням сутностей.


Якщо ви маєте намір використовувати SimpleXML, майте на увазі, що за допомогою функції simplexml_import_dom() ви можете імпортувати перевірений об'єкт DOMDocument.

7.4K
У цій статті я опишу створення та надсилання форми AJAX. Після цього ми зможемо розглянути реалізацію анімації за допомогою animate.css, валідації даних за допомогою JavaScript.

На момент написання цієї статті Bootstrap 3.3.5 є актуальною версією фреймворку. Для цієї статті ми використовуємо складання Bootstrap за замовчуванням (з 12 стовпцями). Коли ви будете виконувати завдання цієї статті, переконайтеся, що використовуєте останні сніпети та структуру коду, описані в документації Bootstrap.

Структура файлів та папок

Ми створимо кореневий каталог і додамо до нього наступні файли та папки:

Bootstrap-Form:


Нам потрібно буде підключити деякі бібліотеки front-end:
  • Bootstrap;
  • jQuery.

З урахуванням цих бібліотек структура файлів виглядатиме так:

Bootstrap-Form:

Створення форми

Відкрийте файл index.html та скопіюйте в нього наступну базову структуру AJAX форми зворотнього зв'язку:

Contact form using Bootstrap 3.3.4 "

Send me a message

Це базовий шаблон HTML , який ми будемо додавати вміст форми. Ми підключили всі необхідні файли CSS та JavaScript. Зверніть увагу, що для цього конкретного прикладу нам не потрібний bootstrap.js .

Ми включили мета-тег viewport для медіа-запитів у рамках Bootstrap. JavaScript був розміщений у нижній частині файлу, щоб в першу чергу оброблявся основний код.

У тезі body ми включили div з класом col-sm-6 col-sm-offset-3. Це означає, що в межах вікна перегляду sm (маленького) і поверх нього хочемо відобразити стовпець шириною 50% ( максимальна кількість стовпців 12). Клас col-sm-offset-3 задає відступ зліва на 25%.

Таким чином, створюється макет, який займає половину доступного простору та відцентрований по горизонталі. Після цього ми включили h3 і далі йде основа форми. Переконайтеся, що ви застосували до форми ідентифікатор, щоб пізніше прикріпити до неї подію для надсилання форми AJAX JQuery :

Без боротьби не буває перемоги

Це все поля введення та кнопки, з якими взаємодіятиме користувач. Початковий div з присвоєним класом row - це класичний синтаксис Bootstrap, що є горизонтальним угрупуванням елементів col. Стовпці у межах Bootstrap створюють відступи чи прогалини. Видаляючи їх, можна домогтися, щоб рядок рівномірно вписувався у контейнер.

Ми створили два стовпці з класом col-sm-6 (50%), який будемо використовувати, щоб відокремити верхню частину форми. В межах першого стовпця col-sm-6 ми створили label та поля для імені та електронної пошти. Кожен з них містить label з відповідним атрибутом for тому мітка пов'язана з відповідним полем.

Кожен з цих стовпців включає form-group, який семантично групує мітки, створюючи невеликий відступ знизу:

Друкарня

Bootstrap дозволяє використовувати класи для H1-H6. Вони допомагають задати стилі вбудованих елементів без додавання додаткових полів або створення блоків елементів super AJAX contact form. Ми використовували клас для H4, щоб задати стиль label і зробити їх більшими.

Клас form-control застосовується для кожного елемента введення, щоб займати всю ширину контейнера (ширина 100% ). Цей клас також додає різні стилі, які дозволяють створити елемент форми, що легко читається ( великий розмір, чіткі краї та ін.).

Після цих колонок ми включаємо тіло повідомлення. Ми обертаємо його в form-group і застосовуємо ті ж стилі, що і для міток та текстових полів.

Заклик до дії

Створимо submit button. Bootstrap містить класи для різних кнопок та їх станів. Ми вирішили використати кнопку “ success” (btn-success), яка, за замовчуванням, є зеленою.

Також потрібно застосувати базовий клас btn, щоб скинути основні параметри кнопки ( рамка, відступ, вирівнювання тексту, розмір шрифту). Ми застосували клас btn-lg, який створює велику кнопку, а потім клас pull-right, який задає обтікання кнопки зліва.

Після кнопки ми включили div з ідентифікатором #msgSubmit та застосували такі класи: « h3 text-center hidden“. Клас h3 допомагає створити більший заголовок, text-center встановлює вирівнювання тексту центром, а hidden - задає display: none і visible: hidden :

Додавання функціоналу надсилання даних

Ми створили базову Bootstrap JQuery AJAX form, але вона ще нічого не робить. Наш наступний крок - створити функцію, яка приймає дані, що вводяться Користувачами, і відправляє їх асинхронно в PHP.

Відкрийте файл scripts.js та скопіюйте в нього наступний код:

$("#contactForm").submit(function(event)( // скасовує відправлення даних форми event.preventDefault(); submitForm(); ));

Цей фрагмент коду JQuery, який прослуховує функції надсилання даних #contactForm ( як зазначено раніше). Перед цією функцією ми обробляємо змінну event, яка зберігає дію надсилання даних форми для функції.

event.preventDeafult() зупиняє надсилання даних форми при оновленні сторінки без вибору дії у формі. І насамкінець цей код запитує функцію submitForm(); :

function submitForm()( // Ініціюємо змінну з вмістом форми var name = $("#name").val(); var email = $("#email").val(); var message = $("#message ").val(); $.ajax(( type: "POST", URL: "php/form-process.php", data: "name=" + name + "&email=" + email + "&message=" + message, success: function(text)( if (text == "success")( formSuccess(); ) ));) function formSuccess()( $("#msgSubmit").removeClass("hidden"); )

Три ініційовані змінні захоплюють значення кожного з полів введення форми і передають їх змінної JavaScript для подальшого використання.

Ми ініціюємо об'єкт AJAX всередині JQueryі встановлюємо параметри для post, адресу розміщення файлу PHP, дані, які ми хочемо відправити, та функцію зворотного виклику. Дані включають всі три змінні з відповідним id . Функція зворотного виклику викликається, коли об'єкт AJAX успішно отримав інформацію від скрипта PHP . Функція захоплює повернутий текст і перевіряє, чи дорівнює він рядку “ success”. Якщо так, то запускається фінальна функція formSuccess .

Вона видаляє прихований клас із DIV #msgSubmit, який ми застосували раніше, виводячи таким чином текст.

Підключення до функції PHP Mail

Тепер потрібно написати скрипт, який отримуватиме дані з форми AJAX , і надсилатиме контент через функцію PHP Mail . Відкрийте файл process.php і додайте до нього наступний код:

Нам необхідно зберегти змінні, які хочемо використовувати. З поштової функції можна отримати три вхідних змінних і присвоїти їм ті ж імена в PHP. Змінна $EmailTo є адресою електронної пошти, яку можна встановити у скрипті. $Subject — це рядок, який описує тему електронного листа.

Тіло листа створюється довільно з додаванням трьох створених змінних. Спочатку ми задаємо текст опису, наприклад, « Name:«, потім йде змінна, а потім перенесення на новий рядок (/n). Ті ж дії ми повторюємо, пов'язуючи всі дані зі змінною $body.

Щоб надіслати електронний лист, ми приєднуємо його до поштової функції. Надавши значення змінної $success , ми задаємо адресу електронної пошти, на яку буде надіслано лист, тему листа, тіло та адресу електронної пошти відправника.

Щоб розпочати процес надсилання електронною поштою, потрібно викликати його в операторі if . Таким чином, можна перевірити, чи були дані форми успішно надані чи ні. Якщо функція Mail повертає “ true”, скрипт повертає “ success”, якщо функція видає помилку, повертається “ invalid”.

Цей результат буде повертатися об'єкту AJAX і оброблятися на стороні клієнта. Переваги AJAX у тому, що це робиться в асинхронному режимі за клієнта. Це дозволяє користувачеві продовжувати взаємодіяти з сайтом під час відправлення даних AJAX form:

Наводимо блиск

Тепер ми зосередимося на забезпеченні зворотного зв'язку з користувачем за допомогою різних додаткових функцій, які можна увімкнути. Зокрема, ми розглянемо зворотний зв'язок форми за допомогою обробки помилок як на стороні клієнта, так і на стороні сервера.

Також для валідації форми ми використовуємо деякі інструменти:

  • Animate.css: ;
  • Bootstrap Validator.

Додайте їх у проект, як ми раніше робили з Bootstrap та JQuery . Ці інструменти допоможуть забезпечити зворотний зв'язок із користувачем після того, як він надіслав дані.

Структура проекту тепер має виглядати так:

Валідація форми

Почнемо з установки валідатора після введення даних форми зворотного зв'язку AJAX PHP. Перейдіть до файлу scripts.js і відредагуйте перший фрагмент коду, який викликає функцію SubmitForm() після надсилання даних форм.
Його потрібно змінити так:

$("#contactForm").validator().on("submit", function (event) ( if (event.isDefaultPrevented()) ( // обробка помилки форми... ) else ( // все гаразд! event .preventDefault(); submitForm(); ) ));

Цей новий фрагмент коду перевіряє, чи знайшов Bootstrap Validator проблеми та чи зупинив роботу коду. Якщо ні, ми продовжуємо виконання дій у стандартному режимі. Нам все ще потрібно виключити дію за умовчанням ( перезавантаження сторінки без заповнення форми) зі сценарію представлення даних форми.

Тепер, якщо ми натиснемо кнопку відправки даних форми, не заповнивши всі поля, порожні виділятимуться червоним кольором:


У процесі додавання валідації ми заблокували рідну валідацію HTML5. Можна додати до валідації додатковий контекст, увімкнувши повідомлення про помилки. Bootstrap Validator має зручну функцію, що дозволяє відобразити повідомлення про помилку кожного з полів. Щоб додати їх, потрібно доповнити розмітку HTML.

Всередині кожної form-group під полем введення даних потрібно розмістити наступний HTML-код:

Як приклад нижче наведено додатковий div , що додається полям імені та адреси електронної пошти:

Тепер при повторному надсиланні даних AJAX JQuery форми буде виводитися повідомлення про помилку, якщо поля форми не були заповнені: “ Please fill in this field.”. Додавши data-атрибут для даних, що вводяться під назвою “ data-error”, можна ввімкнути повідомлення користувача про помилку.

Наприклад:

Додавання анімації зворотного зв'язку

Ми додали функціонал індикації незаповнених полів форми. Але було б непогано додати до форми додаткову анімацію та кілька повідомлень, які дадуть користувачеві знати, що відбувається. В даний час при успішному надсиланні даних форми з'являється повідомлення « Message Submitted!«, але як щодо помилок?

Щоб задіяти існуючий код, ми змінимо повідомлення про успішне надсилання даних. Насамперед видалимо текст « Message Submitted!» з HTML-розмітки і залишимо порожній div :

Тепер потрібно створити нову функцію для обробки статусу повідомлення. Додайте цю функцію до нижньої частини файлу scripts.js :

function submitMSG(valid, msg)( var msgClasses; if(valid)( msgClasses = "h3 text-center tada animated text-success"; ) else ( msgClasses = "h3 text-center text-danger"; ) $("# msgSubmit").removeClass().addClass(msgClasses).text(msg); )

Ця функція приймає два аргументи. valid буде логічною змінною: якщо її значення true , буде виводитися повідомлення про успішне надсилання даних. Якщо false буде виводитися повідомлення про помилку. msg — це повідомлення, яке ми виводитимемо на екран у блоці div .

Ця функція перевіряє, чи маємо ми справу з повідомленням про успішне надсилання даних або з повідомленням про помилку. Це робиться через перевірку значення змінної valid. У будь-якому випадку вона встановлює змінну з відповідними класами CSS ( нам необхідно повторно включити h3 і text-center , тому що ми видалимо їх).

Примітка: Для класу повідомлення про успішне надсилання даних ми використовуємо деякі класи animate.css . При успішному надсиланні даних AJAX JQuery contact form програватиметься анімація tada.

Нарешті, функція видаляє всі класи #msgSubmit ( щоб уникнути перетину класів), а потім встановлює пріоритетні класи та додає текст повідомлення до div .

Всередині ініціалізації валідатора на початку розділу ми оновлюємо код, щоб додати виклик наступної функції всередині оператора if , коли він дає значення true :

submitMSG(false, "Did you fill in the form properly?");

Тепер, якщо ви не заповнили всі поля, буде виводитись повідомлення про помилку “ Did you fill in the form properly?»

Останній крок для цієї нової функції submitMSG – викликати її, коли дані форми відправлені успішно. Обновіть функцію formSuccess() таким чином:

$("#contactForm").reset(); submitMSG(true, "Message Submitted!")

Ми хочемо скинути форму та очистити значення, коли викликаємо функцію submitMSG , як зазначено вище з повідомленням про успішне надсилання даних. Тепер при успішному надсиланні даних форми має відображатись відповідне повідомлення з анімацією animate.css tada :

Потрусьмося

Давайте додамо до всієї форми анімацію помилки, універсальна анімація "тряски" має підійти!

Створіть відразу після функції formSuccess() нову та назвіть її formError() :

function formError()( $("#contactForm").removeClass().addClass("shake animated").one("webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend", function()( $(this).removeClass(); )) ;)

Ця функція використовує підхід, описаний на демонстраційній сторінці animate.css , який дозволяє додати анімацію до елемента, а потім знову викликати її.

Анімація CSS має неприємну особливість: відсутність можливості повторного програвання, навіть якщо видалити та повторно додати клас. Ця функція допомагає скинути класи кінця анімації, що дає змогу повторно додати їх. Коли користувач натискає кнопку "Надіслати", не заповнивши всі поля AJAX форми зворотного зв'язку, ми програємо анімацію shake . І якщо він знову не заповнить усі поля, потрібно знову програти цю анімацію.

Можна викликати цю функцію formError() вище за функцію submitMSG() , яку ми створили для повідомлення про помилку. Наприклад, так:

formError(); submitMSG(false, "Did you fill in the form properly?");

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

Більше валідації

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

Нам потрібно відкрити файл process.php і внести до нього необхідні зміни, щоб перевірити заповнення всіх полів. Ми створимо змінну $errorMSG , за допомогою якої перехоплюватимемо повідомлення про помилки, а потім включимо додаткову перевірку $_POST :

Цей PHP-код перевіряє, чи існують порожні поля AJAX form , перед тим як встановити їх дані як відповідні змінні ( замінює існуючі в коді змінні з $_POST). Якщо поля порожні, ми задаємо спільне повідомлення, щоб відправити назад клієнту.

У відповідь на вихідний виклик AJAX нам потрібно надіслати повідомлення про помилку, яке відображатиметься у браузері. Для цього відредагуйте оператор if, який ми створили раніше в нижній частині коду PHP:

Через оператор if ми перевіряємо, чи є змінна $errorMSG порожньою («») , а також статус вбудованої функції Mail, яку ми використовували для змінної $success. За умови else ми включили додаткову перевірку, чи є помилка результатом збою $success . Якщо так, то відправляємо назад повідомлення “ Something went wrong:“. Інакше виводимо повідомлення, яке було скомпільовано, коли ми проводили перевірку порожніх полів.

І останній етап – потрібно прийняти нове повідомлення в AJAX та вивести його у формі. Нам потрібно оновити об'єкт AJAX у файлі scripts.js таким чином:

$.ajax(( type: "POST", URL: "php/form-process.php", data: "name=" + name + "&email=" + email + "&message=" + message, success: function( text)( if (text == "success")( formSuccess(); ) else ( formError(); submitMSG(false,text); ) ) )));

Ми тільки що оновили умови else, яке перевіряє відповідність text == success. У else ми викликаємо функцію formError() , яка застосовує анімацію «тряски» і запитуємо у функції submitMSG() текст, повернутий із PHP .

Висновок

Зайдіть на Github, щоб переглянути весь код повністю. Тепер форма зворотнього зв'язку AJAX PHPнадає користувачеві інформацію про те, які з полів не заповнив. Ми виводимо контекстні повідомлення, засновані на статусі та повідомленні, що повертається від PHP. Також реалізували додатковий рівень перевірки на стороні сервера для тих користувачів, які намагаються обійти front-end валідацію.

Сподіваюся, вам сподобалася ця стаття. Будь ласка, залишайте у коментарях свої питання та відгуки.

Дана публікація є перекладом статті « Building a Bootstrap Contact Form Using PHP and AJAX» , підготовленою дружньою командою проекту

Це доступний та безпечний спосіб платити за товари та послуги через інтернет. Додайте обробник цієї системи у ваш інтернет-магазин і приймайте платежі без зволікань.

Оновлений протокол Яндекс.Гроші 3.0 дозволяє використовувати різні типи оплати:

  • Власне Яндекс гроші;
  • Банківські карти;
  • Платежі через термінали;
  • Мобільні платежі
Крім того, процедура підключення магазинів, створених на платформі 1С-Бітрікс: Управління сайтом,до Янедекс.Грошам значно спрощено. Вам потрібно залишити заявку на сайті Яндекс.Гроші (у коментарі вкажіть, що у вас сайт на з версією протоколу 3.0.) та заповніть спрощену анкету (що складається всього з 3-х полів).

Для підключення нового протоколу Яндекс.Гроші в інтернет-магазині на платформі 1С-Бітрікс потрібно створити нову платіжну систему та обрати обробник

Перевірте, чи ваш сайт відповідає за протоколом https. Це обов'язкова умова прийому платежів за протоколом Янедекс.Гроші 3.0.

Можна використовувати самопідписаний SSL-сертифікат або нашу віртуальну машину, де вже все налаштовано.

Далі вкажіть Ідентифікатор магазину в ЦПП, Номер вітрини магазину в ЦПП, які ви повинні отримати від Яндекса під час укладання договору, та Пароль магазину (shopPassword)з анкети магазину для Яндекса

Для кожного типу відплати необхідно буде створити свій обробник і вибрати тип оплати.

Щоб протестувати оплату, потрібно поставити значення “Y” у полі Тестовий режим. При надсиланні заявки на підключення протоколу Яндекс.Гроші 3.0 вам прийде спеціальне посилання, використовуючи яке ви поповнити баланс вашого гаманця для тесту на 1000 рублів.

У налаштуваннях модуля Інтернет-магазин можна перевизначити шляхи до сторінок із повідомленням про успішну оплату або помилку.

Усе. Налаштування закінчено. Користуйтесь

Клієнтам, які підключили попередню версію Яндекс.Денег (1.6), не обов'язково переходити на версію 3.0. Тобто. обидві версії підтримуються як Яндекс.Грошами, так і 1С-Бітрікс: Управління сайтом. АЛЕ у версію 1.6 не додається можливість використовувати оплату, крім Яндекс.Гроші. Нові клієнти цієї платіжної системи підключаються за протоколом 3.0.

У постачання продукту 1С-Бітрікс: Управління сайтомобробник Яндекс.Денег (3.0) вийде до 14.0.0 версії модуля Інтернет-магазин (sale). До виходу цього оновлення (припустимо, наприкінці місяця вийде в альфі) обробник можна запросити через Технічну підтримку.

До базової функціональності слід додати такі можливості:
  • Користувач може використовувати наступні HTML теги у повідомленнях:
  • Повинна бути перевірка на закриття тегів, код має бути валідним XHTML
  • Гостьова книга. JavaScript та AJAX.

    До базової функціональності слід додати такі можливості:
    • Валідація даних, що вводяться на стороні сервера і клієнта
    • Функція попереднього перегляду та додавання повідомлення, без перезавантаження сторінки
    • Для HTML тегів зробити панель із кнопками (,,,,)
    • Додавання візуальних ефектів також вітається
  • Вимоги

    Система має коректно працювати на ОС Linux з наступною конфігурацією:

    • PHP 5.1+
    • MySQL 4.1+
    • Apache 2.2+
    Допустимо використовувати такі бібліотеки:
    • PHP Zend Framework або PEAR
    • JS jQuery або Prototype

    P.S.На малюнку зображений двигун Стірлінга, wikipedia частенько дає їжу для розуму.

    Upd: дуже правильний коментар з'явився на моєму блозі:

    народ, ви, мабуть, не розумієте, на кого це завдання розраховане. Людина з досвідом природно не буде її робити з двох причин: а) не захоче витрачати час і б) йому не дадуть.

    Але реалії такі, що це часто взагалі перше більш-менш об'ємне завдання претендента на посаду junior php developer.

    Тому 80 годин дається не для того, щоб він це завдання просто зробив, а щоб привів реальність (свої знання) у відповідність до галочок у своєму резюме навпроти php, html, css, js, ajax, mysql.

    По виходу отримуємо якийсь інтегральний показник як скиленості так і здатності гуглити.

    Власне з цим завдання справляється.

    А кандидати, яким є що показати, природно йдуть одразу до проектів.


    Теги: Додати теги

  • В епоху сучасного вебу більшість сайтів стають все більш інтерактивними. Якщо раніше для отримання оновлених даних нам потрібно було оновити повністю сторінку, то зараз з'явилися технології, які дозволяють повністю сторінку не завантажувати, а лише окрему її частину. У свою чергу це надає зручність як користувачам, так і власникам серверів, адже для користувача завантаження сторінки буде швидше, тому що завантажується лише окрема частина сторінки, а серверу не потрібно щоразу генерувати сторінку та віддавати її користувачеві. Ці можливості просто реалізувати за допомогою php та ajax.

    Сьогодні ми розберемо невеликий приклад для кращого розуміння концепції. AJAX. Іноді новачкам буває важко зрозуміти яким чином взаємодіє між собою php і ajax, багато людей шукають приклади того як валідувати форми на льоту без перезавантаження всієї сторінки. Я вам коротко покажу як це робиться, для того, щоб ви могли зрозуміти основи та принципи, які дозволять вам у майбутньому швидше освоїти інші інструменти і писати свої власні скрипти.

    Придумаємо невелике завдання собі, перевірятимемо наявність email адреси в базі даних без перезавантаження сторінки використовуючи php та ajax. Такий приклад добре продемонструє як ми можемо взаємодіяти з сервером без перезавантаження сторінки в браузері, а також, це часто використовується при різноманітних валідаціях форм користувача. У кореневому каталозі створимо 3 файли з іменами index.php, email.php, validate.js.

    Створення сторінки

    Створимо просту сторінку з однією формою, яка містить лише одне поле для введення електронної пошти.
    Синтаксис файлу index.php

    AJAX Tutorial

    Найпростіший спосіб працювати з AJAX- це підключити фреймворк jQueryщо власне я і зробив. jQueryнадає нам простий у розумінні та роботі синтаксис для відправки AJAXзапитів, чому б не використати цю перевагу?

    Створення js скрипту

    Синтаксис файлу validate.js

    $(document).ready(function()( var email = ""; $("#email").keyup(function()( var value = $(this).val(); $.ajax(( type: "POST", url:"email.php", data:"email="+value, success:function(msg)( if(msg == "valid")( $("#message").html(" Цей e-mail можна використовувати.Цей e-mail вже зайнятий."); ) ) )); )); $("#submit").click(function()( if(email == "")( alert("Please, put data to all email"); )else( $.ajax(( type: "POST", url:"email.php", data:"add_email="+email, success:function(msg)( $("#message").html(msg); ) ) ); ) )); ));

    Обробник на php

    Цей скрипт отримуватиме POSTзапит від клієнта, обробляти його та повертати результат. AJAXзчитує результат та на його основі приймає рішення.
    Синтаксис файлу email.php

    $connection = mysqli_connect("localhost","email","email","email"); if(isset($_POST["email"]) && $_POST["email"] != "")( $email = $_POST["email"]; $email = mysqli_real_escape_string($connection,$email); if (!filter_var($email, FILTER_VALIDATE_EMAIL))( echo "invalid"; )else( $sql = "SELECT id FROM email WHERE email="$email""; $result = mysqli_query($connection,$sql); if( mysqli_num_rows($result) == 1)( echo "invalid"; )else( echo "valid"; ) ) ) if(isset($_POST["add_email"]) && $_POST["add_email"] != "" )( $email = mysqli_real_escape_string($connection,$_POST["add_email"]); $sql = "INSERT INTO email(email) VALUES("$email")"; if(mysqli_query($connection,$sql))( echo Success"; )else( echo " Error"; } }

    У нашому php скрипті, звичайнісінький код, який обробляє post запит і друкує на сторінці певний текст. В результаті AJAXвідправляє запит php скрипту, скрипт його обробляє та видає результат, AJAXзчитує результат та змінює сторінку в реальному часі.

    AJAX передає POST запит скрипту за допомогою цієї ділянки коду:

    $.ajax(( type:"POST", url:"email.php", data:"email="+value, success:function(msg)( if(msg == "valid")) ( $("#message ").html(" Цей e-mail можна використовувати."); email = value; )else( $("#message").html(" Цей e-mail вже зайнятий."); } } });

    type – Тип запиту, POST або GET. У разі POST;
    url - адреса скрипта якому надсилають запит;
    data - дані, які передаються в запиті;
    success - що робити в результаті успішного виконання запиту. У разі викликається функція;

    У самому скрипті, перевірка наявності електронної пошти в базі виконується при кожному введенні символу в полі електронної пошти. У скрипті за обробку введення відповідає ділянка $("#email").keyup(function()()); , який перевіряє натискання кнопки в полі з id = "email" .
    Як бачите, код досить простий і не вимагає особливо великих навичок для розуміння, все зав'язано на обробці подій keyup() – натискання клавіші, click() – клік мишкою по елементу. Далі слідує AJAXзапит та відповідь від скрипта. Таким чином, використовуючи php і ajax можна отримати практично безмежні можливості для створення інтерактивних сторінок.
    Цей код не претендує на звання високоякісного, але якщо розвинути, додати правильних валідацій на рівні клієнта та сервера, запровадити css, то цілком можна використовувати у своїх проектах.
    Якщо у вас виникли запитання, не соромтеся, пишіть коментарі.
    Бажаю вам гарного дня та до швидких зустрічей 🙂