Насправді два питання в одному. І питання з назви має дуже мало спільного з занепокоєнням, висловленим ОП у коментарях після цього.
Хоча я усвідомлюю, що для ОП це важливий їх конкретний випадок, для читачів, які приходять з Google, важливо відповісти на більш загальне питання, яке можна висловити як "є конкатенація настільки ж безпечною, як підготовлені заяви, якщо я переконався що кожен буквальний, який я об'єдную, безпечний? ". Отже, я хотів би сконцентруватися саме на цьому останньому. І відповідь така
Однозначно НІ.
Пояснення не таке пряме, як хотілося б більшості читачів, але я постараюся зробити все можливе.
Я певний час розмірковував над цим питанням, в результаті чого стаття (хоча і заснована на середовищі PHP), де я намагався підвести підсумки. Мені прийшло в голову, що питання захисту від ін'єкції SQL часто ухиляється від деяких споріднених, але вужчих тем, таких як скачування рядків, лиття типів тощо. Хоча деякі заходи можна вважати безпечними, якщо їх вживати самостійно, не існує ані системи, ані простого правила, яке слід дотримуватися. Це робить її дуже слизькою землею, приділяючи занадто багато уваги та досвіду розробника.
Питання інжекції SQL не може бути спрощений до якоїсь конкретної проблеми з синтаксисом. Він ширший, ніж звичайний розробник, який раніше думав. Це також методологічне питання. Це не лише "Яке саме форматування ми повинні застосувати", але і " Як це потрібно зробити".
(З цієї точки зору, стаття Джона Скіта, цитована в іншій відповіді, робить скоріше поганою, ніж хорошою, оскільки знову опиняється на певному крайовому випадку, концентруючись на певному синтаксичному питанні та не в змозі вирішити проблему взагалі.)
Коли ви намагаєтеся вирішити питання захисту не в цілому, а як набір різних проблем із синтаксисом, ви стикаєтеся з безліччю проблем.
- список можливих варіантів форматування дійсно величезний. Значить, можна легко проігнорувати деякі. Або переплутати їх (наприклад, використовуючи рядок уникнення рядка для ідентифікатора ).
- Об’єднання означає, що всі заходи захисту повинні виконувати програміст, а не програма. Саме це питання призводить до кількох наслідків:
- таке форматування є вручну. Інструкція означає надзвичайно схильні до помилок. Можна було просто забути подати заявку.
- крім того, існує спокуса перенести процедури форматування в якусь централізовану функцію, ще більше плутати речі та псувати дані, які не збираються в базу даних.
- коли задіяно більше одного розробника, проблеми множать на десять.
- коли використовується конкатенація, не можна сказати потенційно небезпечний запит з першого погляду: всі вони потенційно небезпечні!
На відміну від цього безладу, підготовлені заяви справді є Святим Граалом:
- вона може бути виражена у вигляді одного простого правила, якого легко дотримуватися.
- це, по суті, недосяжний захід, означає, що розробник не може втручатися і, охоче чи не бажаючи, зіпсувати процес.
- захист від ін'єкцій насправді є лише побічним ефектом підготовлених тверджень, реальною метою яких є створення синтаксично правильного твердження. А синтаксично правильне твердження - 100% доказ ін'єкції. Однак нам потрібен правильний синтаксис, незважаючи на будь-яку можливість введення.
- якщо використовується навпаки, він захищає додаток незалежно від досвіду розробника. Скажімо, є річ, яка називається ін'єкцією другого порядку . І дуже сильна оманливість, яка звучить "з метою захисту, уникнути всього введення користувачем ". У поєднанні вони призводять до ін'єкцій, якщо розробник бере на себе вирішення, що потрібно захистити, а що ні.
(Думаючи далі, я виявив, що поточного набору заповнювачів недостатньо для реальних потреб життя, і їх потрібно розширити, як для складних структур даних, як масиви, так і навіть ключові слова або ідентифікатори SQL, які іноді доводиться додавати до запит також динамічно, але розробник залишається без озброєння для такого випадку і змушений повернутися до об'єднання рядків, але це питання іншого питання).
Цікаво, що суперечки цього питання спровоковані дуже суперечливим характером Stack Overflow. Ідея сайту полягає в тому, щоб використовувати конкретні запитання користувачів, які задають безпосередньо, щоб досягти мети - мати базу даних відповідей загального призначення, придатних для користувачів, які приходять із пошуку . Ідея сама по собі непогана , але вона провалюється у такій ситуації: коли користувач задає дуже вузьке запитання , особливо, щоб отримати аргумент у суперечці з колегою (або вирішити, чи варто рефакторировать код). У той час як більшість досвідчених учасників намагаються написати відповідь, пам’ятаючи про місію переповнення стека в цілому, завдяки чому їх відповідь хороша для якомога більшої кількості читачів, а не лише для ОП.