提问人:Faraaz 提问时间:4/3/2023 最后编辑:Faraaz 更新时间:4/5/2023 访问量:296
避免使用 Dapper 在 Postgres sql 动态查询中注入 SQL
Avoid SQL injection in Postgres sql dynamic query using Dapper
问:
我在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注入的影响。如果我只是传递值,它会破坏我的代码。我以为 dapper 参数化方法可以解决问题,但 dapper 不能处理这种情况。是因为动态查询吗?"_Chapter" = "01' or 8519=8519--"
任何帮助都是值得赞赏的。
答:
0赞
Adrian Maxwell
4/3/2023
#1
为什么不将动态 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赞
Faraaz
4/3/2023
我不能这样做,因为我们的应用程序只使用函数,所以我必须只在函数中编写整个代码。
0赞
Adrian Maxwell
4/3/2023
你的函数是纯postgres,所以如果你传入恶意代码,你将执行恶意代码。你根本没有利用 dapper。在问题下方的评论中,我提供了一个网址。试试看。
1赞
Faraaz
4/5/2023
#2
事实证明,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;
这将确保避免不必要的字符串终止
评论