python pyodbc SQLite sql 注入

python pyodbc SQLite sql injections

我在我的 python flask 项目中使用 pyodbc 作为 SQLite 数据库连接。 我知道并理解 SQL 注入,但这是我第一次处理它。 我试图执行一些

我有一个函数可以连接我的 database.py 文件中的 SQL 字符串:

    def open_issue(self, data_object):
        cursor = self.conn.cursor()

        # data_object is the issue i get from the user
        name = data_object["name"]
        text = data_object["text"]
        rating_sum = 0

        # if the user provides an issue
        if name:

            # check if issue is already in db
            test = cursor.execute(f'''SELECT name FROM issue WHERE name = "{name}"''')
            data = test.fetchall()

            # if not in db insert
            if len(data) == 0:

                # insert the issue
                cursor.executescript(f'''INSERT INTO issue (name, text, rating_sum)
                                    VALUES ("{name}", "{text}", {rating_sum})''')
            else:
                print("nothing inserted!")

在 api.py 文件中调用了 open_issue() 函数:

        @self.app.route('/open_issue')
        def insertdata():

            # data sent from client
            # data_object = flask.request.json

            # unit test dictionary
            data_object = {"name": "injection-test-table",
                           "text": "'; CREATE TABLE 'injected_table-1337';--"}
            DB().open_issue(data_object)

“'; CREATE TABLE 'injected_table-1337';--”sql 注入没有创建 injected_table-1337,而是像字符串一样正常插入到注入测试的文本列-table.

所以我真的不知道我对 SQL 注入的标准方式是否安全(这个项目将只在本地托管,但总是欢迎良好的安全性)

其次:pyodbc 有没有办法检查字符串是否包含 sql 语法或符号,这样就不会在我的示例中插入任何内容,或者我是否需要手动检查字符串?

非常感谢

事实证明,使用 SQLite,您遇到 SQL 注入问题的风险要小得多,因为默认情况下 Python 的内置 sqlite3模块和 SQLite ODBC 驱动程序都允许在单个 .execute 调用中执行多个语句(通常称为“匿名代码块”)。此代码:

thing = "'; CREATE TABLE bobby (id int primary key); --"
sql = f"SELECT * FROM table1 WHERE txt='{thing}'"
crsr.execute(sql)

为 sqlite3 抛出这个

sqlite3.Warning: You can only execute one statement at a time.

这是 SQLite ODBC

pyodbc.Error: ('HY000', '[HY000] only one SQL statement allowed (-1) (SQLExecDirectW)')

不过,您应该遵循最佳做法并使用适当的参数化查询

thing = "'; CREATE TABLE bobby (id int primary key); --"
sql = "SELECT * FROM table1 WHERE txt=?"
crsr.execute(sql, (thing, ))

因为这也将正确处理直接注入会导致错误的参数值,例如

thing = "it's good to avoid SQL injection"