【问题标题】:How do PyMySQL prevent user from sql injection attack?PyMySQL如何防止用户遭受sql注入攻击?
【发布时间】:2019-01-09 20:27:23
【问题描述】:

很抱歉在这里询问,但我找不到太多关于 pymysql 的安全指南关于我们如何防止 sql 注入的参考, 当我做 PHP 开发时,我知道使用 mysql 准备语句(或称为参数化查询或 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?

【问题讨论】:

  • 攻击 sql 应该是 "jason' and 1='1" 我认为
  • 要成为一个重要的 SQL 注入,它应该是 "jason' OR 1='1"。如果使用 AND,结果不会改变。

标签: python sql-injection pymysql server-side-attacks


【解决方案1】:

Python 驱动程序不使用真正的查询参数。在 python 中,参数(在您的示例中为变量attack)在将 SQL 发送到数据库服务器之前被插入到 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  

【讨论】:

  • 这难道不是您围绕低级驱动程序创建包装器以提供高级接口和数据验证的原因吗?
  • 如果编写包装器的开发人员了解如何编写安全代码,那么可以。
  • 谢谢Karwin,这解决了我的困惑,很高兴收到你的回答,祝你有美好的一天!
  • 很高兴为您提供帮助。顺便说一句,在 Stack Overflow 上,通常会投票或接受对您有帮助的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-19
  • 1970-01-01
  • 2015-10-03
  • 2019-08-10
  • 2020-02-24
  • 2014-12-08
  • 2015-04-14
相关资源
最近更新 更多