TL; DR
- Додаток приймає вхідні дані , в даному випадку «Ненсі», не намагаючись - санувати вхід, наприклад, з допомогою спеціальних символів
школи => INSERT INTO студентів VALUES ( «Ненсі» ); ВСТАВКА 0 1
- ін'єкції SQL відбувається , коли вхід в команду бази даних маніпулюють , щоб - викликати сервер бази даних виконати довільний SQL
школи => INSERT INTO студентів VALUES ( «Robert» ); ДРОПУВАТИ ТАБЛИЧНІ студенти ; - '); ВСТАВКА 0 1 ТАБЛИКА ДРОПА
- Студентські записи тепер пропали - це могло бути ще гірше!
школа => ВИБРАТИ * ВІД учнів ;
ПОМИЛКА : співвідношенню «студенти» зовсім НЕ існує
РЕКЛАМ 1 : ВИБІРТЕ * З учнів ; ^
Це скидає (видаляє) таблицю учнів.
( Усі приклади коду в цій відповіді були запущені на сервері баз даних PostgreSQL 9.1.2. )
Щоб зрозуміти, що відбувається, спробуймо це з простою таблицею, що містить лише поле імені та додамо один рядок:
школа => СТВОРИТИ ТАБЛИЧНІ студенти ( назва ТЕКСТ ПЕРШИЙ КЛЮЧ );
УВАГА : CREATE TABLE / PRIMARY KEY буде створювати неявну індекс "students_pkey" для таблиці "Студенти" CREATE TABLE
школи => INSERT INTO студентів ЗНАЧЕННЯ ( 'Джон' ); ВСТАВКА 0 1
Припустимо, що програма використовує наступний SQL для вставки даних у таблицю:
INSERT INTO студентів ЗНАЧЕННЯ ( 'Foobar' );
Замініть foobar
фактичним прізвищем студента. Нормальна операція вставки виглядатиме так:
- Вхідні дані:
школа Ненсі => ВСТАВЛЯЙТЬСЯ В НАВЧАЛЬНІ ЗНАЧЕННЯ студентів ( «Ненсі» ); ВСТАВКА 0 1
Коли ми запитуємо таблицю, ми отримуємо це:
школа => ВИБРАТИ * ВІД учнів ;
назва
-------
Джон
Ненсі
( 2 ряди )
Що станеться, коли ми вставимо в таблицю ім'я маленьких Боббі Столів?
- Вхід: Роберт '); ДРОПУВАТИ ТАБЛИЧНІ студенти; -
школа => INSERT INTO студентів ЗНАЧЕННЯ ( 'Роберт' ); ДРОПУВАТИ ТАБЛИЧНІ студенти ; - '); ВСТАВКА 0 1 ТАБЛИКА ДРОПА
Ін'єкція SQL тут є результатом того, що ім'я студента закінчує оператор і включає окрему DROP TABLE
команду; обидві тире в кінці вводу призначені для коментування будь-якого коду, що залишився, який інакше спричинив би помилку. Останній рядок виводу підтверджує, що сервер бази даних скинув таблицю.
Важливо зауважити, що під час INSERT
операції програма не перевіряє вхід на наявність спеціальних символів, а тому дозволяє довільно вводити в команду SQL. Це означає, що зловмисний користувач може вставити в поле, звичайно призначене для введення користувача, спеціальні символи, такі як лапки разом з довільним кодом SQL, щоб змусити систему баз даних виконувати його, отже, ін'єкцію SQL .
Результат?
школа => ВИБРАТИ * ВІД учнів ;
ПОМИЛКА : співвідношенню «студенти» зовсім НЕ існує
РЕКЛАМ 1 : ВИБІРТЕ * З учнів ; ^
Інжекція SQL - еквівалент бази даних віддаленої уразливості виконання довільного коду в операційній системі або додатку. Потенційний вплив успішної атаки ін'єкції SQL не можна недооцінювати - залежно від системи бази даних та конфігурації програми, зловмисник може використовувати її для втрати даних (як у цьому випадку), отримання несанкціонованого доступу до даних або навіть виконання довільний код на самій хост-машині.
Як зазначає комікс XKCD, одним із способів захисту від атак SQL-ін'єкції є санітація входів бази даних, наприклад, за допомогою втечі спеціальних символів, щоб вони не могли змінювати базову команду SQL і, отже, не могли викликати виконання довільного коду SQL. Якщо ви використовуєте параметризовані запити, як-от за допомогою SqlParameter
ADO.NET, вхід, як мінімум, буде автоматично очищений для захисту від ін'єкції SQL.
Однак санітарія входів на рівні програми може не зупинити більш досконалі методи введення SQL. Наприклад, є способи обійти функцію mysql_real_escape_string
PHP . Для додаткового захисту багато систем баз даних підтримують підготовлені заяви . Якщо правильно впроваджено в заднім часі, підготовлені оператори можуть зробити неможливим введення SQL, трактуючи введення даних як семантично відокремлене від решти команди.