使用 Dapper 避免 Postgres sql 动态查询中的 SQL 注入

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

我在 postgres SQl 中有一个函数,它使用动态查询来搜索结果。我正在为任务使用参数化方法来避免 SQL 注入。下面是我的函数的片段。

CREATE OR REPLACE FUNCTION master."FilterFooBar"(
    "_Codes" character varying,
    "_Chapter" character varying)
    RETURNS TABLE("Foo" integer, "Bar" integer) 
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE PARALLEL UNSAFE
    ROWS 1000

AS $BODY$
DECLARE
    "_FromSql" TEXT;

BEGIN
    "_FromSql" := ' FROM 
                        master."FooBar" fb 
                    WHERE 
                        1 = 1';
                        
    IF "_Codes" IS NOT NULL
    THEN
        "_FromSql" := "_FromSql" || ' AND fb."Code" IN ('|| "_Codes" ||')';
    END IF;
    
    IF "_Chapter" IS NOT NULL
    THEN
        "_FromSql" := "_FromSql" || ' AND fb."Code" ILIKE '''|| "_Chapter" ||'%''';
    END IF;
    
    RETURN QUERY 
    EXECUTE
    ' SELECT fb."Foo",'|| ' fb."Bar",' || "_FromSql";
END
$BODY$;

这里的问题是这段代码

IF "_Chapter" IS NOT NULL
    THEN
        "_FromSql" := "_FromSql" || ' AND fb."Code" ILIKE '''|| "_Chapter" ||'%''';
END IF;

在测试过程中,我发现它存在SQL注入漏洞。如果我只是传递像

"_Chapter" = "01' or 8519=8519--"
这样的值,它会破坏我的代码。我认为 dapper 参数化方法会解决问题,但 dapper 不处理这种情况。是因为动态查询吗?

任何帮助表示赞赏。

postgresql sql-injection dapper dynamicquery
2个回答
0
投票

为什么不将动态 sql 放入 Dapper 然后使用参数应该通过抛出异常来保护您免受恶意代码的侵害(以下是未经测试的代码):

public IEnumerable<dynamic> FilterFooBar(string codes, string chapter)
{
    using (var connection = new NpgsqlConnection(connectionString))
    {
        var parameters = new DynamicParameters();
        parameters.Add("_Codes", codes);
        parameters.Add("_Chapter", chapter);

        var sql = @"SELECT fb.""Foo"", fb.""Bar""
                    FROM master.""FooBar"" fb
                    WHERE 1 = 1";

        if (!string.IsNullOrEmpty(codes))
        {
            sql += " AND fb.""Code"" IN (@_Codes)";
        }

        if (!string.IsNullOrEmpty(chapter))
        {
            sql += " AND fb.""Code"" ILIKE @_Chapter || '%'";
        }

        return connection.Query(sql, parameters);
    }
}

在您的应用程序中这样调用:

var results = FilterFooBar(codes, chapter);

0
投票

原来 Dapper 正在转义单引号来处理 SQL 注入,问题是动态查询。当像这样提供恶意参数时

'01'' or 8519=8519--'
这个声明
"_FromSql" := "_FromSql" || ' AND fb."Code" ILIKE '''|| "_Chapter" ||'%''';
被转换为
 AND fb."Code" ILIKE '01' or 8519=8519-- %;
.

为了解决这个问题,还有另一种编写动态查询的方法。而不是使用连接运算符 ||我们可以使用 $ 运算符进行替换。

例如上面的语句会转换为

"_FromSql" := "_FromSql" || ' AND hs."Code" LIKE $2 ||''%'' ';
,执行时可以传实参

RETURN QUERY 
EXECUTE
' SELECT fb."Foo",'|| ' fb."Bar",' || "_FromSql" 
  USING
      "_Codes", --$1
      "_Chapter"; --$2;

这将确保避免不必要的字符串终止

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