如何防止在使用web.py的web.database时的滥用?
我正在写一个简单的 web.py 应用程序,并从 web.input 中获取数据...
import web
urls = (
'/', 'something',
)
app = web.application(urls, globals())
db = web.database(dbn='postgres', db='database', user='username', password='password', host='127.0.0.1')
class something:
def GET(self):
i = web.input()
return db.select('foo.table', where="column=$variable", vars={'variable':i.input, })
if __name__ == "__main__": app.run()
我需要担心把 i.input 传给 db.select(或者查询等)作为变量的一部分吗?会不会有 SQL 注入的风险等等?
编辑:
我自己在尝试这个问题,想看看会不会发生什么糟糕的事情。比如我试着玩一下引号,http://localhost:8080/?id=13' or 'x' ='x 结果显示在异常中有很好的 SQL 转义:
<sql: 'select * from foo.table where id = "13\' or \'x\'=\'x"'>
我还尝试了一些网络上常见的测试,觉得 web.py 在处理数据清理方面做得不错... 有没有其他人能发表一下看法?
3 个回答
是的,因为有人可以改变这个变量,特别是当它来自网址时,比如说“select * from table where id = [变量 + DELETE TABLE[”。这就是一个SQL注入的例子。如果用户对你的后台数据对象的名称有任何了解,这种情况就特别危险。
我不太确定Python是如何处理SQL语句中变量的参数化的,但我之前在处理ColdFusion和ASP.net网站时,必须进行类似的安全修复。
你看到的“漂亮的转义SQL”其实没什么用,因为它根本不会被发送到数据库引擎。
只要你不是手动把值插入到SQL请求字符串里,你就不用担心SQL注入的问题。这包括选择、插入、更新和删除这些操作,还有$variable_name
这种替换方式。在这两种情况下,SQL请求并不是完全作为文本拼接起来的,而是被正确地转换成了一个SQL准备好的语句,并由数据库引擎进行编译。只有在这个之后,参数才会被实际替换以执行语句。所以,只要你不是用不可信的数据手动构建SQL查询字符串或它的部分内容,你就安全了。
很遗憾,我无法提供比这个模块的源代码更好的资料,因为这是我唯一的信息来源。
http://webpy.org/cookbook/query 上说:
为了防止SQL注入攻击,db.query也支持“vars”这种语法,就像在db.select中描述的那样:
results = db.query("SELECT * FROM users WHERE id=$id", vars={'id':10})
这样做可以对用户输入进行处理,如果你信任他们提供的“id”变量。
所以我想这就是这么简单。
当然,我也意识到如果我要把用户输入放到其他地方,我还是需要验证这些输入……