提问人:TonyTT 提问时间:4/9/2015 更新时间:4/9/2015 访问量:17901
Python SQLite3 SQL 注入易受攻击代码
Python SQLite3 SQL Injection Vulnerable Code
问:
我知道下面的代码片段由于 .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)
答:
从文档中:
通常,您的 SQL 操作需要使用 Python 中的值 变量。不应使用 Python 的字符串来组装查询 操作,因为这样做是不安全的;它使你的程序 容易受到 SQL 注入攻击(请参阅 http://xkcd.com/327/ 幽默的例子,说明可能出错的地方)。
请改用 DB-API 的参数替换。放?作为 占位符,然后在任何位置使用值,然后提供元组 的值作为游标的 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()
使用第一个 SQL 语句的 SQL 注入示例:
cursor.execute("insert into user(username, password) values('{0}', '{1}')".format(username, password))
如果 和 是生成的 SQL 语句为:username
password
"blah"
insert into user(username, password) values('blah', 'blah')
这个特殊的说法没有问题。
但是,如果用户能够输入 的值,则可能来自 HTML 表单:password
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))
占位符被添加到查询中,数据库引擎将正确转义这些值以避免 SQL 注入。生成的查询将是:?
insert into user(username, password) values('blah', 'blah''); drop table users; --')
终止已正确转义。价值'
'blah\''
blah'); drop table users; --
将出现在插入记录的密码字段中。
每当您使用字符串操作和外部用户提供的数据构造 SQL 语句时,您都会面临两种类型的漏洞:
- 恶意意图,即用户使用行分隔符、注释字符和 SQL UPDATE 或 DELETE 语句的某种组合键入值,这些语句将对数据库产生负面影响(参见 mhawke 的回答)。
- 用户键入合法文本但包含程序不希望看到的字符的无意。例如,用户名为 。当它入到字符串中时,备用撇号将使生成的 SQL 无效。
O'Reilly
评论
secret'); drop table user;--