避免在Devexpress网格中注入SQL,其中\ filt

发布于 2025-02-08 19:50:19 字数 2676 浏览 0 评论 0原文

我正在使用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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

2025-02-15 19:50:19

不是它的设计方式。或至少没有仔细解析语句,然后利用参数化值和/或积极验证组件。这样做比通过组件更复杂,容易出错。

在您当前的设计中,将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 pass ColumnA (sic) and ABC 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文