Как я могу предотвратить инъекцию SQL с произвольной строкой запроса JSONB, предоставленной внешним клиентом? - PullRequest
1 голос
/ 06 августа 2020

У меня есть базовая c служба REST, поддерживаемая базой данных PostgreSQL с таблицей с различными столбцами, один из которых является столбцом JSONB, содержащим произвольные данные. Клиенты могут хранить данные, заполняющие фиксированные столбцы, и предоставлять любые JSON в виде непрозрачных данных, которые хранятся в столбце JSONB.

Я хочу разрешить клиенту запрашивать базу данных с ограничениями как для фиксированных столбцов, так и для JSONB. Некоторые параметры запроса, такие как ?field=value, легко перевести в параметризованный запрос SQL для фиксированных столбцов, но я хочу добавить произвольный запрос JSONB к SQL.

Эта строка запроса JSONB может содержать инъекцию SQL, как я могу предотвратить это? Я думаю, что, поскольку структура данных JSONB произвольна, я не могу использовать параметризованный запрос для этой цели. Вся документация, которую я могу найти, предполагает, что я использую параметризованные запросы, и я не могу найти никакой полезной информации о том, как на самом деле дезинфицировать саму строку запроса, что кажется моим единственным вариантом.

Например, похожий вопрос: : Как предотвратить SQL инъекцию в PostgreSQL поле JSON / JSONB?

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

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

edit: некоторые примеры запросов к JSONB, которые может выполнить клиент:

(content->>'company') is NULL
(content->>'income')::numeric>80000
content->'company'->>'name'='EA' AND (content->>'income')::numeric>80000
content->'assets'@>'[{"kind":"car"}]'
(content->>'DOB')::TIMESTAMP<'2000-01-30T10:12:18.120Z'::TIMESTAMP
EXISTS (SELECT FROM jsonb_array_elements(content->'assets') asset WHERE (asset->>'value')::numeric > 100000)

Обратите внимание, что они не охватывают все возможные типы запросов. В идеале я хочу, чтобы был разрешен любой запрос, который PostgreSQL поддерживает в данных JSONB. Я просто хочу проверить запрос, чтобы убедиться, что он не содержит инъекции sql. Например, упрощенным c и, вероятно, неадекватным решением было бы не допускать никаких ";" в строке запроса.

1 Ответ

0 голосов
/ 06 августа 2020

Вы можете разрешить пользователям указывать путь в документе JSON, а затем параметризовать этот путь в вызове такой функции, как json_extract_path_text. То есть предложение WHERE будет выглядеть так:

WHERE json_extract_path_text(data, $1) = $2

Аргумент пути - это просто строка, легко параметризуемая, которая описывает ключи для перехода к заданному значению, например 'foo.bars[0].name'. Правая часть предложения будет параметризована в соответствии с теми же правилами, которые вы используете для фильтрации фиксированных столбцов.

...