Безопасно ли не параметризовать SQL-запрос, если параметр не является строкой?

113

Что касается внедрения SQL , я полностью понимаю необходимость параметризации stringпараметра; это одна из старейших уловок в книге. Но когда можно оправдать отсутствие параметризации SqlCommand? Считаются ли какие-либо типы данных "безопасными" для отказа от параметризации?

Например: Я не считаю себя в любом месте рядом с экспертом в SQL, но я не могу думать о каких - либо случаях , когда это было бы потенциально уязвимы к SQL инъекции , чтобы принять boolили intи просто сцепить его прямо в запросе.

Верно ли мое предположение, или это потенциально может привести к серьезной уязвимости системы безопасности в моей программе?

Для пояснения этот вопрос помечен который является строго типизированным языком; когда я говорю «параметр», думаю, что-то вроде public int Query(int id) .

johnnyRose
источник
14
Вы не получите преимуществ кэшированных планов запросов, если не будете использовать параметры, вам нужно будет составлять отдельный план запроса для каждой новой комбинации вводимых вами данных.
Скотт Чемберлен
5
@MatthewWhited Откуда вы знаете, что на это уходит меньше времени? Эта ситуация возникает повсеместно в определенных проектах от текущего разработчика и предыдущего разработчика. Если это действительно улучшает безопасность, отправьте ответ. Для пояснения я согласен, что, очевидно, лучше параметризовать. Но это не совсем мой вопрос.
johnnyRose
7
Параметризованные запросы в основном используются для повышения производительности и оптимизации. Предотвращение SQL-инъекций - это побочный эффект.
Salman A
13
Я думаю, что ОП задал правильный вопрос. Он пытается оценить затраты / выгоды от устранения потенциального риска. это уравнение меняется в зависимости от потенциала этого риска. если риск нулевой, я бы тоже этого не сделал. Его задают технический вопрос о потенциале, а не субъективное суждение о том, стоит ли, по вашему мнению, потратить его время. OP - единственный, кто может сделать этот звонок.
Сэр ругается много
10
Чтобы объяснить себя: я dba. Я ценю и уважаю передовой опыт, и в идеальном мире весь код был бы идеальным. К сожалению, в мире, в котором я работаю, мне нужно решить больше проблем, чем у меня есть время, чтобы решить их. Это означает расстановку приоритетов. IMO Rewriting кода, который уже работает, безопасен и работает до приемлемого уровня, звучит как роскошь. (Этого я не могу себе позволить)
Сэр ругается много,

Ответы:

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/…
RemarkLima
5
@RemarkLima Какое решение может быть при динамической генерации кода, который сопоставляет значения с параметрами? Сообщение в блоге не рассматривает этот сценарий. Да, это одна строка для установки типа SQL, если он известен , но когда это не так, у вас есть проблема (или вам нужно прибегнуть к аннотированию моделей с помощью этой информации).
casperOne
1
Тогда вы застрянете, AddWithValueесли у вас нет сопоставления типов базы данных как части динамического построения оператора. Я предполагаю, что у вас есть список целевых столбцов, и как часть словаря, вы можете иметь типы, если хотите. В противном случае просто получите удар производительности. В конце концов, я думаю, это просто хорошая информация.
RemarkLima
8
@RemarkLima Суть в том, "Можем ли мы AddWithValueуже прекратить употреблять ?" должны действительно быть « , если вы знаете тип, то вы должны воздерживаться от использования AddWithValue.
casperOne
2
Эй, не стреляйте в мессенджер, я его не писал ;-) Но суть в том, что если он встроен в ваш дизайн с самого начала, нет причин, по которым вы не должны знать тип. Лучшая практика и все такое :-)
RemarkLima
65

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

Но эта часть «на компьютере, которым вы управляете» важна, потому что в противном случае пользователь может изменить поведение, используемое системой для генерации строк из этих значений, чтобы включить произвольный текст.

Я также люблю думать о долгосрочной перспективе. Что происходит, когда сегодняшняя устаревшая строго типизированная база кода переносится через автоматический перевод на новый динамический язык, и вы внезапно теряете проверку типов, но еще не имеете всех необходимых модульных тестов для динамического кода ?

На самом деле нет веских причин не использовать параметры запроса для этих значений. Это правильный способ сделать это. Идите вперед и жестко закодируйте значения в строку sql, если они действительно являются константами, но в противном случае почему бы просто не использовать параметр? Не то чтобы это было сложно.

В конечном счете, я бы не назвал это ошибкой как таковой, но я бы назвал это запахом : то, что само по себе не является ошибкой, но является убедительным признаком того, что ошибки поблизости или будут в конечном итоге. Хороший код не оставляет запаха, и любой хороший инструмент статического анализа отметит это.

Я добавлю, что это, к сожалению, не тот аргумент, который можно выиграть сразу. Похоже, ситуация, когда «быть правым» уже недостаточно, и наступать на пальцы ног ваших коллег, чтобы решить эту проблему самостоятельно, вряд ли будет способствовать хорошей командной динамике; в конечном итоге это может больше навредить, чем помочь. Лучшим подходом в этом случае может быть продвижение использования инструмента статического анализа. Это придаст законность и доверие усилиям, направленным на исправление существующего кода и исправлению его.

Джоэл Кохорн
источник
1
Определенно не проблема сделать это параметризованным. Мой вопрос возник из-за того, что мой коллега написал кучу запросов, объединяющих целочисленные значения, и мне было интересно, не было ли потрачено времени, чтобы пройти и исправить все из них.
johnnyRose
2
Я думаю, что вопрос «Это ошибка?» - вот к чему сводится мой вопрос.
johnnyRose
7
Это «запах»: то, что само по себе не является ошибкой, но указывает на то, что ошибки, вероятно, находятся поблизости. Хороший код пытается устранить запахи. Любой хороший инструмент статического анализа обязательно отметит это.
Джоэл Кохорн
1
Мне нравится термин «запах». Вместо этого я бы использовал что-то вроде «личинки», где это еще не совсем ошибка, но в будущих обновлениях она может заразиться личинкой, которая будет есть на вашем сервере, пока вы не раздавите ее или не окурите. Вы, конечно, не хотите, чтобы в производственной среде возник потенциал некротического кода, и наличие чего-то, что не было разработано с определенной долей изящества, определенно могло вызвать его присутствие, как в этом случае.
CSS
1
Это просто неправильно. См. Мой ответ, например, о том, как еще можно создать SQL-инъекцию с помощью DateTimeилиint
Каспарс Озолс
53

В некоторых случаях МОЖНО выполнить атаку с использованием SQL-инъекции с непараметризованными (конкатенированными) переменными, отличными от строковых значений - см. Эту статью Джона: http://codeblog.jonskeet.uk/2014/08/08/the-bobbytables -культура / .

Дело в том, что при ToStringвызове какой-то настраиваемый поставщик культуры может преобразовать нестроковый параметр в свое строковое представление, которое вводит некоторый SQL в запрос.

Maciek
источник
14
Я думаю, что это единственный пост, который отвечает на вопрос, который, по сути, звучит так: «Как инъекция вообще возможна с ints?»
Артуро Торрес Санчес
3
Хотя, если у вас есть возможность вводить собственный код, такой как мина в ловушке, CultureInfoтрудно понять, зачем вам все равно понадобится SQL-инъекция.
Мартин Смит
плюс 1, единственный ответ, который действительно отвечает на вопрос
ken2k
@MartinSmith: см. Мой ответ, в котором показан один из возможных способов изменить CultureInfo извне.
user1027167
Если человек может написать такой код в приложении, зачем ему SQL Injection?
Reza Aghaei
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-инъекция для уничтожения данных.
Reza Aghaei
5
Это лучший ответ, он показывает один из способов, который подтверждает обеспокоенность OP, это ошибка / недостаток безопасности. Производительность и надежность в будущем, если не считать конкатенации дат и времени в SQL, например, - это не просто запах или технический долг . @RezaAghaei, вопрос никогда не упоминался на стороне сервера, это может быть приложение Windows с SQLExpress - в любом случае это не критерий для вопроса. Кто угодно может сказать, но у кого есть доступ к настройкам сервера, чтобы опровергнуть этот отличный ответ, точно так же, как любой мог бы сказать, что насчет хостинга общего сервера или ошибки 2000 года. Я согласен с тем, что сервер заблокирован - это не обязательно.
Джереми Томпсон
2
Не могли бы вы привести пример того, что вы говорили о intтипе?
johnnyRose
1
Я знаю, что с тех пор, как вы ответили на этот вопрос, прошло несколько недель, но сможете ли вы отредактировать свой пост и добавить пример того, как вы можете определить собственный отрицательный знак?
johnnyRose
23

«ВЫБРАТЬ * ИЗ Table1 WHERE Id =» + intVariable.ToString ()


Безопасность
Это нормально.
Злоумышленники не могут ничего ввести в вашу типизированную переменную int.

Производительность
не в порядке.

Лучше использовать параметры, чтобы запрос был скомпилирован один раз и кэширован для следующего использования. В следующий раз, даже с другими значениями параметров, запрос кешируется и не требует компиляции на сервере базы данных.

Стиль кодирования
Плохая практика.

  • Параметры более читабельны
  • Может быть, это заставляет вас привыкнуть к запросам без параметров, тогда, может быть, вы однажды ошиблись и использовали строковое значение таким образом, и тогда вам, вероятно, следует попрощаться со своими данными. Плохая привычка!


«ВЫБРАТЬ * ИЗ продукта, ГДЕ 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

На самом деле есть два вопроса в одном. И вопрос из заголовка имеет мало общего с опасениями, выраженными ОП в комментариях впоследствии.

Хотя я понимаю, что для OP важен именно их конкретный случай, для читателей из Google важно ответить на более общий вопрос, который можно сформулировать так: «Конкатенация так же безопасна, как и подготовленные утверждения, если я убедился что каждый литерал, который я объединяю, безопасен? ". Итак, я хотел бы сосредоточиться на последнем. И ответ

Определенно нет.

Объяснение не такое прямое, как хотелось бы большинству читателей, но я постараюсь изо всех сил.

Некоторое время я размышлял над этим вопросом, и в результате появилась статья (хотя и основанная на среде PHP), в которой я попытался подвести итоги. Мне пришло в голову, что вопрос защиты от SQL-инъекций часто ускользает от некоторых связанных, но более узких тем, таких как экранирование строк, приведение типов и тому подобное. Хотя некоторые меры можно считать безопасными, если их принимать сами по себе, не существует системы или простого правила, которому следовало бы следовать. Это делает его очень скользким, слишком сильно отнимая у разработчика внимание и опыт.

Вопрос о внедрении SQL нельзя упростить до какой-то конкретной синтаксической проблемы. Он шире, чем раньше думал средний разработчик. Это тоже методологический вопрос. Это не только «какое именно форматирование мы должны применить», но и « как это должно быть сделано».

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

Когда вы пытаетесь решить вопрос о защите не в целом, а как набор различных синтаксических проблем, вы сталкиваетесь с множеством проблем.

  • список возможных вариантов форматирования действительно огромен. Значит, некоторых можно легко упустить из виду. Или запутайте их (например, используя экранирование строки для идентификатора ).
  • Конкатенация означает, что все меры защиты должны выполняться программистом, а не программой. Сама по себе эта проблема приводит к нескольким последствиям:
    • такое форматирование выполняется вручную. Ручной означает чрезвычайно высокую вероятность ошибок. Можно было просто забыть подать заявку.
    • более того, есть соблазн перенести процедуры форматирования в какую-то централизованную функцию, что еще больше запутает вещи и испортит данные, которые не попадают в базу данных.
  • когда задействовано более одного разработчика, количество проблем увеличивается в десять раз.
  • когда используется конкатенация, невозможно сразу определить потенциально опасный запрос: все они потенциально опасны!

В отличие от этого беспорядка, заранее подготовленные утверждения - это действительно Святой Грааль:

  • его можно выразить в виде одного простого правила, которому легко следовать.
  • По сути, это неотъемлемая мера, означающая, что разработчик не может вмешиваться и, вольно или невольно, испортить процесс.
  • защита от инъекций на самом деле является лишь побочным эффектом подготовленных операторов, реальная цель которых - создать синтаксически правильный оператор. А синтаксически правильное утверждение на 100% доказано. Тем не менее, нам нужно, чтобы наш синтаксис был правильным, несмотря на любую возможность инъекции.
  • при полном использовании он защищает приложение независимо от опыта разработчика. Скажем, есть такая штука , как инъекция второго порядка . И очень сильное заблуждение, которое гласит: «Чтобы защитить, избегайте всех вводимых пользователем данных ». Вместе они приводят к инъекции, если разработчик решает, что нужно защитить, а что нет.

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

Интересно, что полемика по этому вопросу вызвана очень противоречивой природой Stack Overflow. Идея сайта состоит в том, чтобы использовать конкретные вопросы пользователей, которые задают напрямую, для достижения цели создания базы данных ответов общего назначения, подходящей для пользователей, которые приходят из поиска . Идея сама по себе неплохая , но она терпит неудачу в такой ситуации: когда пользователь задает очень узкий вопрос , в частности, чтобы получить аргумент в споре с коллегой (или решить, стоит ли рефакторинг кода). Хотя большинство опытных участников пытаются написать ответ, помня о миссии Stack Overflow в целом, что делает их ответ интересным для как можно большего числа читателей, а не только для OP.

Ваш здравый смысл
источник
10
Не
отвечу
Большинство баз данных обнаруживают уже используемые параметризованные запросы по равенству строк SQL, поэтому старый метод подготовки и использования кажется мне устаревшим. Эти дескрипторы могут использоваться только в определенной области и требуют кодирования для отслеживания дескриптора. На мой взгляд, параметризованные запросы следует использовать напрямую, чтобы планы запросов можно было повторно использовать без отслеживания дескрипторов и даже в разных приложениях.
Эрик Харт
15

Давайте не будем думать только о безопасности или типобезопасности.

Причина, по которой вы используете параметризованные запросы, заключается в повышении производительности на уровне базы данных. С точки зрения базы данных параметризованный запрос - это один запрос в буфере SQL (если использовать терминологию Oracle, хотя я полагаю, что все базы данных имеют аналогичную внутреннюю концепцию). Таким образом, база данных может хранить в памяти определенное количество запросов, подготовленных и готовых к выполнению. Эти запросы не нужно анализировать, и они будут выполняться быстрее. Часто выполняемые запросы обычно находятся в буфере и не нуждаются в синтаксическом анализе каждый раз, когда они используются.

если

Кто-то не использует параметризованные запросы. В этом случае буфер постоянно очищается потоком почти идентичных запросов, каждый из которых должен быть проанализирован и запущен ядром базы данных, и производительность страдает от всех возможных, поскольку даже часто выполняемые запросы в конечном итоге повторно анализируются много раз. день. Я зарабатывал себе на жизнь настройкой баз данных, и это был один из самых больших источников низко висящих фруктов.

СЕЙЧАС

Чтобы ответить на ваш вопрос, ЕСЛИ ваш запрос имеет небольшое количество различных числовых значений, вы, вероятно, не вызовете проблем и на самом деле можете бесконечно улучшить производительность. ЕСЛИ, однако, потенциально существуют сотни значений и запрос часто вызывается, вы собираетесь повлиять на производительность вашей системы, поэтому не делайте этого.

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

mcottle
источник
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 не является общедоступным, вы можете вызывать другие общедоступные функции.

user1027167
источник
1
Вам даже не нужно делать это с помощью кода. Вы можете добавить инъекцию прямо в региональных настройках Windows. Смотрите мой ответ.
Каспарс Озолс
2
Кто может менять настройки сервера или кто может втирать такой код в сервер? Если человек может сделать это на вашем сервере, ему не потребуется SQL-инъекция для уничтожения данных.
Reza Aghaei
7

На мой взгляд, если вы можете гарантировать, что параметр, с которым вы работаете, никогда не будет содержать строку, это безопасно, но я бы не стал этого делать в любом случае. Кроме того, вы увидите небольшое снижение производительности из-за того, что вы выполняете конкатенацию. Я хотел бы задать вам вопрос: почему вы не хотите использовать параметры?

Максимум
источник
1
Дело не в том, что я не хочу использовать параметры, я использую параметры. Сотрудник написал подобный код, который я сегодня изменил для параметризации, что заставило меня задуматься над вопросом.
johnnyRose
Хорошо. Отлично. Рекомендуется использовать параметры. Таким образом, вам не придется беспокоиться о таких вещах, как внедрение sql. Кроме того, если вы создаете динамические запросы, вы также можете использовать параметры, независимо от того, насколько сложны ваши запросы. Просто используйте стиль @ 1 ... @ n при их создании. И добавьте их в коллекцию параметров с желаемым значением.
Макс
@johnyRose Есть еще один момент для использования параметров: программы развиваются и меняются. Вы можете использовать конкатенацию только для строки, но это не гарантирует, что кто-то реализует рефакторинг, который изменяет какой-либо тип параметра, и что изменения могут привести к уязвимости SQL Injection.
lerthe61
3

Это нормально, но никогда не безопасно .. и безопасность всегда зависит от входных данных, например, если входным объектом является TextBox, злоумышленники могут сделать что-то сложное, поскольку текстовое поле может принимать строку, поэтому вам нужно поставить какую-то проверку / преобразование чтобы иметь возможность предотвратить неправильный ввод пользователей. Но дело в том, что это небезопасно. Вот так просто.

Джапздивино
источник
Хотя это строка. Я говорю о других типах данных, таких как целые числа, логические значения или даты.
johnnyRose
@johnnyRose Ага, я видел выше очень хороший пример, который вы помечаете как ответ Каспардса ... и отличный ответ, поскольку он использует тип данных datetime в качестве примера, что необычно. :) Надеюсь, вы уже убедились, что использовать параметр в любых
типах
Я никогда не сомневался, что безопаснее использовать параметры. Мой вопрос касается строго типизированных реализаций.
johnnyRose 05
Ага .. я согласен. и это тоже отличный вопрос, который может помочь будущим читателям :)
japzdivino 05
-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 . Использование только одной страницы и не параметризованного значения ID. Я могу узнать имя каждой таблицы в вашей базе данных. После этого я могу искать важные таблицы. На это потребуется время, но это выполнимо.

Атилла Озгур
источник
2
Мой вопрос относится к строго типизированному языку. Хотя ваше объяснение отлично подходит для языков с гибкой типизацией, введенное значение по-прежнему является строкой.
johnnyRose
Никакое введенное значение не является целым. Вы получаете char и меняете его на целое число с помощью функции ASCII MySQL. Вы делаете то же самое в SQL Server, используя CAST (YourCharValue AS INT)
Атилла Озгур
Я имел в виду что-то вроде этого:public void QuerySomething(int id) { // this will only accept an integer }
johnnyRose
-3

Что ж ... одно можно сказать наверняка: безопасность - это НЕ нормально, когда вы объединяете строку (взятую пользователем) со строкой команды SQL. Не имеет значения, относится ли предложение where к Integer или к любому типу; инъекции могут произойти.

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

Предположим, у нас есть целое число в предложении where и:

  1. пользовательская переменная - это строка. Тогда хорошо, это не очень просто ввести (используя UNION), но очень легко обойти, используя атаки типа 'OR 1 = 1' ...

  2. Если пользовательская переменная является целым числом. С другой стороны, мы можем «проверить» прочность системы, пройдя тестирование с необычно большими числами на сбои системы или даже на скрытое переполнение буфера (в последней строке) ...;)

Возможно, параметры запросов или (даже лучше - imo) хранимых процедур не являются 100% безопасными для угроз, но они являются наименее необходимой мерой (или элементарной, если хотите) для их минимизации.

Андреас Веньерис
источник
Я думаю, вы могли неправильно понять вопрос. Я говорю о том, не являющихся -string типов.
Джонни Роуз
Привет, Джонни Роуз ... спасибо за записку. Я понимаю ваш вопрос, но я просто сформулировал свой ответ в более общей форме. Для случая, когда речь идет не о строках, проверьте мою точку (2). ;)
Андреас Веньерис