基本上,我试图在下面的代码中找到探索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为:“或”1“=”1
它的工作,程序返回给我我的第一个项目在表上(它不应该,因为我没有提供任何名称)
2-已尝试将board_name设置为:';删除Table BoardGames;它没有工作,mysql.connector.errors.InterfaceError:在执行多个语句时使用multi=True是向我提出的。
所以我的问题是“mysql.connector”是保护我免受大多数SQL注入?因为我没有将代码中的“multi”标记设置为True?你能告诉我其他方法来探索这段代码中的漏洞吗?除了1和2。
我想我知道如何解决SQL注入问题:**“connector.mycursor.execute(query,values)"**可能就可以完成这项工作。但是,我试图更好地了解什么样的SQL漏洞,我会与这个原始代码没有这个修复。
2条答案
按热度按时间z3yyvxxp1#
SQL注入并不总是恶意的。它可能会导致一个简单的错误,而不是删除所有的学生记录。
例如,如果您网站的某个合法用户名为“O 'Reilly”,那么您的代码格式将有一个不平衡的引号,这将是一个语法错误:
使用参数可以避免此类问题。查询参数不仅仅是一种快速插值变量的方法。它们要么转义动态内容中的特殊字符(默认情况下Python会这样做),要么完全成熟的参数将值与SQL查询分开,直到SQL服务器解析它之后。所以没有特殊字符会导致语法错误。
但是表名和其他标识符不能是参数。您只能使用参数来代替SQL值,就像您的示例中引用的字符串一样。
你说用户不能控制表名变量。很好,但还不够。
如果项目中的另一个程序员在调用您的
find_board_by_name()
函数时不小心,无意中传递了不安全的内容作为表名,该怎么办?请注意,不安全的内容不仅仅是用户输入。如果表名是SQL中的保留关键字怎么办?
如果表名包含空格或标点符号怎么办?还有其他风险。
您应该对函数进行编码,使其不信任其调用方。对于SQL值,当然要使用参数。对于其他动态元素(如表名),您必须将变量插入SQL字符串,但您可以采取防御措施:
(我更喜欢f-strings而不是现代Python中的
format()
)khbbv19g2#
即使允许执行多个语句,SELECT语句中的SQL注入也允许攻击者监视数据。
假设tablename有4列,注入
' UNION SELECT name, birthday, identity_nr, credit_card_nr FROM customers WHERE '1'='1
将允许攻击者从另一个表中窃取凭据。