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

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

Оновлений протокол Яндекс.Гроші 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). До виходу цього оновлення (припустимо, наприкінці місяця вийде в альфі) обробник можна запросити через Технічну підтримку.

В епоху сучасного вебу більшість сайтів стають все більш інтерактивними. Якщо раніше для отримання оновлених даних нам потрібно було оновити повністю сторінку, то зараз з'явилися технології які дозволяють повністю сторінку не завантажувати, а лише окрему її частину. У свою чергу це надає зручність як користувачам, так і власникам серверів, адже для користувача завантаження сторінки буде швидше, тому що завантажується лише окрема частина сторінки, а серверу не потрібно щоразу генерувати сторінку та віддавати її користувачеві. Ці можливості просто реалізувати за допомогою 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("Цей Email можна використовувати.Цей Email вже зайнятий."); ) ) )); )); $("#submit"). 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("Цей Email можна використовувати. "); email = value; )else( $("#message").html("Цей Email вже зайнятий. "); ) ) )));

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

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

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

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

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

Name Email Message Submit Message Submitted!

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

Ми створили два стовпці з класом col-sm-6 (50%), який будемо використовувати, щоб відокремити верхню частину форми. В межах першого стовпця col-sm-6 ми створили мітку та поля для імені та електронної пошти. Кожен із них містить 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 , що додається полям імені та адреси електронної пошти:

Name Email

Тепер при повторному надсиланні даних 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», підготовленої дружною командою проекту


У списку десяти найпоширеніших видів атак за версією 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-запитами може переслідувати такі цілі:

  • Витоку даних.
  • Розкриття інформації, що зберігається.
  • Маніпулювання збереженою інформацією.
  • Обхід авторизації.
  • Впровадження 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 InjectionCommand InjectionExamples of Command InjectionDefenses against Command InjectionВикористання лога (відомо як впровадження лог-файлу, Log File Injection)

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


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


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


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

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


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


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

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

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


    $username = "iamnothacker! на 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 TraversalDefenses 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, він опрацює цю кастомну сутність відразу ж, як завантажиться документ. Тому при запиті відповідного тексту поверне таке:


    Цей результат є повністю 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("/