Как избежать SQL-инъекции с помощью "SELECT * FROM {table_name}"?

Использование параметров postgres запроса psycopg2 в функции postgresql execute является наиболее безопасным sql и простым в использовании, когда python-interpreter параметры используются как pgsql литералы.

cursor.mogrify("select * from foo where bar = %s", ('example',))
# yields "select * from foo where bar = 'example'"

(обратите внимание, что cursor.mogrify() действует как выполнение, но просто показывает отформатированный SQL, не выполняя его на самом деле)

Однако сделать postgres это немного сложнее, если python вы хотите, чтобы параметр sql-select был таблицей, схемой или py другим идентификатором. Вы python-shell можете использовать AsI для psycopg2 обертывания вашего параметра, но pythonic это по-прежнему оставляет sql-injection дверь открытой для SQL-инъекции.

from psycopg2.extensions import AsIs

cur.mogrify('select %s from foo;', (AsIs('* from dual; drop table students; --'),))
# yields 'select * from dual; drop table students; -- from foo;'

Похоже, что sql-query новая разработка psycopg2 python-shell (> = 2.7) будет иметь sql-postgres класс идентификатора, в который sql-injection вы можете заключать параметры postgresql и, надеюсь, быть в безопасности. Если sql-syntax он еще не выпущен или у вас sql-postgres его нет, вот способ создать postgresql свой собственный класс. Ниже python я приведу несколько фрагментов, но python-shell вы также можете увидеть my gist.

import re
import psycopg2.extensions

class NotSqlIdentifierError(Exception):
    pass

valid_pattern = r'^[a-zA-Z_][a-zA-Z0-9_\$]*$'

class QuotedIdentifier(object):
    def __init__(self, obj_str):
        self.obj_str = obj_str

    def getquoted(self):
        if re.match(valid_pattern, self.obj_str):
            return self.obj_str
        else:
            raise NotSqlIdentifierError(repr(self.obj_str))

psycopg2.extensions.register_adapter(QuotedIdentifier, lambda x: x)

Если python-shell у вас уже есть экземпляр sql курсора psycopg2, вы можете python-shell протестировать / использовать sql-syntax его следующим образом:

# Test that a valid identifier formats into string
cursor.mogrify('select %s from foo;', (QuotedIdentifier('bar'),))
# returns 'select bar from foo;'

# Test formatting both an identifier and a literal
cursor.mogrify(
    'select * from foo where %s = %s;', 
    (
        QuotedIdentifier('bar'),
        'example'
    )
)
# returns "select * from foo where bar = 'example';"

# Test that a non-valid identifier fails with exception
cursor.mogrify('select %s from foo;', (QuotedIdentifier('* from dummy; drop table students; --'),))
"""Returns following:
---------------------------------------------------------------------------
NotSqlIdentifierError                     Traceback (most recent call last)
 in ()
----> 1 cur.mogrify('select %s from foo;', (QuotedIdentifier('* from dummy; drop table students; --'),))
 in getquoted(self)
     18             return self.obj_str
     19         else:
---> 20             raise NotSqlIdentifierError(repr(self.obj_str))
     21 
     22 psycopg2.extensions.register_adapter(QuotedIdentifier, lambda x: x)
NotSqlIdentifierError: '* from dummy; drop table students; --'
"""

Для sql-postgres получения дополнительной sql-query информации о механизме пользовательских sql-query классов для обертывания параметров pgsql SQL см. this section в документации.

python

sql

postgresql

sql-injection

psycopg2

2022-09-28T22:48:34+00:00
Вопросы с похожей тематикой, как у вопроса:

Как избежать SQL-инъекции с помощью "SELECT * FROM {table_name}"?