提问人:digoalbuq2 提问时间:9/24/2023 最后编辑:digoalbuq2 更新时间:9/25/2023 访问量:67
SQL注入 - Python中文版 - MySQL
SQL Injection - Python - MySQL
问:
基本上 我正在尝试在下面提供的代码中找到探索 SQL 注入漏洞的方法。代码还有另一层,即表示,它要求用户输入board_name。 Table_name 是一个内部变量,用户无法控制它。
def find_board_by_name(cls, connector, board_name, table_name: str):
query = "SELECT * FROM {} WHERE name = '{}'".format(table_name,board_name.title())
print(query)
try:
connector.mycursor.execute(query)
res = connector.mycursor.fetchone()
if res:
return res[1]
return None
except Exception as e:
raise e
尝试:
1- board_name为:' OR '1'='1
它奏效了,程序将桌子上的第一个项目返回给我(它不应该,因为我没有提供任何名称)
2-试图将board_name写为:“;删除桌面棋盘游戏; 它不起作用,mysql.connector.errors.InterfaceError:执行多个语句时使用 multi=True 呈现给我。
所以我的问题是“ mysql.connector”正在保护我免受大多数SQL注入的侵害?因为我没有将代码中的“multi”标签设置为 True?您能告诉我探索此代码中漏洞的其他方法吗?除了 1 和 2.
我想我知道如何解决SQL注入问题:“connector.mycursor.execute(query, values)”可能会完成这项工作。但是,我试图更好地了解如果没有此修复程序,我使用此原始代码会遇到什么样的 SQL 漏洞。
答:
SQL 注入并不总是恶意的。这可能会导致一个简单的错误,而不是删除所有学生记录。
例如,如果您网站的某个合法用户名为“O'Reilly”,那么您的代码格式将具有不平衡的引号,这将是语法错误:
SELECT * FROM tablename WHERE name = 'O'Reilly'
^ wtf
使用参数可以避免此类问题。查询参数不仅仅是插值变量的快速方法。它们要么对动态内容中的特殊字符进行转义(默认情况下 Python 会这样做),要么将完整的参数将值与 SQL 查询分开,直到 SQL 服务器对其进行分析。因此,任何特殊字符都不会导致语法错误。
但表名和其他标识符不能是参数。您只能使用参数来代替 SQL 值,例如示例中带引号的字符串。
您说用户无法控制表名变量。这很好,但还不够。
如果项目中的其他程序员在调用函数时不小心,无意中将不安全的内容作为表名传递,该怎么办?请注意,不安全的内容不仅仅是用户输入的内容。find_board_by_name()
如果表名是 SQL 中的保留关键字怎么办?
SELECT * FROM order WHERE name = ?
^ syntax error
如果表名包含空格或标点符号怎么办?还有其他风险。
您应该对函数进行编码,使其不信任其调用方。对于 SQL 值,当然要使用参数。对于其他动态元素(如表名),您必须将变量插入 SQL 字符串中,但您可以采取防御措施:
使用允许列表验证表名是否为合法的已知表名。
在 SQL 中用反引号分隔表名,以防万一它是保留字或不是简单的标识符。
legit_table_names = Set(['table1', 'table2', 'table3']) if table_name not in legit_table_names: return error # pseudocode query = f"SELECT * FROM {table_name} WHERE name = %s"
(我更喜欢 f 字符串而不是现代 Python)format()
即使允许执行多个语句,SELECT 语句中的 SQL 注入也允许攻击者窥探数据。
假设 tablename 有 4 列,注入将允许攻击者从另一个表窃取凭据。' UNION SELECT name, birthday, identity_nr, credit_card_nr FROM customers WHERE '1'='1
评论
multi=True
multi=False