提问人:Learning from masters 提问时间:3/24/2022 更新时间:3/24/2022 访问量:3730
SQL 清理 python [重复]
SQL sanitize python [duplicate]
问:
在使用 python 时,清理 SQL 以防止注入的最佳方法是什么?我正在使用mysql-connector。我已经读到我应该使用类似于以下内容的结构:
import mysql.connector
connection = mysql.connector.connect(host="", port="", user="", password="", database="")
cursor = connection.cursor( buffered = True )
sql = "INSERT INTO mytable (column1, column2) VALUES (%s, %s)"
val = (myvalue1, myvalue2)
cursor.execute(sql, val)
connection.commit()
但是,我不明白为什么这会阻止注射。这够了吗?用户可以在 myvalue1 或 myvalue2 上向我介绍任何内容,即使它不应该这样做。有什么有用的图书馆吗?
答:
当不受信任的输入入到 SQL 查询中并且输入包含更改查询语法的字符时,SQL 注入将起作用。
查询参数与 SQL 查询分开,从不插入其中。参数的值在解析后与 SQL 查询合并,因此不再有任何更改语法的机会。该参数保证被视为单个标量值(即,就好像它只是 SQL 表达式中的字符串文字一样)。
如果使用 cursor 子类,这就是 Python 连接器的工作方式。查看 https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursorprepared.htmlMySQLCursorPrepared
否则,Python 连接器将“模拟”准备好的查询。它实际上在解析 SQL 查询之前将参数插值到 SQL 查询中,但它通过转义会导致 SQL 注入的特殊字符来安全地这样做。它经过充分测试,因此很可靠。
两种游标类型的使用方式相同,传递一个带有占位符的 SQL 查询字符串,以及另一个带有参数值元组的参数。您正在正确使用它。%s
来自@Learningfrommasters的回复:
是的,存储在数据库中的字符串可能会在另一个 SQL 查询中不安全地使用,并导致 SQL 注入。有些人认为只有用户输入必须得到安全处理,但事实并非如此。任何变量都应被视为查询参数,无论该变量的值来自用户输入,还是从文件中读取,甚至是从您自己的数据库中提取。
示例:假设我的名字是 Bill O'Karwin。它有一个撇号,你知道它是 SQL 的一个特殊字符,因为它终止了一个字符串文字。
如果我的名字存储在数据库中,然后以变量的形式提取到应用程序中,那么我可以搜索具有相同姓氏的其他人:userlastname
sql = f"SELECT * FROM Users WHERE lastname = '{userlastname}'"
这是不安全的,因为撇号会导致SQL注入。尽管该值不是直接来自用户输入,但它来自我自己的数据库。
因此,对所有变量使用参数。然后,您不必考虑来源是否安全。
sql = "SELECT * FROM Users WHERE lastname = %s"
cur.execute(sql, (userlastname,))
评论