Python 中的 MySQL、MATCH 和注入攻击
来自 MySQL 的
<前><代码>"""选择 * 来自我的表 WHERE MATCH(myColumnName) AGAINST(%s) 按 ID 排序 LIMIT 20""" % 查询MATCH
是否也容易受到注入攻击? 例如:似乎允许任意字符串,这看起来很糟糕。
如果是这样,我已经尝试了 - 以下是 Python 文档中的示例 -
t = (查询,) 语句=“”“选择* 来自我的表 哪里匹配(myColumnName)反对(?) 按 ID 排序 限制 20""" 光标.执行(语句,t)
但没有返回任何内容 - 即使字符串
query
返回了上面 (1) 中的结果。为什么会这样?在2)中,使用占位符
%s
而不是?
返回结果。为什么这比 1) 更安全(如果有的话)?例如,对于查询字符串,我总是可以用query=')...'
关闭字符串和括号,然后继续query=') OR otherColumnName LIKE '%hello%' --< /code>.
因此,除去查询字符串中除罗马字符或数字之外的所有内容是否足够?
Is
MATCH
from MySQL also vulnerable to injection attack?
For example:"""SELECT * FROM myTable WHERE MATCH(myColumnName) AGAINST(%s) ORDER BY id LIMIT 20""" % query
seems to allow arbitrary strings, which looks bad.
If so, I've instead tried - following examples in the Python docs -
t = (query,) statement = """SELECT * FROM myTable WHERE MATCH(myColumnName) AGAINST(?) ORDER BY id LIMIT 20""" cursor.execute(statement, t)
but nothing is returned - even when the string
query
returned hits in (1) above. Why is that?In 2), using the placeholder
%s
instead of?
returns results. Why is this safer than 1) (if at all)? E.g. with the query string I can always close off a string and parenthesis withquery=')...'
and continuequery=') OR otherColumnName LIKE '%hello%' --
.
Therefore, is it enough to strip query strings of everything but roman characters or numerals?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
什么运算符、函数、子句或任何其他主机并不重要您在注入时使用的语言术语。注入是混合数据和语言语句的问题,当您将数据插入到语句中时就会发生这种情况。准备好的语句参数将数据和语句分开,因此它们不易受到注入的影响。
至于
?
与%s
的参数,MySQLdb 文档 Cursor.execute 表示以下内容:It doesn't much matter what operators, functions, clauses or any other host-language terms you're using when it comes to injection. Injection is a matter of mixing data and language statements, which happens when you interpolate data into a statement. Prepared statement parameters keep data and statements separate, so they're not vulnerable to injection.
As for
?
versus%s
for parameters, the MySQLdb documentation for Cursor.execute says the following:当使用带有参数的参数化语句时,MySQLdb 会转义参数并使用 Python 字符串格式将这些参数重新插入到参数化语句中。然后将单个字符串语句发送到服务器。
您依赖 MySQLdb 正确转义参数以防止 SQL 注入的能力:
MySQLdb/cursors.py:
相反, oursql 完全独立地将查询和数据发送到服务器。
它不依赖于转义数据。这样应该更安全。
When using a parameterized statement with arguments, MySQLdb escapes the arguments and uses Python string formating to re-insert those arguments into the parametrized statement. A single string statement is then sent to the server.
You are relying on MySQLdb's ability to properly escape arguments to protect against SQL injection:
MySQLdb/cursors.py:
In contrast, oursql sends queries and data to the server completely separately.
It does not rely on escaping the data. This should be even safer.
第一种方法不正确,因为它使用基本的 python 字符串格式,不会转义查询字符串。
第二种方法是向服务器发送简单查询的首选方法,它将正确转义查询。
你只是有一个简单的错误。您需要将
AGAINST(?)
替换为AGAINST(%s)
该信息也可以在 python DbApi 常见问题解答
The first method is not correct since it uses basic python string formatting, that will not escape the query string.
The second method is the preferred method of sending a simple query to the server and it will properly escape the query.
You just have a simple bug. You need to replace
AGAINST(?)
withAGAINST(%s)
The information is also found in the python DbApi FAQ
就我的目的而言,清理
query
字符串就足够了 - 去除所有非字母数字字符(特别是'
和)
)。For my purposes it's enough to sanitise the
query
string - strip if of all non-alphanumeric characters (in particular'
and)
).