【问题标题】:Python MySQL, is this a prepared statement?Python MySQL,这是一个准备好的语句吗?
【发布时间】:2019-01-31 12:14:24
【问题描述】:

我正在设置一个 mysql 应用程序。这是我使用标准 mysqldb 格式连接的 getUsername 方法。 这是否意味着这是一个准备好的声明?另外,这段代码安全吗,还是我容易受到 SQL 注入的攻击?

def selectUser(userName):
    try:
        username = pickle.loads(base64.decode(userName))
    except:
        username = "admin"
    query = "SELECT name FROM users WHERE name = '%s'"
    conn = MySQLdb.connect('localhost', 'dbAdmin', 'lja8j30lJJal##', 'blog');
    with conn:
        c = conn.cursor()
        c.execute(query, (username,))

【问题讨论】:

  • 我相信这是一个 parameterized 语句,而不是一个 prepared 语句。是的,它不会受到 SQL 注入的影响。
  • 我不是 100% 确定这在 Python 中是如何工作的,但我怀疑 name = '%s' 最终会变成 name = ''John''name = 'NULL',这可能不是什么您打算这样做,在前一种情况下可能会导致 SQL 端出现语法错误。通常参数周围没有引号,因为如有必要,它们将由库添加。
  • 我的想法是使攻击向量成为可能,因为 pickle.loads() 会出错,因为方法应该是 load()。这样,它将始终是管理员用户。

标签: python mysql sql security sql-injection


【解决方案1】:

否 - 无法在 MySQLdb 中创建准备好的语句。在MySQL API binding in _mysql.c 中找不到任何mysql_stmt_init()mysql_stmt_prepare()mysql_stmt_execute()

无论出于何种原因,MySQLdb 的作者选择模拟参数,而不是使用真正的服务器端准备好的语句。

为了防止 SQL 注入,MySQLdb 包使用 Python 字符串格式语法。它将动态值插入 SQL 查询并应用正确的转义,即在引号字符之前添加 \ 以确保动态值不包含字符串分隔符。

请参阅我对How do PyMySQL prevent user from sql injection attack? 的回答以进行演示。

但是,如果您需要对数值常量使用动态值,则转义将无济于事。

【讨论】:

  • Sticky bit 在上面留下了关于查询报价的评论。这是攻击向量还是 mysqldb 不存在格式错误的查询?
  • 如果引用不正确,则存在 SQL 注入漏洞的风险。请参阅我为另一个 Stack Overflow 答案提供的链接中的示例。
猜你喜欢
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 2012-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多