Действительно ли CallableStatement невосприимчив к SQL-инъекциям?

StackOverflow https://stackoverflow.com//questions/21053535

Вопрос

У нас есть приложение Java, которое связывается с несколькими базами данных SQL Server в одном и том же поле.Количество и названия этих баз данных различаются.По большому счету, мы используем почти исключительно хранимые процедуры с CallableStatement для доступа к базам данных.Мы очень хорошо избегаем SQL-инъекций и используем переменные связывания.

Единственное, что вызывает беспокойство, это то, что само имя базы данных объединяется с SQL, который мы передаем в CallableStatement как таковой:

"{call [" + dbName + ".dbo." + procName + "(?, ?, ?)}"

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

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

Я установил для него следующее значение, чтобы производить следующие вызовы SQL (имена таблиц и процедур изменены для защиты невиновных):

securitytest].nx_proc()};delete from poor_victim_table;

становится

{call [securitytest].nx_proc()};delete from poor_victim_table;].dbo.proper_proc_name()}

и

securitytest].nx_proc()};exec('delete from poor_victim_table');

становится

{call [securitytest].nx_proc()};exec('delete from poor_victim_table');].dbo.proper_proc_name(?,?,?,?,?,?,?)}

Результаты в Incorrect syntax near ')'. и poor_victim_table все еще есть строки.я использовал truncate table, drop table и drop database и когда они не сработали, я перешел на простые delete чтобы исключить настройки безопасности.

Если я использую процедуру, которая принимает параметры привязки, я всегда получаю несоответствие между количеством ожидаемых параметров и предоставленными параметрами, такими как The index 1 is out of range..

securitytest]};exec('delete from poor_victim_table');

становится

{call [securitytest]};exec('delete from poor_victim_table');].dbo.proper_proc_name(?,?,?,?,?,?,?)}

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

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

После некоторого исследования этого вопроса, лучшее, что я придумал, это вопрос о stackoverflow: SQL-инъекция – нет опасности при вызове хранимой процедуры (в iSeries)?.Кажется, он поддерживает использование CallableStatement, поскольку он защищает вас от SQL-инъекций. если только ваш код процедуры не создает динамический SQL из входного параметра.

Итак, мой вопрос к сообществу: если предположить, что код SQL в процедуре безопасен, действительно ли использование CallableStatement в JDBC предотвращает внедрение SQL?Или драйвер SQL Server анализирует строку таким образом, чтобы это предотвратить, а другие драйверы - нет?Или я недостаточно стараюсь?

Если это безопасно, то как обеспечивается эта гарантия?Это из-за абстрактного синтаксиса использования { call blah(?) } который не является настоящим SQL, но переводится в SQL?

Это было полезно?

Решение

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

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

Другие советы

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top