SQL 인젝션 (SQL Injection) - knex

SQL Injection

설명

SQL 인젝션은 사용자가 입력한 데이터가 쿼리에 직접 삽입될 때 발생하는 취약점입니다. 검증되지 않은 입력이 SQL 쿼리에 포함되면, 공격자는 악의적인 SQL 코드를 삽입하여 데이터베이스에 접근하거나 조작할 수 있습니다. 특히 Node.js의 knex와 같이 동적으로 쿼리를 작성하는 경우, 사용자 입력이 적절히 처리되지 않으면 SQL 인젝션에 취약해질 수 있습니다.

잠재적 영향

  • 데이터 유출 (데이터베이스 정보 노출): 공격자가 민감한 정보나 사용자 데이터를 탈취할 수 있습니다.

  • 데이터 훼손 (무단 수정 및 삭제): 공격자가 데이터베이스의 데이터를 임의로 수정하거나 삭제할 수 있습니다.

  • 인증 우회 (권한 상승): 관리자 권한으로 우회하여 서비스 전체를 장악할 수 있습니다.

해결 방법

  • 파라미터라이즈드 쿼리(Parameterized Query) 사용: 항상 user input이 SQL 쿼리에 삽입되기 전에 바인딩 변수를 사용하세요.

  • 입력값 검증 및 정제: 쿼리에 사용되는 모든 입력값을 타입 및 형식에 따라 검증, 정제(Validation/Sanitization)합니다.

  • ORM/Query Builder 기능 적극 활용: knex와 같은 라이브러리의 .raw() 보다는 .select(), .where() 등 안전한 메소드를 사용하세요.

취약한 코드 및 안전한 코드 예시

취약한 코드

app.post('/user', async (req, res) => {
  const result = await knex.raw(
    `INSERT INTO users (name, email) VALUES ('${req.body.name}', '${req.body.email}')`
  );
  res.send('User added');
});

안전한 코드

설명:

  • 취약한 코드: 위 예제는 사용자의 입력값을 직접 SQL 쿼리 문자열에 포함시켜, 공격자가 SQL 문을 조작할 수 있도록 허용합니다. 예를 들어, 이름(name)에 'test', admin-- 와 같은 값을 입력하면 쿼리 문이 변조될 수 있습니다.

  • 안전한 코드: 바인딩 변수(?, ?)를 사용하여 입력값을 별도로 처리하므로, 입력이 SQL 쿼리로 해석되지 않고 단순 데이터로만 전달되어 SQL 인젝션이 차단됩니다.

참조

Last updated