避免在我的Python SQL API中发生SQL注入攻击

时间:2017-07-28 12:43:02

标签: python sql-server security sqlite

我设计了一个与GUI接口的Python SQLite API。 GUI允许用户选择一个给定的列,其数据将在每个月汇总。根据我从https://docs.python.org/2/library/sqlite3.html学到的知识,我知道我写这个的方式使我的代码容易受到SQL注入攻击;我使用Python的字符串操作汇编了我的查询。但是,我无法让这个模块以“正确”的方式工作;使用DB-API的参数替换将“?”作为占位符放在您想要使用值的任何位置。我猜这个问题是我想把表列变成变量而不是值。请帮助我重新构建此模块,以使其更安全,更不容易受到SQL注入攻击。

下面的代码有效(它按照我的意愿运行)我只知道这不是正确/最安全的方法。

    def queryEntireCategoryAllEmployees(self, column):

        table_column = 'Name_Data_AllDaySums.%s' % column

        cursor = self.conn.execute("SELECT \
            SUBSTR(data_date,1,7), \
            SUM(%s) \
        FROM ( \
            SELECT \
                SS_Installations.data_date AS 'data_date', \
                SS_Installations.Installations_day_sum, \
                SS_PM_Site_Visits.PM_Site_Visits_day_sum, \
                SS_Rpr_Maint_Site_Visits.Inst_Repair_or_Maintenance_on_Site_day_sum, \
                SS_Rmt_Hrdwr_Spt.Rmt_Hardware_Support_day_sum, \
                SS_Rmt_Sftwr_Spt.Rmt_Software_Support_day_sum, \
                SS_Rpr_Mant_RFB_in_House.Inst_Repair_Maint_Rfb_In_House_day_sum, \
                Miscellaneous.Miscellaneous_day_sum, \
                SS_Doc_Gen.Document_Generation_day_sum, \
                SS_Inter_Dep_Spt.Inter_Dep_Spt_day_sum, \
                SS_Online_Training.Online_Training_day_sum, \
                SS_Onsite_Training.Onsite_Training_day_sum, \
                SS_In_House_Training.In_House_Training_day_sum, \
                Validation_Duties.Validation_Duties_day_sum \
            FROM \
                SS_Installations \
            INNER JOIN SS_PM_Site_Visits ON \
                SS_Installations.employee_clk_no = SS_PM_Site_Visits.employee_clk_no AND \
                SS_Installations.data_date = SS_PM_Site_Visits.data_date \
            INNER JOIN SS_Rpr_Maint_Site_Visits ON \
                SS_Installations.employee_clk_no = SS_Rpr_Maint_Site_Visits.employee_clk_no AND \
                SS_PM_Site_Visits.data_date = SS_Rpr_Maint_Site_Visits.data_date \
            INNER JOIN SS_Rmt_Hrdwr_Spt ON \
                SS_Installations.employee_clk_no = SS_Rmt_Hrdwr_Spt.employee_clk_no AND \
                SS_Rpr_Maint_Site_Visits.data_date = SS_Rmt_Hrdwr_Spt.data_date \
            INNER JOIN SS_Rmt_Sftwr_Spt ON \
                SS_Installations.employee_clk_no = SS_Rmt_Sftwr_Spt.employee_clk_no AND \
                SS_Rmt_Hrdwr_Spt.data_date = SS_Rmt_Sftwr_Spt.data_date \
            INNER JOIN SS_Rpr_Mant_RFB_in_House ON \
                SS_Installations.employee_clk_no = SS_Rpr_Mant_RFB_in_House.employee_clk_no AND \
                SS_Rmt_Sftwr_Spt.data_date = SS_Rpr_Mant_RFB_in_House.data_date \
            INNER JOIN Miscellaneous ON \
                SS_Installations.employee_clk_no = Miscellaneous.employee_clk_no AND \
                SS_Rpr_Mant_RFB_in_House.data_date = Miscellaneous.data_date \
            INNER JOIN SS_Doc_Gen ON \
                SS_Installations.employee_clk_no = SS_Doc_Gen.employee_clk_no AND \
                Miscellaneous.data_date = SS_Doc_Gen.data_date \
            INNER JOIN SS_Inter_Dep_Spt ON \
                SS_Installations.employee_clk_no = SS_Inter_Dep_Spt.employee_clk_no AND \
                SS_Doc_Gen.data_date = SS_Inter_Dep_Spt.data_date \
            INNER JOIN SS_Online_Training ON \
                SS_Installations.employee_clk_no = SS_Online_Training.employee_clk_no AND \
                SS_Inter_Dep_Spt.data_date = SS_Online_Training.data_date \
            INNER JOIN SS_Onsite_Training ON \
                SS_Installations.employee_clk_no = SS_Onsite_Training.employee_clk_no AND \
                SS_Online_Training.data_date = SS_Onsite_Training.data_date \
            INNER JOIN SS_In_House_Training ON \
                SS_Installations.employee_clk_no = SS_In_House_Training.employee_clk_no AND \
                SS_Onsite_Training.data_date = SS_In_House_Training.data_date \
            INNER JOIN Validation_Duties ON \
                SS_Installations.employee_clk_no = Validation_Duties.employee_clk_no AND \
                SS_In_House_Training.data_date = Validation_Duties.data_date \
            WHERE \
                (SS_Installations.Installations_day_sum != 0 OR \
                SS_PM_Site_Visits.PM_Site_Visits_day_sum !=0 OR \
                SS_Rpr_Maint_Site_Visits.Inst_Repair_or_Maintenance_on_Site_day_sum != 0 OR \
                SS_Rmt_Hrdwr_Spt.Rmt_Hardware_Support_day_sum != 0 OR \
                SS_Rmt_Sftwr_Spt.Rmt_Software_Support_day_sum != 0 OR \
                SS_Rpr_Mant_RFB_in_House.Inst_Repair_Maint_Rfb_In_House_day_sum != 0 OR \
                Miscellaneous.Miscellaneous_day_sum != 0 OR \
                SS_Doc_Gen.Document_Generation_day_sum != 0 OR \
                SS_Inter_Dep_Spt.Inter_Dep_Spt_day_sum != 0 OR \
                SS_Online_Training.Online_Training_day_sum != 0 OR \
                SS_Onsite_Training.Onsite_Training_day_sum != 0 OR \
                SS_In_House_Training.In_House_Training_day_sum != 0 OR \
                Validation_Duties.Validation_Duties_day_sum != 0)) Name_Data_AllDaySums \
        GROUP BY SUBSTR(data_date,1,7) \
        ORDER BY SUBSTR(data_date,1,7) ASC" % table_column)

        dataList = cursor.fetchall()

        return dataList

1 个答案:

答案 0 :(得分:0)

首先,我会阅读这篇关于在PHP中防止SQL注入的非常有用的SO帖子,因为许多原则都适用:How can I prevent SQL Injection in PHP?

此外,因为您正在使用SQL Server,我会考虑创建一个存储过程并在T-SQL中使用EXEC命令运行它并将列名作为参数传递(因为您的查询似乎只是基于列动态更改),类似于此MSSQL文档示例Execute a Stored Procedure并使用此SO线程基于参数Can I Pass Column Name As Input...动态更改查询

这样做可以帮助您隐藏代码,使其免受注入攻击,从而确保输入符合您的预期。

最后,考虑使用列的下拉列表进行选择,以便最终用户只能选择一组预定义的输入,从而使您的应用程序更加安全。这种方法以及模糊存储过程中的代码将有助于更容易推出更新。