我被赋予了重写旧的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注入问题,所以我开始重新编写它。
现在还有其他三个问题。
将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 ...");
问题
答案 0 :(得分:0)
由于您使用的是基本程序设计,因此无法更改仅尝试向输入中添加编辑以查找注入元素的操作。例如,如果输入为列名,则最大长度必须为30个字符(在12.x之前),并且不应包含分号或字符串“ OR”或“ AND”。虽然不是完美的解决方案,但这应该是实用的解决方案。