Этот код предотвращает внедрение SQL?
Фон
Я заключил контракт на анализ существующего поставщика данных, и я знаю, что следующий код неисправен; но чтобы показать, насколько это плохо, мне нужно доказать, что он подвержен SQL-инъекции.
Вопрос
Какой параметр "Ключ" может сломать PrepareString
функция и позвольте мне выполнить DROP
заявление?
Фрагмент кода
Public Shared Function GetRecord(ByVal Key As String) As Record
Dim Sql As New StringBuilder()
With Sql
.Append("SELECT * FROM TableName")
If String.IsNullOrEmpty(Agency) Then
.Append(" ORDER BY DateAdded")
Else
.Append(" WHERE Key = '")
.Append(PrepareString(Key))
.Append("'")
End If
End With
Return ExecuteQuery(Sql.ToString())
End Function
Public Shared Function PrepareString(ByVal Value As String) As String
Return Value.Replace("''", "'") _
.Replace("'", "''") _
.Replace("`", "''") _
.Replace("´", "''") _
.Replace("--", "")
End Function
7 ответов
В ответ на ваш прямой вопрос: предотвращает ли этот код внедрение SQL: Нет
Вот доказательство - протолкните эту строку через метод PrepareString:
Dim input = "'" & Chr(8) & "; Drop Table TableName; - " & Chr(8) & "-"
Dim output = PrepareString(input)
Console.WriteLine(input)
Console.WriteLine(output)
Я изменил метод GetRecord, который вы опубликовали, чтобы он возвращал полностью подготовленную строку SQL, а не получал запись из базы данных:
Console.WriteLine(GetRecord(output))
И это выход
Input = ; Drop Table TableName; --
Output = '; Drop Table TableName; --
Query = SELECT * FROM TableName WHERE Key = ''; Drop Table TableName; --'
Добавьте 1 дополнительную строку кода:
My.Computer.Clipboard.SetText(input)
И у вас есть строка, которую нужно скопировать прямо в буфер обмена, чтобы вставить в поле ввода на веб-сайте для завершения SQL-инъекции:
'; Drop Table TableName; - -
[Отметив, что управляющие символы были опущены в выводе поста Stackru, поэтому вам придется следовать примеру кода для создания выходных данных]
После запуска метода PrepareString он будет иметь точно такой же вывод - код Chr(8) ASCII - это обратная область, которая удалит лишние "", которые вы добавляете к моему, что закроет вашу строку, а затем я свободно добавлять все, что я хочу в конце. Ваша PrepareString не видит моего - потому что я на самом деле использую - символа возврата, чтобы убрать пробел.
Полученный в результате код SQL, который вы создаете, будет беспрепятственно выполнять мой оператор Drop Table и быстро игнорировать остальную часть вашего запроса.
Самое интересное в том, что вы можете использовать непечатаемые символы, чтобы обойти любую проверку символов, которую вы можете придумать. Поэтому безопаснее использовать параметризованные запросы (это не то, что вы просили, но лучший способ избежать этого).
Чтобы ответить на ваш сомнительный вопрос, нет, это не сработает.
.Replace("``", "''")
будет предотвращать законные запросы с помощью `` '
.Replace("´", "''")
будет предотвращать законные запросы с "´"
.Replace("--", "")
будет препятствовать законным запросам с '-' в них
.Replace("''", "'")
неправильно изменил бы законные запросы с '' '' в них
и так далее.
Кроме того, полный набор escape-символов может варьироваться от одной RDBMS к другой. Параметризованные запросы FTW.
Я думаю, что это не повезло, если вы просто замените "на". Я слышал, что возможно изменить символ escape-кавычки, который потенциально может нарушить это, однако я не уверен. Я думаю, что вы в безопасности, хотя.
Я думаю, что это безопасно (по крайней мере, на сервере SQL), и я также думаю, что единственное, что вам действительно нужно сделать, это s = s.Replace("'", "''")
, Конечно, вы должны использовать параметризованные запросы, но вы уже знаете это.
Эта статья MSDN охватывает большинство вещей, на которые нужно обратить внимание (я боюсь сказать все, что касается внедрения SQL).
Но я буду повторять всеобщее мнение о параметрах параметров параметров.
Что касается вашего примера, некоторые ошибки [Правка: Обновил эти]:
не будет ли строка "1 ИЛИ 1=1" позволить пользователю вернуть всеили хуже "1; удалить таблицу sometablename"
Согласно статье вы хотите проверить:
; - разделитель запросов.
'- символьный разделитель строк данных.
- Разделитель комментариев.
/ *... / - Разделители комментариев. Текст между / и */ не оценивается сервером.
xp_ - используется в начале имени расширенных по каталогу хранимых процедур, таких как xp_cmdshell.
Вы пытаетесь создать черный список символов для реализации собственной версии SQL Escaping. Я бы посоветовал просмотреть этот URL - экранирование SQL не обязательно является наихудшим выбором (т. Е. Быстрое исправление существующих приложений), но это нужно сделать правильно, чтобы избежать уязвимостей.
Этот URL-адрес ссылается на другую страницу для выхода в SQL Server, где автор дает советы, которые помогут вам избежать уязвимостей без ограничения функциональности.
Если это помогает, статьи предлагают также избегать скобок (я называю их квадратными скобками - но []).
Если вы попытаетесь использовать свой код, кто-то может передать ключ (; выберите * из таблицы; и получите список любой таблицы, которую они хотят.
В вашем коде вы не проверяете точку с запятой, которая позволяет вам завершить оператор t-sql и запустить другой.
Я бы пошел с параметризованным запросом.