.query() 심화

Songss·2024년 12월 2일

DBMS

목록 보기
9/20

이 글을 보기전에

이전에 작성한 .query()관련 글을 보고 오는 걸 추천합니다. [링크]

.query() 메서드의 1번째 인자로 SQL 쿼리를 작성해서 넣거나 쿼리가 할당된 변수를 넣는다고 하지 않았습니까?

그런데 where의 조건이 동적으로 들어온다면 ?
Group by의 조건이 동적으로 들어온다면 ?

그래서 필요한 2가지 정도의 방식이 있습니다.


1. 문자열 보간 방식

conn.query(
	SELECT * FROM users WHERE email = '${email}'
  function (err, results) {
  if (results.length) {
    res.status(200).json(results);
  } else {
    res.status(404).json({ error: "존재하지 않는 id입니다." });
  }
}
);

위 코드는 SQL 쿼리를 작성할 때 문자열 보간법(템플릿 리터럴)을 사용하여 email 값을 직접 SQL 쿼리에 삽입합니다.

이 방식은 보안에 취약할 수 있습니다.

만약 email 변수에 악의적인 SQL 코드가 포함되어 있다면, SQL 인젝션 공격에 노출될 수 있습니다

엥? 인젝션 공격?

예시:

const email = "test@example.com'; DROP TABLE users; --";

이 경우, 쿼리는 다음과 같이 변형되어 실행될 수 있습니다:

SELECT * FROM users WHERE email = 'test@example.com'; DROP TABLE users; --';

이렇게 되면 DROP TABLE users;가 실행되어 데이터베이스의 테이블이 삭제될 수 있습니다.


그럼 어떻게 해야하나?


2. SQL 파라미터 바인딩 방식

2. SQL 파라미터 바인딩 방식

conn.query
  SELECT * FROM users WHERE email = ?,
  email,
  function (err, results) {
    if (results.length) {
      res.status(200).json(results);
    } else {
      res.status(404).json({ error: "존재하지 않는 id입니다." });
	  }
  }
);

이 코드는 파라미터 바인딩 방식으로 SQL 쿼리를 작성합니다.

?는 SQL 쿼리 내에서 placeholder 역할을 하며, 실제 값은 email 변수로 바인딩됩니다

이렇게 하면 SQL 인젝션 공격을 방지할 수 있습니다.

SQL 인젝션 공격자는 ?에 악의적인 SQL 코드를 삽입할 수 없으며, 파라미터는 안전하게 처리됩니다.

2-1. 여러개를 바인딩 해야 할 경우는 ?

// 회원 가입 (INSERT INTO)
router.post("/join", (req, res) => {
  if (req.body == {}) {
    res.status(400).json({ error: "userId, password, name은 필수입니다." });
  } else {
    const { email, name, password, contact } = req.body;
    conn.query(
      `INSERT INTO users (email, name, password, contact) VALUES (?,?,?,?)`,
      // 배열([])을 사용해서 차례로 입력 할 수 있게 해줍니다.
      [email, name, password, contact],
      function (err, result) {
        res.status(201).json({ message: `${name}님 환영합니다.` });
      }
    );
  }
});

중간에 보면 [email, name, password, contact] 처럼 배열을 사용해서 (?,?,?,?) 구문 순서대로 데이터를 입력해 줄 수 있습니다.

0개의 댓글