Как предотвратить Sql-инъекции в пользовательских Sql-запросах - PullRequest
4 голосов
/ 14 января 2009

У меня есть проект (частный, веб-сайт ASP.net, защищенный паролем с помощью https), в котором одно из требований заключается в том, чтобы пользователь мог вводить запросы Sql, которые будут напрямую запрашивать базу данных. Мне нужно иметь возможность разрешать эти запросы, не допуская, чтобы они наносили ущерб самой базе данных, а также не могли получить доступ или обновить данные, к которым они не смогут получить доступ / обновить.

Я разработал следующие правила для реализации:

  1. Используйте пользователя базы данных, который только имеет разрешение на выбор таблицы / просмотр и обновление таблицы (таким образом, любые другие команды, такие как drop / alter / truncate / insert / delete, просто не будут выполняться).
  2. Убедитесь, что выписка начинается со слов «Выбрать» или «Обновить»
  3. Убедитесь (используя Regex), что в выражении нет точек с запятой, которые не заключены в одинарные кавычки, пробелы и буквы. (Здесь мысль состоит в том, что единственный способ, которым они могут включить второй запрос, состоит в том, чтобы завершить первый точкой с запятой, которая не является частью входной строки).
  4. Убедитесь (используя Regex), что у пользователя есть разрешение на доступ к запрашиваемым / обновляемым таблицам, включенным в объединения и т. Д. Это включает любые подзапросы. (Частично способ, которым это будет достигнуто, состоит в том, что пользователь будет использовать набор имен таблиц, которые на самом деле не существуют в базе данных, часть синтаксического анализа запроса будет заключаться в замене в запросе правильных соответствующих имен таблиц) .

Я что-то упустил?

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

Ответы [ 15 ]

16 голосов
/ 14 января 2009

Это плохая идея, и не только с точки зрения предотвращения инъекций. Для пользователя, который не знает ничего лучше, случайно выполнить запрос, который приведет к захвату всех ресурсов базы данных (памяти / процессора), что эффективно приведет к атаке типа «отказ в обслуживании».

Если вы должны разрешить это, лучше оставить для этих запросов совершенно отдельный сервер и использовать репликацию, чтобы он был достаточно близко к точному зеркалу вашей производственной системы. Конечно, это не сработает с вашим требованием ОБНОВИТЬ.

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

4 голосов
/ 14 января 2009

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

В частности, ваша идея «убедиться (используя Regex), что у пользователя есть разрешение на доступ к запрашиваемым / обновляемым таблицам, включенным в объединения и т. Д.» Похоже, вы пытаетесь повторно реализовать функции безопасности, уже встроенные в базу данных.

4 голосов
/ 14 января 2009

что насчет этого, просто представьте, что выбор - это EXEC

select convert(varchar(50),0x64726F70207461626C652061)
3 голосов
/ 14 января 2009

Ну, у вас уже есть достаточно людей, говорящих вам "не делайте этого" , поэтому, если они не могут вас отговорить, вот несколько идей:

ВКЛЮЧАЕТ хорошее, не пытайтесь ИСКЛЮЧИТЬ плохое
(Я думаю, что правильная терминология - Белый список против Черный список ) Под этим я подразумеваю не ищите злых или недействительных вещей, чтобы выбросить (существует слишком много способов, которыми это можно было бы написать или замаскировать), вместо этого ищите допустимых вещей, чтобы включить и выбросить все остальное.

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

Я все еще склоняюсь к графическому пользовательскому интерфейсу какого-то рода: выберите таблицы для просмотра здесь, выберите поля, которые вы хотите видеть здесь, используйте некоторые раскрывающиеся списки для создания предложения where и т. Д. Больно, но все же наверное проще.

3 голосов
/ 14 января 2009

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

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

Короче говоря: Это монументально плохая идея!

2 голосов
/ 15 января 2009

Технология, кажущаяся безопасной, например, Dynamic LINQ, не защищена от проблем с внедрением кода , и вы говорите о предоставлении низкоуровневого доступа.

Независимо от того, насколько тщательно вы обрабатываете запросы и настраиваете разрешения, вероятно, вы все равно сможете заморозить вашу БД, отправив какой-либо запрос, интенсивно загружающий ЦП.

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

Другой вариант - просто попробуйте найти лучшую альтернативу (то есть, если вам действительно нужно обрабатывать и обновлять данные, почему бы не предоставить API, чтобы сделать это безопасно?)

2 голосов
/ 14 января 2009

Как указывают другие, позволить конечным пользователям делать это не очень хорошая идея. Я подозреваю, что на самом деле требование не в том, что пользователю действительно нужен специальный SQL, а скорее в способе получения и обновления данных способами, которые изначально не предусмотрены. Чтобы разрешить запросы, делайте так, как предлагает Джоэл, и сохраняйте базу данных «только для чтения», но используйте приложение для создания отчетов, такое как Microsoft Reporting Services или отчеты Data Dynamics Active, чтобы пользователи могли создавать и запускать специальные отчеты. Я полагаю, что у обоих есть способы представить пользователям фильтрованное представление «их» данных.

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

1 голос
/ 14 января 2009

Вопрос в том, доверяете ли вы своим пользователям? Если ваши пользователи должны были войти в систему, вы используете HTTPS и приняли меры предосторожности против атак XSS, тогда SQL-инъекция является меньшей проблемой. Выполнение запросов под ограниченной учетной записью должно быть достаточно, если вы доверяете законным пользователям. В течение многих лет я запускал MyLittleAdmin в Интернете, и до сих пор не было проблем.

Если вы запускаете под правильно ограниченной учетной записью SQL, выберите команду convert (varchar (50), 0x64726F70207461626C652061), и вы не сможете зайти слишком далеко, и вы сможете защититься от запросов на задержку ресурсов, установив короткий таймаут для запросов к базе данных. Люди все еще могут делать неправильные обновления, но тогда это просто возвращает вас к доверию своих пользователей?

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

1 голос
/ 14 января 2009

Вы можете нанести огромный урон с помощью заявления об обновлении.

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

1 голос
/ 14 января 2009

Одной (возможно, избыточной) опцией может быть использование компилятора для сокращенного языка SQL. Что-то вроде использования JavaCC с измененной грамматикой SQL, которая допускает только инструкции SELECT, тогда вы можете получить запрос, скомпилировать его, а если он скомпилируется, вы можете запустить его.

Для C # я знаю Ирония , но никогда не использовал его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...