SELECT * FROM table1 WHERE year_month BETWEEN '2021-08' AND '2022-01';
update table2 set note_description = 'test @8:57am', patient_id = '5840', note_updated_by = '10000019', note_update_date = '2022-07-13 09:45:49' where note_id = '639'
现在我的后端查询可以被SQL注入攻击,所以我想避免SQL注入在上面的查询中,我想把参数从查询中分离出来,并用特殊字符替换它,这样我就可以避免sql注入,如果有任何包或任何东西来做它。
如果您收到的SQL语句中已经连接了参数,那么这是错误的地方来解决您的问题-没有办法安全地解析语句并从查询中分离出参数。
您应该在代码中找到将参数连接到语句中的位置,并利用准备好的语句/参数化查询安全地传递/绑定参数。
如果这是不可能的(例如,因为代码的结构只是沿着语句传递),一个不太理想的替代方法是在连接参数之前对参数进行编码/引用,同时确保它们在语句中都被引用。如何做这部分将取决于所使用的数据库/语言。
我见过一个这样做的产品:pt-query-digest。它是一个免费的工具,可以解析MySQL查询日志,并生成运行每个查询所花费的总时间报告。为此,它必须建立一个查询"指纹"。这允许它对除了常量值以外的相同查询进行分组。如SELECT * FROM mytable WHERE id = 123
与SELECT * FROM mytable WHERE id = 456
具有相同的指纹
这意味着它必须解析查询并用占位符?
替换每个常量值,如数字或字符串文字。在IN()
谓词的情况下,它用?+
替换值列表。它还减少了空白和删除注释。
这是相当多的代码,大约100行Perl代码:https://github.com/percona/percona-toolkit/blob/3.x/lib/QueryRewriter.pm#L139-L248尽管如此,该函数前面有一个注释,开发人员承认它并不完美,可能会错过某些情况。使用正则表达式实现递归下降解析器既不高效也不正确。
但这可能不是你想要做的。您不应该从具有常量值的查询开始,然后将它们变成参数化查询。您应该根据需要自己设计参数化查询。
并不是SQL查询中的每个常量值都必须参数化。只有那些不是固定值的。也就是说,如果需要将客户机代码中的变量组合到SQL查询字符串中,并且不能保证该变量是安全的,则使用参数。如果查询具有固定的常数值(不是从变量插入的),那么它可以保留在查询中。如果查询的值来自于一个变量,但是该变量是安全的,并且永远不会被不可信的输入污染,那么它可以保留在查询中。由你来做这些判断更可靠、更经济。你比任何自动化系统都更了解代码和上下文。