programing

코어 레벨 또는 ORM 레벨에서만 SQLAlchemy SQL 주입 보호

linuxpc 2023. 8. 14. 22:33
반응형

코어 레벨 또는 ORM 레벨에서만 SQLAlchemy SQL 주입 보호

사용하는 ORM 라이브러리 및 데이터베이스 드라이버에 대해 여러 데이터베이스 테이블(모두 SELECT 문)을 쿼리해야 하는 기능을 수행하고 있습니다.SQLAlchemy그리고.PyMySQL.

처음에는 이 기능을 완전히 ORM 수준에서 구축했지만, 이 기능을 실행할 때마다 파이썬 애플리케이션 서버와 데이터베이스 서버 간에 여러 번 왕복 작업이 발생하여 성능 문제가 발생했습니다. 그 이후 SQL Chemy Core 수준의 데이터베이스 서버로 한 번에 여러 SQL 문을 전송하는 새로운 접근 방식이 고안되었습니다.

새로운 접근 방식의 단순화된 버전은 다음과 같습니다.

from sqlalchemy.sql import select as sa_select
db_engine = sqlalchemy_engin_init()

def my_db_query_fn(self, user_input_1, user_input_2):
    # note that user_input_1, user_input_2 are from untrusted user input
    with db_engine.connect() as conn:
        # raw DBAPI connection for multiple result sets in one go
        dbapi_conn = conn.connection
        # cursor comes from low-level database driver, not standard SQLAlchemy class
        cursor = dbapi_conn.cursor()
        try:
            table_a = Model_A.__table__
            table_b = Model_B.__table__
            stmt  = sa_select(table_a.c.column1, table_a.c.column2
                        ).where(table_a.c.column3 == user_input_1)
            stmt2 = sa_select(table_b.c.column1, table_b.c.column2
                        ).where(table_b.c.column3 == user_input_2)
            sql_compile_fn = lambda s: str(s.compile(conn.engine, compile_kwargs={"literal_binds": True})) 
            # generate raw SQL statements by running compile()
            rawsqls = list(map(sql_compile_fn, [stmt, stmt2]))
            # send all the generated raw SQL statements in one round trip
            cursor.execute(';'.join(rawsqls))
            # then retrieve each result set one after the other, this part is skipped ....
        finally:
            cursor.close()

테스트 후, 위의 코드는 왕복 지연 시간을 줄이지만, 제 질문은 :가 SQL 주입 공격에 취약한 새로운 접근 방식인지 여부입니다.제가 고려하고 있는 것은 다음과 같습니다.

  • 위의 코드 샘플에서 언급한 바와 같이, 함수는my_db_query_fn()신뢰할 수 없는 사용자 입력을 사용해야 합니다.user_input_1그리고.user_input_2모든 SQL 문을 빌드하기 위해 모든 원시 SQL 문자열도 생성됩니다.sqlalchemy.sql.selectable.Select.compile()신뢰할 수 없는 사용자 입력으로 원시 SQL 문자열 패턴을 직접 포맷하는 대신
  • 함수my_db_query_fn()SQL 문을 실행합니다.cursor.execute()것은 아니다.conn.execute().그cursor낮은 수준의 데이터베이스 드라이버에서 제공됩니다(나의 경우는 그렇습니다).PyMySQL), 그것이 SQL 주입을 피하기 위한 나쁜 관행으로 간주되는지 모르겠습니다. (혹은cursor.execute()그리고.conn.execute()결코 그것과 관련이 없습니까?)
  • 스택 오버플로에 대한 유사질문과 공식 문서에 따르면, 함수는YOUR_MODEL.__table__.select()SQL 화학 ORM 및 함수에서sqlalchemy.sql.expression.select(YOUR_MODEL)SQL에서 Lchemy Core는 실제로 동일한 클래스 유형의 인스턴스를 생성합니다.sqlalchemy.sql.selectable.SelectSELECT 문 인스턴스는 다음 중 하나로 전달될 수 있습니다.conn.execute()또는session.execute()SQLAlchemyCore에서도 SQL 주입을 확인한다는 의미입니까?

읽어주셔서 감사합니다, 당신의 피드백, 힌트 또는 팁에 감사드립니다.

언급URL : https://stackoverflow.com/questions/68473636/sqlalchemy-sql-injection-protection-at-core-level-or-only-at-orm-level

반응형