来自请求的SQL查询中的列名

时间:2018-11-21 15:20:19

标签: c# sql-server oracle sql-injection

我被赋予了重写旧的Web API的任务。

此API从数据库读取SQL查询。

从字面上看,名称中包含“查询”的视图包含“ SqlText”列。

SELECT SqlText FROM Queries WHERE QueryID = 123

按照惯例,“ SqlText”仅包含格式为SELECT [columns] FROM [table]的简单SQL查询。

根据请求中的URL参数更改查询。然后,该查询的结果将显示为结果。

string parsedColumns = ParseColumns(queryRow); //contains "Column1, Column2";
string parsedTable = ParseTable(queryRow); //contains "SomeTable"

string requestColumns = HttpContext.Request["columns"];
string sqlColumns = requestColumns ?? parsedColumns;

string col1Condition = HttpContext.Request["Column1"]
string col2Condition = HttpContext.Request["Column2"]

string sqlQuery = "SELECT " + sqlColumns 
                  + " FROM " + parsedTable 
                  + " WHERE Column1 = " + col1Condition 
                  + " AND Column2 = " + col2Condition;

这是一个明显的SQL注入问题,所以我开始重新编写它。

现在还有其他三个问题。

  • 我无法更改数据库的结构或约定
  • 数据库是Oracle或SQL Server
  • 我不知道如何正确使用“ columns” URL参数以避免SQL注入。

将WHERE子句中的URL参数转换为SQL Server和Oracle的SQL参数很容易。

SQL Server

var sqlCommand = new SqlCommand("SELECT * FROM SomeTable WHERE Condition1 = @con1 AND Condition2 = @con2");

Oracle

var oracleCommand = new OracleCommand("SELECT * FROM SomeTable WHERE Condition1 = :con1 AND Condition2 = :con2");

列标识符

问题出在HttpContext.Request["columns"]上。我仍然需要以某种我完全不喜欢的URL参数更改SQL查询字符串。

为简化此问题,让我们考虑URL请求中的单个列。

string column = HttpContext.Request["column"];
var cmd = new SqlCommand($"SELECT {column} FROM ...");

我知道在SQL Server中,标识符可以用大括号括起来。因此,我的思路是,如果我将色谱柱上的所有大括号都剥掉,我会很安全。

string column = HttpContext.Request["column"];
column = column.Replace("[", "").Replace("]", "");
column = $"[{column}]";
var cmd = new SqlCommand($"SELECT {column} FROM ...");

Oracle使用引号。

string column = HttpContext.Request["column"];
column = column.Replace("\"", "");
column = $"\"{column}\"";
var cmd = new OracleCommand($"SELECT {column} FROM ...");

问题

  • 此sql注入足够安全吗?
  • 还是这种用例本质上是sql-injection不安全的?

1 个答案:

答案 0 :(得分:0)

由于您使用的是基本程序设计,因此无法更改仅尝试向输入中添加编辑以查找注入元素的操作。例如,如果输入为列名,则最大长度必须为30个字符(在12.x之前),并且不应包含分号或字符串“ OR”或“ AND”。虽然不是完美的解决方案,但这应该是实用的解决方案。