我知道下面的代码片段因为.format而容易受到SQL注入攻击,但我不知道为什么。有谁知道为什么这个代码容易受到攻击,我会在哪里开始修复它?我知道这些代码片段会打开输入字段以通过SQL注入执行其他恶意命令,但不知道为什么
cursor.execute("insert into user(username, password)"
" values('{0}', '{1}')".format(username, password))
handle[0].execute("insert into auditlog(userid, event)"
" values({0}, ‘{1}')".format(handle[2],event))
audit((cursor, connection, 0),
"registeration error for {0}”.format(username))
sql="""insert into activitylog(userid, activity, start, stop)
values({0}, '{1}', '{2}', '{3}')
""".format(handle[2], activity, start, stop)
答案 0 :(得分:3)
使用第一个SQL语句的示例SQL注入:
cursor.execute("insert into user(username, password) values('{0}', '{1}')".format(username, password))
如果username
和password
为"blah"
,则生成的SQL语句为:
insert into user(username, password) values('blah', 'blah')
这个特定的陈述没有问题。
但是,如果用户能够输入password
的值(可能来自HTML表单):
blah'); drop table user; --
生成的SQL语句将是:
insert into user(username, password) values('blah', 'blah'); drop table user; --
实际上是由分号分隔的3个语句:插入,删除表,然后是注释。一些数据库,例如Postgres将执行所有这些语句,导致用户表被删除。但是,尝试使用SQLite,SQLite似乎不允许一次执行多个语句。尽管如此,可能还有其他方法可以注入SQL。 OWASP对该主题有很好的参考。
修复此问题很简单,请使用参数化查询,如下所示:
cursor.execute("insert into user(username, password) values(?, ?)", (username, password))
使用?
将占位符添加到查询中,db引擎将正确地转义这些值以避免SQL注入。结果查询将是:
insert into user(username, password) values('blah', 'blah''); drop table users; --')
'
中的终止'blah\''
已正确转义。值
blah'); drop table users; --
将出现在插入记录的密码字段中。
答案 1 :(得分:2)
来自the docs:
通常,您的SQL操作需要使用Python中的值 变量。您不应该使用Python的字符串汇编查询 因为这样做是不安全的;它使你的程序 容易受到SQL注入攻击(请参阅http://xkcd.com/327/) 什么可能出错的幽默例子。)
相反,请使用DB-API的参数替换。放?作为一个 占位符,无论您想要使用哪个值,然后提供元组 value作为游标的execute()方法的第二个参数。 (其他数据库模块可能使用不同的占位符,例如%s或 :1。)例如:
# Never do this -- insecure! symbol = 'RHAT' c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol) # Do this instead t = ('RHAT',) c.execute('SELECT * FROM stocks WHERE symbol=?', t) print c.fetchone()
答案 2 :(得分:0)
每当使用字符串操作和外部用户提供的数据构造SQL语句时,您最多会遇到两种漏洞:
O'Reilly
的人。当它被插入到字符串中时,备用撇号将使得结果SQL无效。