DuckDB查询Pandas DataFrame是否存在SQL注入?如何防护?
DuckDB查询Pandas DataFrame的SQL注入风险与防护方案
一、是否存在SQL注入风险?
是的,完全存在风险。即使查询的是内存中的Pandas DataFrame,DuckDB依然会完整解析执行传入的SQL语句。如果用户输入未做处理直接通过字符串拼接(如format、f-string)插入SQL中,恶意输入可以篡改查询逻辑,甚至在特定场景下造成危害:
- 数据泄露:比如用户输入
"3 OR 1=1",拼接后的SQL会返回所有DataFrame数据; - 破坏查询关联对象:输入
"3; DROP VIEW temp_view;"(若存在注册的临时视图)会删除关联的内存对象; - 潜在系统风险:若DuckDB开启了危险扩展(如支持系统命令的功能),恶意输入可能执行系统级操作(默认配置下该风险极低,但仍需警惕)。
二、安全防护方案
你提到的参数化查询并非仅适用于"真实SQL连接",DuckDB针对内存DataFrame查询也提供了安全的参数化方式,以下是两种可靠方案:
方案1:直接使用duckdb.query的参数化能力
DuckDB的query函数支持通过parameters参数传递用户输入,使用占位符(?、$1)避免字符串拼接:
import duckdb import pandas as pd df_data = pd.DataFrame({'id': [1, 2, 3, 4], 'student': ['student_a', 'student_a', 'student_b', 'student_c']}) user_input = 3 # 用户输入内容 # 使用?作为占位符 result = duckdb.query("SELECT * FROM df_data WHERE id = ?", parameters=(user_input,)).df() # 或者使用$1位置占位符 result = duckdb.query("SELECT * FROM df_data WHERE id = $1", parameters=[user_input]).df()
方案2:注册临时视图后用连接执行参数化查询
将DataFrame注册为DuckDB的临时视图,再通过连接对象的execute方法执行参数化SQL,适合复杂查询场景:
import duckdb import pandas as pd df_data = pd.DataFrame({'id': [1, 2, 3, 4], 'student': ['student_a', 'student_a', 'student_b', 'student_c']}) user_input = 3 # 创建内存模式的DuckDB连接 con = duckdb.connect() # 将DataFrame注册为临时视图 con.register('df_data_view', df_data) # 参数化查询并获取结果 result_df = con.execute("SELECT * FROM df_data_view WHERE id = ?", (user_input,)).fetchdf() # 关闭连接 con.close()
三、为什么字符串拼接不可取?
以你提供的代码为例,如果用户输入不是数字3,而是恶意字符串"3 OR 1=1",拼接后的SQL会变成:
SELECT * FROM df_data WHERE id=3 OR 1=1
这会返回DataFrame中的所有数据,直接导致敏感信息泄露。若输入包含更复杂的恶意SQL片段,可能造成更严重的后果。
内容的提问来源于stack exchange,提问作者Herri15
相关产品推荐
相关产品推荐

