FlawOpen

flawopen.com/참고 자료/FastAPI SQL 인젝션

FastAPI는 기본 설정만으로 SQL 인젝션을 막나요?

Python 및 API 가이드
요약

Pydantic은 값이 선언된 입력 유형과 일치하는지 확인하지만 SQL을 다시 작성하거나 Python 문자열을 데이터베이스 매개변수로 바꾸지는 않습니다. 검증된 name: str도 호출자가 제어하는 텍스트입니다. 검증은 소포의 라벨을 확인하는 일이고, 매개변수 바인딩은 값을 SQL 지시문과 분리해 봉인하는 일이라고 생각하세요. SQL 템플릿은 고정하고 값은 SQLAlchemy를 통해 따로 전달합니다.

FastAPI의 취약한 패턴과 안전한 패턴

취약: 보간으로 SQL 텍스트가 바뀜
# A string type check does not make input safe inside SQL syntax
@app.get("/users")
def get_users(name: str, db: Session = Depends(get_db)):
    query = text(f"SELECT * FROM users WHERE name = '{name}'")
    return db.execute(query).fetchall()
안전: SQLAlchemy가 값을 별도로 바인딩
# :name is a bind parameter; the value is passed separately
@app.get("/users")
def get_users(name: str, db: Session = Depends(get_db)):
    query = text("SELECT * FROM users WHERE name = :name")
    return db.execute(query, {"name": name}).fetchall()

매개변수 바인딩이 다루지 않는 것

바인딩 매개변수는 데이터 값을 나타내며 테이블명, 열 이름, SQL 연산자, 정렬 방향을 나타내지 않습니다. 요청에서 정렬 필드를 고르게 해야 한다면 선택지를 고정된 SQLAlchemy 열 표현식 허용 목록에 매핑하세요. 요청 원문을 SQL에 이어 붙이면 안 됩니다. 매개변수화는 권한 확인을 대신하지도 않습니다. 호출자가 읽을 수 있는 행을 제한하고 데이터베이스 계정에는 해당 엔드포인트에 필요한 권한만 부여하세요.

예방 체크리스트

참고 자료

함께 보기 SQL 인젝션(CWE-89): 동작 원리와 언어별 방어 방법 — flawopen.com GORM Raw SQL: Go SQL 인젝션 방지 따옴표 이스케이프만으로 SQL Injection을 막을 수 있을까? ORM만 쓰면 SQL 인젝션을 막기에 충분한가 Knex.js는 SQL Injection에 안전한가요? MyBatis ${}와 #{}: SQL Injection 방지 MySQLi와 PDO: 안전한 Prepared Statement