作者:_戒咗微博地_100 | 来源:互联网 | 2023-08-29 11:23
我应该如何在Python中为SQLite3进行真正的转义?如果我谷歌(或搜索stackoverflow)有很多问题,每次响应是这样的:dbcursor.execute(SELEC
我应该如何在Python中为SQLite3进行真正的转义?
如果我谷歌(或搜索stackoverflow)有很多问题,每次响应是这样的:
dbcursor.execute("SELECT * FROM `foo` WHERE `bar` like ?", ["foobar"])
这有助于防止SQL注入,并且如果我只是与“=”进行竞争就足够了,但它当然不会对通配符进行条带化处理.
所以,如果我这样做
cursor.execute(u"UPDATE `COOKIEs` set `count`=? WHERE `nickname` ilike ?", (COOKIEs, name))
某些用户可以为昵称提供“%”,并用一行替换所有COOKIE条目.
我可以自己过滤它(呃…我可能会忘记其中一个鲜为人知的通配符),我可以在昵称和昵称上使用小写,并用“=”替换“ilike”,但我真正想做的是类似的东西:
foo = sqlescape(nick)+"%"
cursor.execute(u"UPDATE `COOKIEs` set `count`=? WHERE `nickname` ilike ?", (COOKIEs, foo))
解决方法:
您通过使用参数化查询避免了直接代码注入.现在,您似乎正在尝试与用户提供的数据进行模式匹配,但您希望将用户提供的数据部分视为文字数据(因此没有通配符).你有几个选择:
>只需过滤输入. SQLite的LIKE只有understands%和_作为通配符,因此很难弄错.只需确保始终过滤输入. (我的首选方法:在构造查询之前过滤,而不是在读取用户输入时过滤).
>一般而言,“白名单”方法被认为比删除特定危险字符更安全,更容易.也就是说,不要删除字符串中的%和_(以及任何“鲜为人知的通配符”,如你所说),扫描你的字符串并只保留你想要的字符.例如,如果你的“昵称”可以包含ASCII字母,数字,“ – ”和“.”,它可以像这样清理:
name = re.sub(r"[^A-Za-z\d.-]", "", name)
此解决方案特定于您要匹配的特定字段,并且适用于关键字段和其他标识符.如果我必须使用RLIKE进行搜索,我肯定会这样做,它接受完整的正则表达式,因此需要注意更多的字符.
>如果您不希望用户能够提供通配符,为什么还要在查询中使用LIKE?如果您的查询的输入来自代码中的许多位置(或者您甚至可能正在编写库),那么如果您完全避免使用LIKE,则会使查询更安全:
>这是case insensitive matching:
SELECT * FROM ... WHERE name = 'someone' COLLATE NOCASE
>在您的示例中,您使用前缀匹配(“sqlescape(nick)”%“”).以下是使用精确搜索的方法:
size = len(nick)
cursor.execute(u"UPDATE `COOKIEs` set `count`=? WHERE substr(`nickname`, 1, ?) = ?",
(COOKIEs, size, nick))