在mysql(5.6版)中,我可以在SELECT
子句中进行公式/计算。
e.g。
SELECT (a*2) as x, (b+2) as y, sum(...) from table_name;
我也可以动态传递计算。问题是我可以通过任何公式。有没有办法可以限制SELECT
条款中的内容?这可能会在注入攻击中被利用。
SELECT @@version, @@hostname, (a*2) as x, (b+2) as y, sum(...) from table_name;
这会暴露我的数据库版本和主机名。
答案 0 :(得分:1)
关于你可能想到的东西是关闭的东西叫做预备语句。语句可以防止恶意用户通过SQL查询中的文字值注入SQL。但是,语句不允许列本身成为参数。
我能想到的唯一安全的方法是在用户定义的公式中选择所有值都需要的列。然后,将这些列/变量返回到应用层,并在那里计算公式。如果您尝试使用来自用户的输入在SQL中构建公式,例如从用户界面中,你就有可能被注入。
答案 1 :(得分:1)
你的HTTP包装器听起来像是设计容易受到攻击。
如果允许不受信任的输入作为SQL查询的一部分执行,那么这就是SQL注入的定义。
防止SQL注入的常见建议是使用查询参数。如果查询的动态部分等同于常量值(如带引号的字符串值,日期或数字文字),这很好,但它不适用于您在查询中可能需要的其他内容,例如列名,或者像你正在做的表达式一样。
@TimBiegeleisen描述的内容有时被称为白名单。
在白名单方法中,用户无法发送文字表达。他们选择 SQL表达式,但他们只能从您在应用程序中控制的一组预定义表达式中进行选择。
这是SQL注入:
http://example.com/query?expr=(a*2) as x
这是白名单:
http://example.com/query?expr=1
其中“1”被硬编码以选择您的批准表达式中的第1个。您可以使用case
语句或数组,或类似的东西。
这可以作为白名单,因为如果用户尝试发送与case
语句或表达式数组中的某个键不对应的expr id,那么您的应用程序将不执行任何操作,或返回错误信息。
http://example.com/query?expr=(select password from users)
可以返回:
HTTP Status 400 Bad Request
这确实需要您拥有更强大的应用层。您必须编写代码来执行表达式id到完整表达式的映射。