Чи безпечно не параметризувати SQL-запит, коли параметр не є рядком?


113

З точки зору інжекції SQL я повністю розумію необхідність параметризації stringпараметра; це один із найдавніших трюків у книзі. Але коли можна виправдати не параметризувати SqlCommand? Чи вважаються якісь типи даних "безпечними", щоб не параметризувати їх?

Наприклад: я не вважаю себе ніде поблизу фахівця з SQL, але не можу придумати жодних випадків, коли потенційно вразливим для ін'єкції SQL було б прийняти a boolабо an intі просто об'єднати його прямо у запит.

Чи правильне моє припущення, чи це могло б залишити величезну вразливість безпеки в моїй програмі?

Для уточнення це питання позначено тегами яка є сильно набраною мовою; коли я кажу "параметр", думаю про щось подібне public int Query(int id) .


14
Ви не отримаєте переваги кешованих планів запитів, якщо не будете використовувати параметри, потрібно буде скласти окремий план запитів для кожної нової комбінації введених вами даних.
Скотт Чемберлен

5
@MatthewWhited Як ти знаєш, що це займає менше часу? Така ситуація виникає повсюдно в певних проектах від поточного розробника та попереднього розробника. Якщо це насправді покращує безпеку, будь ласка, опублікуйте відповідь. Для уточнення я згоден, що краще параметризувати, очевидно. Але це насправді не моє питання.
johnnyRose

7
Параметризовані запити в основному використовуються для продуктивності та оптимізації. Профілактика ін'єкцій SQL є побічним ефектом.
Салман

13
Я думаю, що ОП поставила вагоме запитання. Він намагається оцінити вартість / вигоду виправлення потенційного ризику. що рівняння змінюється з потенціалом цього ризику. якщо є нульовий ризик, я б і цього не робив. Він запитав технічне питання про потенціал, а не для суб'єктивного судження про те, чи вважаєте ви, що варто його часу. ОП є єдиним, хто може здійснити цей виклик.
Сер присягає

10
Щоб пояснити себе: я дба. Я ціную і поважаю найкращу практику, і в ідеальному світі весь код був би ідеальним. На жаль, у світі, в якому я працюю, у мене виникає більше проблем, ніж я маю час для їх вирішення. Це означає пріоритетність. Код переписування IMO, який вже працює, захищений і працює на прийнятних рівнях, звучить як розкіш. (Що я не можу собі дозволити)
Сер присягає,

Відповіді:


101

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

var sqlCommand = new SqlCommand("SELECT * FROM People WHERE IsAlive = " + isAlive + 
" AND FirstName = @firstName");

sqlCommand.Parameters.AddWithValue("firstName", "Rob");

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

Отже, ми змінили тип EmployeeNumber з intна string, але забули оновити запити sql. На жаль


24
Чи можемо ми припинити використання AddWithValue вже? blogs.msmvps.com/jcoehoorn/blog/2014/05/12/…
ЗауваженняLima

5
@RemarkLima Що таке рішення, коли ви динамічно генеруєте код, який відображає значення в параметри? Повідомлення в блозі не вдається вирішити цей сценарій. Так, це єдиний рядок для встановлення типу SQL, коли він відомий , але коли його немає, у вас виникає проблема (або вам доведеться вдаватися до анотування моделей з цією інформацією).
casperOne

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

8
@RemarkLima Справа в тому, що "Чи можемо ми AddWithValueвже припинити використання ?" повинні дійсно бути « , якщо ви знаєте тип, то ви повинні утримуватися від використання AddWithValue.
casperOne

2
Гей, не знімайте месенджера, я його не писав ;-), але справа залишається, і якщо вбудований у ваші проекти з самого початку, немає ніяких причин, щоб ви не знали тип. Найкраща практика та весь цей джаз :-)
RemarkLima

65

При використанні сильно типізованих платформи на комп'ютері управління (наприклад , веб - сервер), ви можете запобігти ін'єкції коду для запитів тільки bool, DateTimeабо int(та інші числові) значення. Викликає занепокоєння питання щодо продуктивності, викликаного змушенням сервера sql повторно компілювати кожен запит та заважати йому отримувати хорошу статистику щодо того, які запити виконуються з якою частотою (що шкодить кеш-керуванню).

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

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

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

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

Додам, що це, на жаль, не такий аргумент, який ви можете виграти прямо. Це звучить як ситуація, коли бути «правильним» вже недостатньо, а наступати на пальці колег, щоб самостійно вирішити цю проблему, швидше за все, не сприятиме гарній динаміці команди; в кінцевому рахунку це може зашкодити більше, ніж допомагає. Кращим підходом у цьому випадку може бути сприяння використанню інструменту статичного аналізу. Це дало б легітимність та надійність зусиллям, спрямованим на повернення та закріплення існуючого коду.


1
Зробити це параметризовано, безумовно, не проблема. Моє запитання виникло тому, що колега написав купу запитів, що об'єднують цілі значення, і мені було цікаво, чи марно витрачати свій час, щоб пройти і виправити їх усі.
johnnyRose

2
Я думаю, що питання "Це помилка" - це те, до чого зводиться моє запитання.
johnnyRose

7
Це "запах": щось, що не відповідає помилку, само по собі, але вказує на те, що помилки, ймовірно, поруч. Хороший код намагається усунути запахи. Будь-який хороший інструмент статичного аналізу, безумовно, позначить це.
Joel Coehoorn

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

1
Це просто неправильно. Дивіться, наприклад, мою відповідь про те, як ще можна створити ін'єкцію SQL за допомогою DateTimeабоint
Kaspars Ozols,

53

У деяких випадках можливо здійснити атаку ін'єкцій SQL з непараметризованими (об'єднаними) змінними, відмінними від рядкових значень - див. Цю статтю Джона: http://codeblog.jonskeet.uk/2014/08/08/the-bobbytables -культура / .

Річ у тому, що коли ToStringвикликається, якийсь користувальницький постачальник культури може перетворити нестроковий параметр у його рядкове представлення, що вводить деякий SQL у запит.


14
Я думаю, що це єдиний пост, який відповідає на питання, яке по суті є "Як ін'єкція навіть можлива за допомогою ints?"
Артуро Торрес Санчес

3
Хоча якщо ви в змозі ввести спеціальний код, такий як пастка, CultureInfoважко зрозуміти, для чого вам потрібна ін'єкція SQL.
Мартін Сміт

плюс 1, єдина відповідь, яка насправді відповідає на питання
ken2k

@MartinSmith: дивіться мою відповідь, яка показує один із можливих способів змінити культуруInfo ззовні.
користувач1027167

Якщо людина може написати такий код у додатку, навіщо йому потрібна ін'єкція SQL?
Реза Агхай

51

Це не безпечно навіть для нестрокових типів. Завжди використовуйте параметри. Період.

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

var utcNow = DateTime.UtcNow;
var sqlCommand = new SqlCommand("SELECT * FROM People WHERE created_on <= '" + utcNow + "'");

На перший погляд код виглядає безпечним, але все змінюється, якщо внести деякі зміни в регіональні налаштування Windows та додати ін'єкцію у короткий формат дати:

Ін'єкція дати

Тепер отриманий текст команди виглядає приблизно так:

SELECT * FROM People WHERE created_on <= '26.09.2015' OR '1'<>' 21:21:43'

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

Можна стверджувати, що замість нинішньої культури слід використовувати інваріантну культуру, але я багато разів бачив подібні струнні конкатенації, і це досить легко пропустити при об'єднанні рядків з використанням об'єктів +.


10
Хто може змінити налаштування сервера? Якщо людина може це зробити на вашому сервері, йому не потрібно SQL Injection для знищення даних.
Reza Aghaei

5
Це найкраща відповідь, вона показує один із способів, що підтверджують, що ОП стосуються, що це помилка / недолік безпеки. Ефективність та майбутня перевірка, окрім об'єднувальних дат, наприклад, у SQL, це не лише запах або технологічна заборгованість . @RezaAghaei питання ніколи не згадувало серверну сторону, це може бути додаток для Windows із SQLExpress - в будь-якому випадку це не критерії для цього питання. Будь-хто може сказати, але хто має доступ до налаштувань сервера, щоб спростувати цю чудову відповідь, як і хто-небудь міг сказати, що стосується спільного розміщення сервера або помилки Y2K. Я згоден з вами заблокованим сервером - це просто не застереження.
Джеремі Томпсон

2
Чи можете ви навести приклад того, що ви говорили про intтип?
johnnyRose

1
Я знаю, що минуло декілька тижнів з моменту, коли ви відповіли на це, але чи можна було б ви відредагувати свою допис і додати приклад того, як можна визначити спеціальний негативний знак?
johnnyRose

23

"SELECT * FROM Table1 WHERE Id =" + intVariable.ToString ()


Безпека
Гаразд.
Зловмисники не можуть ввести нічого у вашу введену змінну int.

Виконання
не в порядку

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

Стиль кодування
Неправильна практика.

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


"SELECT * FROM Product WHERE Id =" + TextBox1.Text


Хоча це не ваше питання, але може бути корисним для майбутніх читачів:


Катастрофа безпеки !
Навіть коли Idполе є цілим числом, ваш запит може бути предметом ін'єкції SQL. Припустимо, у вас є запит у вашій програмі "SELECT * FROM Table1 WHERE Id=" + TextBox1.Text. Зловмисник може вставити у текстове поле, 1; DELETE Table1і запит буде:

"SELECT * FROM Table1 WHERE Id=1; DELETE Table1"

Якщо ви не хочете використовувати параметризований запит тут, слід використовувати введені значення:

string.Format("SELECT * FROM Table1 WHERE Id={0}", int.Parse(TextBox1.Text))


Твоє запитання


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

Я думаю, що зміна цих кодів не є марною витратою часу. Дійсно зміни рекомендується!

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


Навіть перший варіант не зовсім гаразд щодо безпеки. Поведінка .ToString()визначається елементом конфігурації операційної системи, який легко змінити, щоб включити довільний текст.
Joel Coehoorn

18

Насправді два питання в одному. І питання з назви має дуже мало спільного з занепокоєнням, висловленим ОП у коментарях після цього.

Хоча я усвідомлюю, що для ОП це важливий їх конкретний випадок, для читачів, які приходять з Google, важливо відповісти на більш загальне питання, яке можна висловити як "є конкатенація настільки ж безпечною, як підготовлені заяви, якщо я переконався що кожен буквальний, який я об'єдную, безпечний? ". Отже, я хотів би сконцентруватися саме на цьому останньому. І відповідь така

Однозначно НІ.

Пояснення не таке пряме, як хотілося б більшості читачів, але я постараюся зробити все можливе.

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

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

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

Коли ви намагаєтеся вирішити питання захисту не в цілому, а як набір різних проблем із синтаксисом, ви стикаєтеся з безліччю проблем.

  • список можливих варіантів форматування дійсно величезний. Значить, можна легко проігнорувати деякі. Або переплутати їх (наприклад, використовуючи рядок уникнення рядка для ідентифікатора ).
  • Об’єднання означає, що всі заходи захисту повинні виконувати програміст, а не програма. Саме це питання призводить до кількох наслідків:
    • таке форматування є вручну. Інструкція означає надзвичайно схильні до помилок. Можна було просто забути подати заявку.
    • крім того, існує спокуса перенести процедури форматування в якусь централізовану функцію, ще більше плутати речі та псувати дані, які не збираються в базу даних.
  • коли задіяно більше одного розробника, проблеми множать на десять.
  • коли використовується конкатенація, не можна сказати потенційно небезпечний запит з першого погляду: всі вони потенційно небезпечні!

На відміну від цього безладу, підготовлені заяви справді є Святим Граалом:

  • вона може бути виражена у вигляді одного простого правила, якого легко дотримуватися.
  • це, по суті, недосяжний захід, означає, що розробник не може втручатися і, охоче чи не бажаючи, зіпсувати процес.
  • захист від ін'єкцій насправді є лише побічним ефектом підготовлених тверджень, реальною метою яких є створення синтаксично правильного твердження. А синтаксично правильне твердження - 100% доказ ін'єкції. Однак нам потрібен правильний синтаксис, незважаючи на будь-яку можливість введення.
  • якщо використовується навпаки, він захищає додаток незалежно від досвіду розробника. Скажімо, є річ, яка називається ін'єкцією другого порядку . І дуже сильна оманливість, яка звучить "з метою захисту, уникнути всього введення користувачем ". У поєднанні вони призводять до ін'єкцій, якщо розробник бере на себе вирішення, що потрібно захистити, а що ні.

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

Цікаво, що суперечки цього питання спровоковані дуже суперечливим характером Stack Overflow. Ідея сайту полягає в тому, щоб використовувати конкретні запитання користувачів, які задають безпосередньо, щоб досягти мети - мати базу даних відповідей загального призначення, придатних для користувачів, які приходять із пошуку . Ідея сама по собі непогана , але вона провалюється у такій ситуації: коли користувач задає дуже вузьке запитання , особливо, щоб отримати аргумент у суперечці з колегою (або вирішити, чи варто рефакторировать код). У той час як більшість досвідчених учасників намагаються написати відповідь, пам’ятаючи про місію переповнення стека в цілому, завдяки чому їх відповідь хороша для якомога більшої кількості читачів, а не лише для ОП.


10
Не відповідаючи на запитання
edc65

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

15

Давайте не будемо думати лише про міркування щодо безпеки чи безпеки типу.

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

БЕЗКОШТОВНО

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

ЗАРАЗ

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

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


8

Щоб додати трохи інформації до відповіді Maciek:

Інформацію про культуру стороннього додатка .NET легко змінити, зателефонувавши за допомогою відображення основної функції збірки:

using System;
using System.Globalization;
using System.Reflection;
using System.Threading;

namespace ConsoleApplication2
{
  class Program
  {
    static void Main(string[] args)
    {
      Assembly asm = Assembly.LoadFile(@"C:\BobbysApp.exe");
      MethodInfo mi = asm.GetType("Test").GetMethod("Main");
      mi.Invoke(null, null);
      Console.ReadLine();
    }

    static Program()
    {
      InstallBobbyTablesCulture();
    }

    static void InstallBobbyTablesCulture()
    {
      CultureInfo bobby = (CultureInfo)CultureInfo.InvariantCulture.Clone();
      bobby.DateTimeFormat.ShortDatePattern = @"yyyy-MM-dd'' OR ' '=''";
      bobby.DateTimeFormat.LongTimePattern = "";
      bobby.NumberFormat.NegativeSign = "1 OR 1=1 OR 1=";
      Thread.CurrentThread.CurrentCulture = bobby;
    }
  }
}

Це працює лише в тому випадку, якщо Основна функція BobbysApp є загальнодоступною. Якщо Main не є загальнодоступним, можливо, ви можете зателефонувати іншим публічним функціям.


1
Вам навіть не потрібно робити це за кодом. Ви можете додати ін'єкцію безпосередньо в регіональні налаштування Windows. Дивіться мою відповідь.
Kaspars Ozols

2
Хто може змінити налаштування сервера або хто може натирати такий код на сервері? Якщо людина може це зробити на вашому сервері, йому не потрібно SQL Injection для знищення даних.
Реза Агей

7

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


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

Гаразд. Чудово. Це найкращі практики використання параметрів. Таким чином, вам не потрібно турбуватися про речі, такі як ін'єкція sql. Крім того, якщо ви будуєте динамічні запити, ви також можете використовувати параметри, незалежно від того, наскільки складні ваші запити. Просто використовуйте стиль @ 1 ... @ n, будуючи їх. І додайте їх до колекції параметрів із потрібним значенням.
Макс

@johnyRose Є ще один момент використання параметрів: програми розвиваються і змінюються. Ви можете використовувати конкатенацію лише для рядків, але це не гарантує, що хтось реалізує рефакторинг, який змінює певний тип параметра і що зміни можуть ввести вразливість SQL Injection.
lerthe61

3

Це нормально, але ніколи не безпечно .. і безпека завжди залежить від входів, наприклад, якщо об'єктом вводу є TextBox, зловмисники можуть зробити щось складне, оскільки текстовий блок може приймати рядок, тому вам доведеться поставити якусь перевірку / перетворення щоб запобігти неправильному введенню користувачами. Але справа в тому, що це не безпечно. Так просто.


Це хоч рядок. Я говорю про інші типи даних, такі як цілі числа, булеві або датні.
johnnyRose

@johnnyRose Yup, я бачив дуже гарний приклад вище, який ви відзначаєте як відповів Каспардс .. і чудову відповідь, оскільки він використовує тип даних datetime як приклад, який є рідкістю. :) Сподіваюсь, ви вже переконалися, що не безпечно і краще використовувати параметр у будь-яких
типах

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

Так .. я згоден і це також чудове питання, яке може допомогти майбутнім читачам :)
japzdivino

-2

Ні, ви не можете отримати атаку ін'єкцій SQL таким чином. Я написав стару статтю турецькою, де показано, як тут . Приклад статті в PHP та MySQL, але концепція працює однаково в C # і SQL Server.

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

http://localhost/sqlEnjeksiyon//instructors.aspx?id=24

Гаразд, я припускаю, що ви використовуєте MySQL, і я атакую ​​наступним чином.

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII((SELECT%20DATABASE()))

Зауважте, що тут введене значення не є рядком. Ми змінюємо значення char на int за допомогою функції ASCII. Ви можете зробити те ж саме в SQL Server, використовуючи "CAST (YourVarcharCol AS INT)".

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

http://localhost/sqlEnjeksiyon//instructors.aspx?id=LEN((SELECT%20DATABASE()))

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR(SELECT%20DATABASE(),1,1))

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

http://localhost/sqlEnjeksiyon//instructors.aspx?id=ASCII(SUBSTR((SELECT table_name FROM INFORMATION_SCHEMA.TABLES LIMIT 1),1,1))

Звичайно, ви повинні автоматизувати цей процес, оскільки ви отримуєте лише ОДИН символ на запит. Але ви можете легко автоматизувати це. У моїй статті показаний один приклад у watir . Використання лише однієї сторінки та не параметризоване значення ідентифікатора. Я можу дізнатися кожну назву таблиці у вашій базі даних. Після цього я можу шукати важливі таблиці. Це займе час, але це можливо.


2
Моє запитання стосується сильно набраної мови. Хоча ваше пояснення чудово підходить для мов з гнучким набором тексту, введене значення все ще є рядком.
johnnyRose

Не введене значення не є цілим числом. Ви отримуєте char і змінюєте його на ціле число за допомогою функції ASCII MySQL. Ви робите те саме в SQL Server, використовуючи CAST (YourCharValue AS INT)
Atilla Ozgur

Я мав на увазі щось подібне:public void QuerySomething(int id) { // this will only accept an integer }
johnnyRose

-3

Ну ... одне впевнене: безпека НЕ ​​нормальна, коли ви об'єднуєте рядок (взятий користувачем) з вашою командною ланцюжком SQL. Не важливо, коли пункт де посилається на цілий чи будь-який тип; ін'єкції можуть статися.

У SQL Injection важливим є тип даних змінної, яка використовувалась для отримання значення від користувача.

Припустимо, у нас є ціле число в пункті «де» і:

  1. користувацька змінна - це рядок. Тоді гаразд, його не дуже легко вводити (за допомогою UNION), але його дуже просто обійти, використовуючи «АБО 1 = 1» - подібні атаки ...

  2. Якщо змінна користувача - ціле число. Потім ми знову можемо «перевірити» міцність системи, пройшовши незвичайні тести великої кількості на збої системи або навіть на прихований переповнення буфера (на остаточному рядку) ...;)

Можливо, параметри запитів або (ще краще - imo) для збережених процедур не є на 100% безпечними, але вони є найменш необхідним заходом (або елементарним, якщо ви бажаєте), щоб мінімізувати їх.


Я думаю, ви могли неправильно зрозуміти питання. Я говорю про те, що не є -string типів.
johnnyRose

Привіт JonnyRose ... дякую за вашу замітку. Я розумію ваше запитання, але я просто ставлю свою відповідь у більш загальній формі. У випадку, що не має рядків, перевірте мою (2) точку. ;)
Андреас Веньєріс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.