很抱歉在这里提问,但我找不到太多关于pymysql的安全指南的参考资料,该指南介绍了如何防止sql注入,当我开发PHP时,我知道使用mysqlpreparedstatement(或称为参数化查询或stmt(,但我在pymysql中找不到关于这方面的参考
简单的代码使用类似于的pymysql
sqls="select id from tables where name=%s"
attack="jason' and 1=1"
cursor.execute(sqls,attack)
我如何知道这是否可以防止sql注入攻击?如果预防成功,pymysql如何预防?默认情况下,cursor.execute是否已使用preparedstatement?
Python驱动程序不使用真正的查询参数。在python中,在将SQL发送到数据库服务器之前,将参数(示例中的变量attack
(插入到SQL字符串中。
这与使用查询参数不同。在真正的参数化查询中,SQL字符串被发送到数据库服务器,参数占位符保持不变。
但是Python驱动程序在插值时确实正确地转义了参数,这可以防止SQL注入。
当我打开查询日志时,我可以证明这一点:
mysql> SET GLOBAL general_log=ON;
并在运行Python脚本时跟踪日志:
$ tail -f /usr/local/var/mysql/bkarwin.log
...
180802 8:50:47 14 Connect root@localhost on test
14 Query SET @@session.autocommit = OFF
14 Query select id from tables where name='jason' and 1=1'
14 Quit
您可以看到,查询中插入了值,嵌入的引号字符前面有一个反斜杠,这可以防止它成为SQL注入向量。
我实际上在测试MySQL的Connector/Python,但pymysql也做同样的事情。
我不同意Python连接器避免使用真实查询参数的设计决定(即,真实参数的工作方式是将SQL查询发送到带有参数占位符的数据库,并分别发送这些参数的值(。风险在于,程序员会认为将参数插入查询字符串的任何字符串都将与您让驱动程序执行时相同。
SQL注入漏洞示例:
attack="jason' and '1'='1"
sqls="select id from tables where name='%s'" % attack
cursor.execute(sqls)
日志显示这导致了SQL注入:
180802 8:59:30 16 Connect root@localhost on test
16 Query SET @@session.autocommit = OFF
16 Query select id from tables where name='jason' and '1'='1'
16 Quit