2017-01-25 18 views
2

我希望用户能够选择显示结果的顺序,例如按年龄),并且我不想在从数据库中获得它们之后对它们进行分类。我该如何参数化pysqlite中的列名以避免SQL注入

显然,如果用户能够指定影响SQL命令的输入,那么需要对它进行消毒处理,而且我通常会使用参数化,但pysqlite似乎忽略除参数以外的任何参数。

示例代码如下显示参数化不适用于ORDER BY,也是一种使用字符串格式化的解决方法,但容易受SQL注入影响。

什么是推荐的解决方案,允许用户输入影响排序顺序而不暴露SQLi漏洞?我必须使用字符串格式并手动检查每个用户输入吗?

#!/user/bin/env python3 

import sqlite3 

con = sqlite3.connect(':memory:') 
cur = con.cursor() 
cur.execute('CREATE TABLE test (name, age)') 
cur.execute('INSERT INTO test VALUES (:name, :age)', {'name': 'Aaron', 'age': 75}) 
cur.execute('INSERT INTO test VALUES (:name, :age)', {'name': 'Zebedee', 'age': 5}) 

cur.execute('SELECT * FROM test ORDER BY age ASC') 
results = cur.fetchall() 
print('\nGood, but hard coded:\n', results) 
# Good, but hard coded: 
# [('Zebedee', 5), ('Aaron', 75)] 

cur.execute('SELECT * FROM test ORDER BY :order_by ASC', {'order_by': 'age'}) 
results = cur.fetchall() 
print('\norder_by parameter ignored:\n', results) 
# order_by parameter ignored: 
# [('Aaron', 75), ('Zebedee', 5)] 

cur.execute('SELECT * FROM test ORDER BY {order_by} ASC'.format(order_by='age')) 
results = cur.fetchall() 
print('\nRight order, but vulnerable to SQL injection:\n', results) 
# Right order, but vulnerable to SQL injection: 
# [('Zebedee', 5), ('Aaron', 75)] 

con.close() 
+0

顺便说一句,我只是用SQLI与该输入尝试''年龄; DROP TABLE测试;''到第三个SQL命令和pysqlite引发一个异常说'sqlite3.Warning:你一次只能执行一个语句.',所以也许我不应该担心?在我看来,使用字符串格式仍然很危险,但... – Grezzo

+0

用户是否可以以任何方式影响字符串的实际内容? (在这个问题中,你使用了'age'这个常量字符串,这是没有道理的。) –

+0

它来自http请求。如果他们使用正确的客户端(网页),它应该是6列名称中的任何一个,但如果有人决定是恶意的,它可能是他们选择的任何东西。 – Grezzo

回答

3

SQL参数仅用于值;其他任何内容都可能会改变查询的含义。 (例如,ORDER BY password可以离开的暗示,如能ORDER BY (SELECT ... FROM OtherTable ...)。)

为了确保来自客户端的列名是有效的,你可以使用白名单:

if order_by not in ['name', 'age']: 
    raise ... 
execute('... ORDER BY {}'.format(order_by)) 

但它仍然是一个坏主意将该字符串集成到查询中,因为验证和实际表可能不同步,或者您可能会忘记检查。从客户更好的回报列索引,让您使用的实际字符串始终是你自己的,任何错误可以正常在测试过程中很容易被发现:

order_by = ['name', 'age'][order_index] 
execute('... ORDER BY {}'.format(order_by)) 
+0

使用常数给出'order_index'名称的值(如'NAME_COLUMN = 0')。这样,您可以轻松添加更多列或移动它们,并可以查看您想要的订购类型。 –

+0

还要注意,通过给它们自己的索引,你可以很容易地创建更复杂的排序,比如'name ASC,age DESC'。 –

+0

很好的答案,特别是按列排序的示例可以提供密码提示。谢谢。然后是白名单。 – Grezzo