til

bindvar는 어떻게 SQL Injection을 막는가?

주먹불끈 2023. 8. 30. 17:07

MidJourney에 database로 생성

개요

bindvar(= binding variable)은 SQL 쿼리에서 사용하는 변수나 placeholder를 말한다. 주로 데이터베이스 쿼리의 파라미터화된 부분에 데이터를 바인딩하는 데 사용하는데 SQL injection 공격을 예방하는 데 중요한 역할을 한다.

SQL Injection 예시

악의적인 사용자가 다음과 같은 input을 넣으려고 했다고 생각해보자.

input := "John'; DROP TABLE users; --"  // 악의적인 사용자 입력
query := "SELECT * FROM users WHERE name = '" + input + "'"

이렇게 생성한 쿼리는 다음과 같으며, 데이터베이스에서 2개의 SQL명령을 실행한다.

  • 하나는 John 이라는 이름의 사용자를 users 테이블에서 가져오는 간단한 요청이지만
  • 두 번째 명령은 users 테이블을 삭제(drop)하라는 끔.찍.한. 명령인 것이다.
    • 참고로 --'부분은 맨 뒤쪽의 작은 따옴표를 주석처리하여 무시하게 하는 테크닉이다.
SELECT * FROM users WHERE name = 'John'; DROP TABLE users; --'

bindvar를 사용한다면?

Go언어의 sqlx 라이브러리를 사용한다고 가정하면 다음과 같이 bindvar를 사용할 수 있다. query의 물음표(?)이다.

이렇게 구현을 하면 어떻게 될까? 이때에 SQL 명령은

  • John 을 가져오는 명령이 아니라,
  • John'; DROP TABLE users; -- 라는 user를 가져오는 명령이 된다. 이렇게 SQL injection을 방지한다.
input := "John'; DROP TABLE users; --"
query := "SELECT * FROM users WHERE name = ?"
rows, err := db.Query(query, input)

참고. 헷갈리지 마세요.

bindvar는 오직 값을 파라미터로 넣는데 사용할 수 있지, 컬럼이나 테이블 이름을 파라미터로 넣을 수는 없다.

따라서 아래와 같은 sqlx 쿼리 명령은 동작하지 않는다. 참조 링크: https://jmoiron.github.io/sqlx/ 의 bindvar 부분

반응형