使用Golang的Go-Redis驱动实现RedisSearch及防范注入攻击
使用Golang的Go-Redis驱动实现RedisSearch及防范注入攻击 我希望使用RedisSearch模块来支持如下代码所示的查询/搜索。
我使用的是Go-Redis驱动,据我所知,这个驱动(或者其他驱动?)没有参数化的方式来调用RedisSearch,因此你必须使用rdb.Do()命令。
这可能会暴露注入攻击的漏洞,因为这些值将由用户通过网站输入。
或许,我可以清理这些值以降低风险,但这也会给流程增加一个步骤和一个潜在的故障点。
有谁知道是否有其他方法可以以更参数化的方式实现这一点?
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"log"
)
var ctx = context.Background()
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
query := "FT.SEARCH housesIdx \"@suburb:{sydney} @price:[1000000 1200000] @bedrooms:[4 4] @garages:[1 1] @bathrooms:[2 2]\""
res, err := rdb.Do(ctx, query).Result()
if err != nil {
log.Fatalf("Error executing search query: %v", err)
}
fmt.Printf("Search results: %+v\n", res)
}
更多关于使用Golang的Go-Redis驱动实现RedisSearch及防范注入攻击的实战教程也可以访问 https://www.itying.com/category-94-b0.html
谢谢!我已经采纳了您的建议,将使用Postgres,并配合Go的Map和其他Go结构体/切片来实现缓存。
更多关于使用Golang的Go-Redis驱动实现RedisSearch及防范注入攻击的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
直接回答你的问题:你可以构建自己的检查。使用正则表达式检查用户输入中是否有异常内容,然后构建查询字符串。
-
你为什么使用Redis?在我看来,Go的一大优点是你可以访问goroutine之间的共享内存。不需要Redis。少了一个可能出问题或制造麻烦的东西需要操心。
-
如果你需要在内存中使用SQL,你也可以直接使用你喜欢的数据库(如Postgres或Maria)中的内存表。
此致
在Go-Redis中使用RedisSearch时,确实需要注意防范注入攻击。虽然Go-Redis没有专门的RedisSearch参数化方法,但可以通过以下方式安全构建查询:
package main
import (
"context"
"fmt"
"github.com/go-redis/redis/v8"
"log"
"strings"
)
var ctx = context.Background()
// 安全构建RedisSearch查询
func buildSafeSearchQuery(index string, filters map[string]string, numericRanges map[string][2]float64) string {
var queryParts []string
// 处理文本过滤条件
for field, value := range filters {
// 清理输入值,移除特殊字符
cleanValue := sanitizeRedisSearchValue(value)
queryParts = append(queryParts, fmt.Sprintf("@%s:{%s}", field, cleanValue))
}
// 处理数值范围条件
for field, rangeVals := range numericRanges {
queryParts = append(queryParts, fmt.Sprintf("@%s:[%v %v]", field, rangeVals[0], rangeVals[1]))
}
// 构建完整查询
queryString := strings.Join(queryParts, " ")
return fmt.Sprintf("FT.SEARCH %s \"%s\"", index, queryString)
}
// 清理RedisSearch值,防范注入攻击
func sanitizeRedisSearchValue(input string) string {
// 移除RedisSearch特殊字符
disallowed := []string{"\"", "'", "\\", "@", ":", "{", "}", "[", "]", "(", ")", "|", "-", "+", "*", "~", "$"}
result := input
for _, char := range disallowed {
result = strings.ReplaceAll(result, char, "")
}
return result
}
// 使用参数化方式执行查询
func executeSafeSearch(rdb *redis.Client, index string, filters map[string]string, numericRanges map[string][2]float64) (interface{}, error) {
query := buildSafeSearchQuery(index, filters, numericRanges)
return rdb.Do(ctx, query).Result()
}
func main() {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
})
// 示例:安全构建查询参数
filters := map[string]string{
"suburb": "sydney",
}
numericRanges := map[string][2]float64{
"price": {1000000, 1200000},
"bedrooms": {4, 4},
"garages": {1, 1},
"bathrooms": {2, 2},
}
// 执行安全查询
res, err := executeSafeSearch(rdb, "housesIdx", filters, numericRanges)
if err != nil {
log.Fatalf("Error executing search query: %v", err)
}
fmt.Printf("Search results: %+v\n", res)
}
对于更复杂的查询,可以使用结构化的查询构建器:
type RedisSearchQuery struct {
Index string
Filters []Filter
Ranges []RangeFilter
Options map[string]interface{}
}
type Filter struct {
Field string
Value string
}
type RangeFilter struct {
Field string
Min interface{}
Max interface{}
}
func (q *RedisSearchQuery) Build() string {
var parts []string
for _, filter := range q.Filters {
cleanValue := sanitizeRedisSearchValue(filter.Value)
parts = append(parts, fmt.Sprintf("@%s:{%s}", filter.Field, cleanValue))
}
for _, rng := range q.Ranges {
parts = append(parts, fmt.Sprintf("@%s:[%v %v]", rng.Field, rng.Min, rng.Max))
}
queryStr := strings.Join(parts, " ")
return fmt.Sprintf("FT.SEARCH %s \"%s\"", q.Index, queryStr)
}
// 使用示例
func exampleUsage() {
query := &RedisSearchQuery{
Index: "housesIdx",
Filters: []Filter{
{Field: "suburb", Value: "sydney"},
},
Ranges: []RangeFilter{
{Field: "price", Min: 1000000, Max: 1200000},
{Field: "bedrooms", Min: 4, Max: 4},
},
}
safeQuery := query.Build()
fmt.Println(safeQuery)
}
这些方法通过输入验证和结构化查询构建,可以有效防范RedisSearch注入攻击。

