【问题标题】:Is this python/mysql query susceptible to SQL injection这个 python/mysql 查询是否容易受到 SQL 注入的影响
【发布时间】:2020-03-02 07:30:05
【问题描述】:

我目前正在审查某人的代码,我遇到了以下 Python 行:

db.query('''SELECT foo FROM bar WHERE id = %r''' % id)

这违背了我的常识,因为我通常会选择使用准备好的语句,或者至少使用数据库系统的原生字符串转义函数。

但是,我仍然很好奇如何利用它,因为:

  1. “id”值是最终用户/渗透测试者提供的字符串或数字
  2. 这是 MySQL
  3. 连接已明确设置为使用 UTF8。

【问题讨论】:

  • 1. “id”由用户提供。 2)不同的SQL服务器有不同的转义机制。 3) MySQL 根据字符集的不同转义。
  • 您可以为id 做的最好的事情就是检查它是否是一个整数。这里最易受攻击的方法甚至都懒得这样做,所以它们是开放的
  • @roganjosh,很抱歉说得太清楚了。我不打算改进此代码。我会使用准备好的陈述。我正在寻找证明这是可利用的证据。
  • 当然,我明白你在问什么。甚至Bobby Tables 也足以在这里演示:)
  • 不会,因为%r 实际上会转义引号。

标签: python mysql sql-injection


【解决方案1】:

MySQL 的 Python 驱动程序不支持真正的预处理语句。他们都做某种形式的字符串插值。诀窍是让 Python 通过适当的转义来进行字符串插值。

查看不安全操作的演示:How do PyMySQL prevent user from sql injection attack?

模拟参数的常规解决方案如下:

sql = "SELECT foo FROM bar WHERE id = %s"
cursor.execute(sql, (id,))

https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html


我知道克服转义的唯一方法(正确完成时)是:

  • 利用 GBK 或 SJIS 或类似字符集,其中转义的引号成为多字节字符的一部分。通过确保set names utf8,您应该可以避免此问题。
  • 更改sql_mode 以中断转义,例如启用NO_BACKSLASH_ESCAPESANSI_QUOTES。您应该在会话开始时设置sql_mode,类似于设置名称的方式。这将确保它没有使用导致问题的全局更改的 sql_mode。

另见Is "mysqli_real_escape_string" enough to avoid SQL injection or other SQL attacks?

【讨论】:

  • 但这并不能回答问题;我们可以注入'''SELECT foo FROM bar WHERE id = %r''' % id 吗?到目前为止,我失败了
  • 我很欣赏背景,但我主要是在寻找一种在不进行任何修改的情况下利用上述代码的方法。我在这方面的角色不是工程师,但我被聘为第 3 方审阅者。尽管来源是一个危险信号,但我想证明一个真正的问题。
  • 看起来%r 调用repr() 与Python 连接器中的MySQLConverter 的作用大致相同。由于您的字符集是 UTF8,因此只要您在字符串格式中使用 %r 而不是 %s,我认为任何一个都不会受到攻击。
  • @BillKarwin 我想这真的归结为.. 够用吗?可以坏掉吗?如果你的答案是“绝对不是”,我会完全接受。如果您不确定,我会将问题留待更长时间。
  • @Evert 很难证明某些东西不能被利用。我已经将它打开到 Python 聊天室,并且有一种方法看起来可以完成这项工作,但我想不出任何理由来解释为什么你现在要把它放在后端
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-16
  • 2016-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多