【问题标题】:Flask-sqlalchemy + pymssql prevent SQL injections from Stored Procedure paramsFlask-sqlalchemy + pymssql 防止来自存储过程参数的 SQL 注入
【发布时间】:2018-04-20 06:27:23
【问题描述】:

我的下一条路线完美无缺:

@home_app.route('/<id>', methods=['GET', 'POST'])
def home(id):
    query = "DECLARE @return_value int, @EXIST bit EXEC @return_value = [dbo].[SP_CHECK_ID] @ID = N'" + id +"', @EXIST = @EXIST OUTPUT SELECT @EXIST as N'@EXIST'"
    result = db.session.execute(query, bind=db.get_engine(app, 'second_db'))
    exist = []
    for row in result:
        exist.append(row['@EXIST'])
    return "Exist? " + str(row['@EXIST'])

问题在于,由于参数,它可能容易受到 SQL 注入的攻击。为了解决这个问题,我试过了:

query = """
        DECLARE @return_value int, @EXIST bit
        EXEC @return_value = [dbo].[SP_CHECK_ID] @ID = N':id',
        @EXIST = @EXIST OUTPUT
        SELECT @EXIST as N'@EXIST'
        """
result = db.session.execute(query, {'id': id}, bind=db.get_engine(app, 'second_db'))

但我得到了一个错误:

sqlalchemy.exc.ProgrammingError: (pymssql.ProgrammingError) (102, b"Incorrect syntax near '179'.DB-Lib error message 20018, severity 15:\nGeneral SQL Server error: Check messages from the SQL Server\n") [SQL: "DECLARE @return_value int, @EXIST bit EXEC @return_value = [dbo].[SP_CHECK_ID] @ID = N'%(id)s', @EXIST = @EXIST OUTPUT SELECT @EXIST as N'@EXIST'"] [parameters: {'id': '179'}]

我尝试过其他方法:

query = """
        DECLARE @return_value int, @EXIST bit
        EXEC @return_value = [dbo].[SP_CHECK_ID] @ID = N'%s',
        @EXIST = @EXIST OUTPUT
        SELECT @EXIST as N'@EXIST'
        """
result = db.session.execute(query, id, bind=db.get_engine(app, 'second_db'))

但我得到了:

AttributeError: 'list' object has no attribute 'keys'

我也试过了

from sqlalchemy.sql import text
query = text(...)

并使用 ?而不是 %s,但我得到了同样的错误。

【问题讨论】:

    标签: python flask sqlalchemy sql-injection pymssql


    【解决方案1】:

    使用占位符的好处之一是您不需要(也不应该)手动引用。所以当你包括

    """ ... N':id' ... """
    

    在您的查询中可能呈现为

    """ ... N''179'' ... """
    

    等等,取决于你的参数类型等。修复方法是删除引号并让 SQLAlchemy/DB-API 驱动程序处理所有这些:

    query = """
            DECLARE @return_value int, @EXIST bit
            EXEC @return_value = [dbo].[SP_CHECK_ID] @ID = :id,
            @EXIST = @EXIST OUTPUT
            SELECT @EXIST as N'@EXIST'
            """
    result = db.session.execute(
        query, {'id': id},
        bind=db.get_engine(app, 'second_db'))
    

    命名占位符样式是text() 构造提供的后端中性 SQLAlchemy 抽象。 Session.execute() 隐式包装您的文本 SQL,如果您省略了它。 %s? 等是 DP-API 特定的占位符样式。 pymssql 似乎使用百分比样式。

    【讨论】:

      猜你喜欢
      • 2020-05-28
      • 1970-01-01
      • 2021-11-21
      • 2014-06-20
      • 2019-01-18
      • 2016-10-15
      • 2012-11-23
      • 2014-06-18
      • 2018-10-06
      相关资源
      最近更新 更多