Python MySQL,这是一个准备好的语句吗?

Posted

技术标签:

【中文标题】Python MySQL,这是一个准备好的语句吗?【英文标题】:Python MySQL, is this a prepared statement? 【发布时间】: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()。这样,它将始终是管理员用户。 【参考方案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 答案提供的链接中的示例。

以上是关于Python MySQL,这是一个准备好的语句吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 MySQL 中使用准备好的语句可以防止 SQL 注入攻击吗?

Python MySql Connector 准备好的语句和字典类

为啥mysql.connecter python准备好的语句在bytearray中返回字符串

无法在准备好的 INSERT 语句中的 python mysql.connector 中使用 None (NULL) 值

Mysql准备好的语句LIKE问题

MySQL准备好的语句在PHP中抛出错误