如何防止FT.SEARCH中的查询注入?

问题描述 投票:0回答:1

当使用redis-py客户端对用户提供的

query_str
(不是Redis
query
参数格式,而是要搜索的文本本身)执行全文搜索时仅在特定字段
 text
在 Redis Stack 服务器上,我担心使用字符串插值会使自己暴露于查询注入。那么在这种情况下避免查询注入的最佳实践是什么?

准确来说,对于客户端来说,这个问题应该是与语言无关的,但我会专门用Python来演示这个问题。

from redis import Redis
from redis.commands.search.query import Query

client = Redis.from_url("redis://localhost:6379")

def search_1(query_str: str):
    query = Query(f"@text:{query_str}")
    return client.ft("idx:test").search(query)

def search_2(query_str: str):
    params = {"query_str": query_str}
    query = Query("@text:$query_str").dialect(2)
    return client.ft("idx:test").search(query, params)

search_1()
中,
query_str
直接连接到
query
 命令的 
FT.SEARCH
参数。因此,假设用户提供了
query_str = "query_for_text @other_field:query_for_other_field"
,实际执行的命令将类似于
FT.SEARCH "@text:query_for_text @other_field:query_for_other_field"
。因此,它偏离了我的规范,只在字段
text
上执行搜索,并且还搜索另一个字段

我相信

search_2()
,利用
PARAMS
FT.SEARCH
参数可以解决这个问题。关于
FT.SEARCH
PARAMS
文档中指出

搜索查询中对参数名称的每个此类引用都将替换为相应的参数值。

您不能在查询字符串中引用不允许具体值的参数,例如在字段名称中,例如

@loc

虽然文档对此不是很明确,但我认为“替换”并不意味着字符串插值,而是将特定参数的整体视为整个“短语”进行搜索,这也得到了证实我的实验。 我想确认是否是这样。

我确实看过Redis安全性是否可以对redis查询运行字符串注入攻击?。我相信我的问题与Redis协议防止的注入不同,我将其理解为防止Redis客户端发送到服务器的消息中的注入(用户在输入中输入转义字符假设Redis协议使用转义字符,这它没有)。

a Github Issue中,除了使用

PARAMS
之外,还有手动转义输入
query_str
的解决方案。因此,处理用作查询一部分的未经消毒的用户输入的最佳实践是什么?

python redis redis-py redisearch
1个回答
0
投票
  1. 将您的查询模板替换为
    f"@text:({query_str})"
    (并包含括号)。
  2. 从括号中删除用户输入:
    query_str = query_str.replace('(', '').replace(')', '')
  3. 使用
    DIALECT 2

使用

DIALECT 2
,文本表达式括号内不允许有其他子查询。查询只能是术语的交集或并集。

通过去掉任何括号,您就消除了有人会这样做的可能性 尝试使用像

opener) @injection:... (closer
这样的命令。

除此之外,您应该进一步解析用户输入。如果不解析用户的输入,很难相信用户输入会与他们想要查找的内容相匹配。您是否想在术语之间添加

|
以匹配至少包含其中一个而不是全部的任何文档?您是否应该将某些术语标记为可选,以便在文档中缺少这些术语时不会取消它们的资格?

© www.soinside.com 2019 - 2024. All rights reserved.