Попытка предотвратить внедрение SQL при динамической ссылке на пакет Oracle с помощью JPA - PullRequest
0 голосов
/ 28 декабря 2018

Я прошел немного по дорожке и ударил стену о том, как этого можно достичь.

По сути, запрос строится с использованием JPA и передается в БД Oracle.На БД есть Пакет, используемый для генерации ссылки, который имеет динамическое имя в зависимости от среды.Это значение доступно для редактирования пользователем и хранится как свойство БД в приложении.У меня нет никакого контроля над архитектурой этого.

На этапе до JPA строка запроса генерируется с использованием ссылочного значения для пакета, который устанавливается как свойство (опять же, я могуне изменить способ, которым это было разработано).Я настроил это, используя Query метод setParameter(), например так:

(псевдокод, заменяющий несущественные части для сфокусированного контекста)

String referenceRef = [ reference is fetched from DB properties ];

String queryString = "SELECT ?1 FROM sys.dual";
final Query myQuery = getEntityManager().createNativeQuery( queryString );
myQuery.setParameter( 1, referenceRef );

return myQuery.getSingleResult();

Я довольномногие делали это как рефлекс, только чтобы понять (в ретроспективе, совершенно очевидно), что это на самом деле не сработает, так как это экранирование от элемента, который не должен быть экранирован ...

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

Возможно ли достичь этого без создания целого куска дополнительного кода?Все, что я в настоящее время могу думать, как альтернатива, это запросить dba_procedures для всех объектов пакета, которые соответствуют, и использовать результат этого запроса для построения queryString (следовательно, обходить круг с использованием любых редактируемых пользователем значений), но этотакое чувство, что оно будет запутанным.Это альтернатива, которую я использую вместо улучшения:

final String verifyReference = "SELECT object_name FROM "
            + "dba_procedures WHERE object_type = 'PACKAGE' AND object_name =?1";
final Query refQuery = getEntityManager().createNativeQuery( verifyReference );

refQuery.setParameter( 1, referenceRef );
final String result = refQuery.getSingleResult();

final String queryString = "SELECT " + result + " FROM sys.dual";
final Query myQuery = getEntityManager().createNativeQuery( queryString );

return myQuery.getSingleResult();

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

(Как уже упоминалось в комментариях, этот вид предназначен дляSQL-инъекция, но она должна предотвращать «SQL-инъекцию» как определение, не позволяющее манипулировать БД вне проекта с использованием непреднамеренного значения.)

1 Ответ

0 голосов
/ 28 декабря 2018

Представление словаря Oracle all_procedures содержит список всех процедур, доступных текущему пользователю.

Специально в представлении есть столбцы OWNER, OBJECT_NAME (=package name), PROCEDURE_NAME.

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

select 
 ?
from dual where exists (
  select null from all_procedures
  where 
   OWNER||'.'||OBJECT_NAME||'.'||PROCEDURE_NAME = upper(?) and
  object_type = 'PACKAGE');

Вам придется дважды связать один и тот же входной параметр.

Запросвозвращает no data, если нет процедуры с данным именем, поэтому вы можете вызвать исключение.

В приведенном выше запросе ожидается полное имя хранимой процедуры, т.е. owner.package.procedure, вам придется адаптировать егонемного, если вы разрешите неквалифицированные имена (без owner).

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