[Flask] SQLAlchemy에서 SQL Injection 방어

22_gas·2024년 6월 22일

2024.01.08작성

개요

새로운 프로젝트를 진행중이다.

이 서비스는 기존의 프로젝트들과는 다르게 '일반 사용자'가 사용하는 서비스이기 때문에 보안에 조금더 신경써야한다.

기존 레퍼런스소스를 확인하던중 SQL Injection 공격에 취약한것 같아 해당 부분을 추가하여 개발을 진행했다.

지금은 SQL Injection을 자세히 설명하진 않고 예시만 한가지 보여줄 예정이다.

기존방식

EX) 사용자 정보 조회 쿼리라고 가정

com_sql.py에 이렇게 저장해놓고 사용중이었다.

select_info = """
    SELECT *
     FROM tb_user
    WHERE USER_ID = '{0}'
"""

그리고 이렇게 호출한다. 딱봐도 {0} 이라는게 위태로워보인다.

obj = #대충 DB연결하는 코드

obj.excute(select_list.format(f"{user_id}"))

원래라면 user_id값으로 id값만 잘 넘어오면 문제가 없는데,, (해커들은 그렇게 호락호락하지 않다)

user_id를 넘길때 >' OR '' ='< 뭐 대충 이렇게 넘겼다고 해보면 쿼리가 아래처럼 만들어진다.

SELECT *
  FROM tb_user
 WHERE USER_ID = '' OR '' = ''

이렇게되면 해커가 유저 정보를 몽땅 조회할수 있어서 위험하다

공격방어

그래서 이걸 방지해야하는데 아래 쿼리로 DB접속해서 조회하는데 

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session

engine = create_engine({DB url}, poolclass=NullPool)
Session = scoped_session(sessionmaker(bind=engine))

... 생략 ...

session.execute(sql).all()

일단 쿼리를 아래처럼 바꿔준다.

select_info = """
    SELECT *
     FROM tb_user
    WHERE USER_ID = :userId
"""

문자열이 그대로 들어가는게 아니고 key값으로 설정되도록 지정해준다.

그리고 excute할때 아래와같이 딕셔너리를 같이 넘겨주면 된다

_dict = {"userId" : "gf160"}

session.execute(sql, _dict).all()

끗!

profile
전 아직 모르는게 많아요

0개의 댓글