Предотвращение Внедрения SQL без параметров

В Kotlin вы можете сделать это:

private fun deleteImage(path: String) {
    val fDelete = File(path)
    if (fDelete.exists()) {
        if (fDelete.delete()) {
            MediaScannerConnection.scanFile(this, arrayOf(Environment.getExternalStorageDirectory().toString()), null) { path, uri ->
                Log.d("debug", "DONE")
            }
        } 
    }
}
108
задан Community 23 May 2017 в 11:54
поделиться

18 ответов

Я думаю, что правильный ответ:

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

Использовать параметры.

82
ответ дан 24 November 2019 в 03:29
поделиться

Было несколько уязвимостей (я не могу вспомнить, какая это была база данных), связанных с переполнением буфера оператора SQL.

Я хочу сказать, что SQL-инъекция - это больше, чем просто «избегайте цитаты», и вы не знаете, что будет дальше.

0
ответ дан 24 November 2019 в 03:29
поделиться

Вот несколько причин для использования параметризованных запросов:

  1. Безопасность - Уровень доступа к базе данных знает, как удалить или избежать элементов, которые не разрешены в данных.
  2. Разделение проблем - Мой код не отвечает за преобразование данных в формат, который нравится базе данных.
  3. Нет избыточности - мне не нужно включать сборку или класс в каждый проект, который выполняет это форматирование / экранирование базы данных; он встроен в библиотеку классов.
0
ответ дан 24 November 2019 в 03:29
поделиться

Я не видел, чтобы другие ответчики обращались к этой стороне вопроса «почему делать это самому - плохо», но рассмотрим атаку усечения SQL .

Существует также функция T-SQL QUOTENAME , которая может быть полезна, если вы не можете убедить их использовать параметры. Он улавливает множество (все?) Ускользнувших проблем qoute.

1
ответ дан 24 November 2019 в 03:29
поделиться

За очень короткое время, которое мне пришлось исследовать проблемы внедрения SQL, я вижу, что создание значения «безопасное» также означает, что вы закрываем дверь для ситуаций, когда вам действительно могут понадобиться апострофы в ваших данных - как насчет чьего-либо имени, например, O'Reilly.

Это оставляет параметры и хранимые процедуры.

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

1
ответ дан 24 November 2019 в 03:29
поделиться

Он может быть взломан, однако средства зависят от точных версий / исправлений и т. Д.

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

Другим средством в будущем будет обнаружение ошибок, аналогичных другим базам данных - например, в стеке MySQL / PHP возникла проблема с экранированием, потому что определенные последовательности UTF8 могут использоваться для управления функцией замены - функция замены будет обманута, введя , вводя символы инъекции.

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

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

1
ответ дан 24 November 2019 в 03:29
поделиться

Вот пара статей, которые могут помочь вам убедить своих коллег.

http://www.sommarskog.se/dynamic_sql.html

http: / /unixwiz.net/techtips/sql-injection.html

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

1
ответ дан 24 November 2019 в 03:29
поделиться

Я бы использовал хранимые процедуры или функции для всего, так что вопрос не возникнет.

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

2
ответ дан 24 November 2019 в 03:29
поделиться

Это безопасно только в том случае, если вам гарантировано, что вы собираетесь передать строку.

Что делать, если вы не передаете строку в какой-то момент? Что, если вы передадите только число?

http://www.mywebsite.com/profile/?id=7;DROP DATABASE DB

В конечном итоге станет:

SELECT * FROM DB WHERE Id = 7;DROP DATABASE DB
3
ответ дан 24 November 2019 в 03:29
поделиться

You aren't able to easily do any type checking of the user input without using parameters.

If you use the SQLCommand and SQLParameter classes to make you're DB calls, you can still see the SQL query that's being executed. Look at the SQLCommand's CommandText property.

I'm always a litle suspect of the roll-your-own approach to preventing SQL injection when parameterized queries are so easy to use. Second, just because "it's always been done that way" doesn't mean it's the right way to do it.

4
ответ дан 24 November 2019 в 03:29
поделиться

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

5
ответ дан 24 November 2019 в 03:29
поделиться

С параметризованными запросами вы получаете больше, чем защиту от внедрения sql. Вы также получаете лучший потенциал кэширования плана выполнения. Если вы используете профилировщик запросов sql server, вы по-прежнему можете видеть «точный sql, который выполняется в базе данных», поэтому вы ничего не теряете и с точки зрения отладки ваших операторов sql.

7
ответ дан 24 November 2019 в 03:29
поделиться

Итак, я бы сказал:

1) Почему вы пытаетесь заново реализовать что-то встроенное? он там, легко доступен, прост в использовании и уже отлажен в глобальном масштабе. Если в будущем в нем будут обнаружены ошибки, они будут исправлены и доступны всем очень быстро, и вам не придется ничего делать.

2) Какие процессы существуют, чтобы гарантировать , что вы никогда пропустите вызов SafeDBString? Отсутствие его всего в одном месте может вызвать целый ряд проблем. Сколько вы собираетесь наблюдать за этими вещами и учитывать, сколько зря потрачены впустую эти усилия, когда принятый правильный ответ так легко получить.

3) Насколько вы уверены, что вы прикрыли каждый вектор атаки, который Microsoft ( автор БД и библиотеки доступа) знает о вашей реализации SafeDBString ...

4) Насколько легко читать структуру sql? В примере используется + конкатенация, параметры очень похожи на string.Format, что более читабельно.

Кроме того, есть 2 способа выяснить, что было на самом деле запущено - сверните свою собственную функцию LogCommand, простую функцию с no проблемы безопасности , или даже посмотрите на трассировку sql, чтобы выяснить, что, по мнению базы данных, на самом деле происходит.

Наша функция LogCommand проста:

    string LogCommand(SqlCommand cmd)
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine(cmd.CommandText);
        foreach (SqlParameter param in cmd.Parameters)
        {
            sb.Append(param.ToString());
            sb.Append(" = \"");
            sb.Append(param.Value.ToString());
            sb.AppendLine("\"");
        }
        return sb.ToString();
    }

Верно или нет, она дает нам необходимую информацию без защиты проблемы.

10
ответ дан 24 November 2019 в 03:29
поделиться

Во-первых, ваш образец для версии "Заменить" неверен. Вам нужно заключить текст апострофами:

string sql = "SELECT * FROM Users WHERE Name='" + SafeDBString(name) & "'";
SqlCommand getUser = new SqlCommand(sql, connection);

Итак, параметры делают за вас еще одну вещь: вам не нужно беспокоиться о том, нужно ли заключать значение в кавычки. Конечно, вы можете встроить это в функцию, но тогда вам нужно добавить к функции много сложностей: как узнать разницу между NULL как null и NULL как просто строкой или между числом и строка, которая просто содержит много цифр. Это просто еще один источник ошибок.

Еще одна вещь - производительность: параметризованные планы запросов часто кэшируются лучше, чем составные планы, что, возможно, экономит серверу шаг при выполнении запроса.

Кроме того, экранирование одинарных кавычек не является ' t достаточно хорошо. Многие продукты БД позволяют использовать альтернативные методы экранирования символов, которыми может воспользоваться злоумышленник. В MySQL, например, вы также можете экранировать одинарную кавычку с помощью обратной косой черты. Таким образом, следующее значение "name" взорвало бы MySQL только с помощью функции SafeDBString () , потому что, когда вы удваиваете одинарную кавычку, первая все равно экранируется обратной косой чертой, а вторая остается "активной" :

x \ 'OR 1 = 1; -


Кроме того, JulianR поднимает полезный момент ниже: НИКОГДА НИКОГДА не пытайтесь самостоятельно выполнить работу по обеспечению безопасности. Очень легко ошибиться в программировании системы безопасности тонкими способами, что кажется работающим даже после тщательного тестирования. Затем проходит время, и год спустя вы обнаруживаете, что ваша система была взломана шесть месяцев назад, и вы даже не знали об этом до тех пор.

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

19
ответ дан 24 November 2019 в 03:29
поделиться

Аргумент безнадежный. Если вам все-таки удастся найти уязвимость, ваши коллеги просто изменят функцию SafeDBString, чтобы учесть ее, а затем попросят вас снова доказать, что это небезопасно.

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

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

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

27
ответ дан 24 November 2019 в 03:29
поделиться

И затем кто-то идет и использует "вместо". Параметры - это, ИМО, единственный безопасный путь.

Это также позволяет избежать множества проблем i18n с датами / числами; дата 01/02/03? Сколько 123 456? Согласованы ли ваши серверы (app-server и db-server) друг с другом?

Если фактор риска не убедит их, как насчет производительности? РСУБД может повторно использовать план запроса, если вы используете параметры, что способствует повышению производительности. Она не может сделать это только с помощью строки.

71
ответ дан 24 November 2019 в 03:29
поделиться

Полностью согласен по вопросам безопасности.
Еще одна причина использования параметров - эффективность.

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

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

2
ответ дан 24 November 2019 в 03:29
поделиться

Еще одно важное соображение - отслеживание экранированных и неэкранированных данных. Существует множество приложений, веб-сайтов и прочих, которые, похоже, не отслеживают должным образом, когда данные являются необработанными - Unicode, & -кодированными, отформатированными HTML и т. Д. Очевидно, что станет трудно отслеживать, какие строки '' –кодированы, а какие нет.

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

форматированный HTML и т. д. Очевидно, что станет трудно отслеживать, какие строки '' –кодированы, а какие нет.

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

форматированный HTML и т. д. Очевидно, что станет трудно отслеживать, какие строки '' –кодированы, а какие нет.

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

0
ответ дан 24 November 2019 в 03:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: