避免在Devexpress网格中注入SQL,其中\ filt
我正在使用DeVexpress网格为最终用户展示我的结果。
由于我使用远程模式,因此我应该根据网格过滤器过滤自己的结果。
我制作了自定义JS开关/情况以构建SQL ,其中
基于过滤器结果的条件:
let whereClause = '';
if (loadOptions['filter']) {
const rawFilter = loadOptions['filter'];
let filters = null;
if (_.isArray(rawFilter[0])) {
filters = _.map(rawFilter, (item) => {
if (_.isArray(item)) {
if (!_.isNumber(item[2])) {
switch (item[1]) {
case 'contains':
return `(${item[0]} LIKE N'%${item[2]}%')`;
case 'notcontains':
return `(${item[0]} NOT LIKE N'%${item[2]}%')`;
case 'startswith':
return `(${item[0]} LIKE N'${item[2]}%')`;
case 'endswith':
return `(${item[0]} LIKE N'%${item[2]}')`;
default:
return `(${item[0]} ${item[1]} N'${item[2]}')`;
}
}
else {
return `(${item[0]} ${item[1]} ${item[2]})`;
}
}
else {
return item;
}
});
whereClause = _.join(filters, ' ');
}
}
然后将whreeclause
传递给控制器,例如: 之后, 'abc')
在这样的存储过程中使用它(以searchParam
的方式传递):
CREATE OR ALTER PROCEDURE GetTestResult
@Skip INT = 0,
@Take INT = 400000,
@SearchParam NVARCHAR(MAX) = null
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sqlCommand NVARCHAR(MAX)
DECLARE @sqlCommandPagination NVARCHAR(MAX)
DECLARE @sqlCommandFinall NVARCHAR(MAX)
SET @sqlCommand = 'SELECT ColumnA,ColumnB,ColumnC FROM dbo.TestTable '
SET @sqlCommandPagination = ' ORDER BY ColumnA ASC OFFSET ' + CAST(@Skip AS varchar(500)) +
' ROWS FETCH NEXT ' + CAST(@Take AS varchar(500)) + ' ROWS ONLY;'
IF (@SearchParam <> '' AND @SearchParam IS NOT NULL)
SET @sqlCommandFinall = @sqlCommand + ' WHERE ' + @SearchParam + @sqlCommandPagination;
IF (@SearchParam = '' OR @SearchParam IS NULL )
SET @sqlCommandFinall = @sqlCommand + @sqlCommandPagination;
Execute SP_ExecuteSQL @sqlCommandFinall;
END;
GO
有什么方法可以使此方法SQL注入证明?
我正在使用dapper/sqlmapper/查询功能来调用我的C#存储过程。
I'm using Devexpress Grid to show my result for final users.
Since I'm using remote mode, I should filter my own result on server based on grid filter.
I made custom JS switch/case to build a SQL WHERE
condition based on filter result like this:
let whereClause = '';
if (loadOptions['filter']) {
const rawFilter = loadOptions['filter'];
let filters = null;
if (_.isArray(rawFilter[0])) {
filters = _.map(rawFilter, (item) => {
if (_.isArray(item)) {
if (!_.isNumber(item[2])) {
switch (item[1]) {
case 'contains':
return `(${item[0]} LIKE N'%${item[2]}%')`;
case 'notcontains':
return `(${item[0]} NOT LIKE N'%${item[2]}%')`;
case 'startswith':
return `(${item[0]} LIKE N'${item[2]}%')`;
case 'endswith':
return `(${item[0]} LIKE N'%${item[2]}')`;
default:
return `(${item[0]} ${item[1]} N'${item[2]}')`;
}
}
else {
return `(${item[0]} ${item[1]} ${item[2]})`;
}
}
else {
return item;
}
});
whereClause = _.join(filters, ' ');
}
}
And then passing the whereClause
to the controller, like : "( ColumnA like N'ABC')"
After that, using it in a stored procedure like this (passing it as SearchParam
):
CREATE OR ALTER PROCEDURE GetTestResult
@Skip INT = 0,
@Take INT = 400000,
@SearchParam NVARCHAR(MAX) = null
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sqlCommand NVARCHAR(MAX)
DECLARE @sqlCommandPagination NVARCHAR(MAX)
DECLARE @sqlCommandFinall NVARCHAR(MAX)
SET @sqlCommand = 'SELECT ColumnA,ColumnB,ColumnC FROM dbo.TestTable '
SET @sqlCommandPagination = ' ORDER BY ColumnA ASC OFFSET ' + CAST(@Skip AS varchar(500)) +
' ROWS FETCH NEXT ' + CAST(@Take AS varchar(500)) + ' ROWS ONLY;'
IF (@SearchParam <> '' AND @SearchParam IS NOT NULL)
SET @sqlCommandFinall = @sqlCommand + ' WHERE ' + @SearchParam + @sqlCommandPagination;
IF (@SearchParam = '' OR @SearchParam IS NULL )
SET @sqlCommandFinall = @sqlCommand + @sqlCommandPagination;
Execute SP_ExecuteSQL @sqlCommandFinall;
END;
GO
Is there any way to make this method SQL injection proof?
I'm using Dapper/SqlMapper/Query function for calling my stored procedure from C#.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不是它的设计方式。或至少没有仔细解析语句,然后利用参数化值和/或积极验证组件。这样做比通过组件更复杂,容易出错。
在您当前的设计中,将SQL注入WHERE或ORDER是微不足道的。您应该将其分解为其组件,将其通过这些组件并在后端进行验证。因此,而不是像n'abc'(SIC)那样传递
columna,您应该通过
columna
(sic)和abc
单独使用,并使用参数化查询对于值(绑定它们)。在第二种情况下,许多数据库将不允许按值进行参数化顺序,因此在这种情况下,您应该确保使用正验证。
Not the way it's designed. Or at least not without carefully parsing the statement and then leveraging parameterized values and/or positively validating the components. And doing that is much more complex and prone to error than just passing the components.
In your current design, it's trivial to inject SQL into the where or order by. You should break this down into its components, pass those through and validate them at the backend. So, rather than passing
ColumnA like N'ABC'
(sic) you should passColumnA
(sic) andABC
separately, and use parameterized queries for the values (bind them).In the second case, many databases will not allow parameterizing order by values, so you should be sure to use positive validation in that case.