안녕하세요 깍돌이 입니다.

저번에는 mysql 을 기본적으로 세팅해서 SELECT 문 정도로만 테스트로 해보았었는데요

이번에는 CRUD 작업들을 작성하기 전에 SQL 을 작성할때 흔히 말하는 "날 쿼리" 를 작성하지 않도록 하는 작업부터

해보도록 하려고 합니다.

 

DOCS (node-mysql2) & Prepared Statements 

우선  SQL 인젝션에 대해서 조사를 하다보면 가장 많이 나오는 이야기 들이 "날 쿼리" 를 사용하지 않아야 한다는 점입니다.  예를 들면 

  const sql = `SELECT * FROM ${table} where uuid = ${_uuid}`;

위와같이 작성 하였을 때 날 쿼리라고 하게 됩니다.  _uuid 값은 사용자가 웹에서 입력해서 넘어오는 값이 될수 있습니다. 그렇기 에 입력하는 입력 폼에서 sql injection 이 가능해지는 경우가 됩니다. 

 

또한 해당 입력되는 값에 SQL 의 예약어가 들어오게되면 서버 에러도 유발 시킬수 있습니다. 

 

우선 Prepared Statements 의 경우 왜 인젝션에 방어가 되는가 에 대한 설명은 블로그로 대체 하도록 하겠습니다.

m.blog.naver.com/PostView.nhn?blogId=skinfosec2000&logNo=220482240245&proxyReferer=https:%2F%2Fwww.google.com%2F

 

[SQL인젝션] Prepared Statement를 쓰면 SQL 인젝션 공격이 되지 않는 이유는?

Prepared Statement의 내부 원리 개요 SQL인젝션 취약점에 대한 대응방안으로 Prepared Statement와...

blog.naver.com

SK 인포섹 블로그 라고 되어있는데 보안은 전문가들에게 맡기는게 좋을 것 같습니다. ^^ 

 

그럼이제 Node.js & mysql2 로 해당 과정을 작성하여야 하는데요 위에 잘못된 예시인 "날 쿼리" 를 변경하는 작업을 보겠습니다. 

먼저 제목과 같이 DOCS 도큐먼트라고 하죠 저희가 쓰고 있는 라이브러리는 mysql2 을 쓰고있기 때문에 mysql2 의 도큐먼트를 먼저 찾아 보는게 좋습니다. (docs가 이해가안된다면 한글로 구글링하는 방안으로 ) 도큐먼트를 자주 보다보면 어느샌가 DOCS의 틀? 프레임? 덕분에  검색되는 내용보다 더 이해가 쉽게 되는 경우가 있습니다.

 

Node.js 의 사용모듈의 DOCS를 찾을 때 저는 npm 으로 먼저 확인합니다.

 

1. npm 검색 (mysql2)

 

2. Repository 이동

여기서 HomePage가 DOCS인경우도있고 Repository 가 DOCS인 경우도 있습니다. 둘다 같은 경우도있구요 저는 Repository 로 들어가서 prepared statements에 대해 검색해보았습니다.

 

떡하니 목차가 있네요 이제 해당 DOCS를 보고 위에 있는 "날 쿼리" 를 변경해보도록 하겠습니다.

DOCS 주소입니다.(github.com/sidorares/node-mysql2#using-prepared-statements)

기존 날 쿼리

  const sql = `SELECT * FROM ${table} where uuid = ${_uuid}`;

변경된 쿼리

const sql = `SELECT * FROM ${this.table} WHERE uuid = ?`;

단순 비교하자면 uuid 를 받는 부분이 ? 로 변경되어있습니다. 해당 이유는 ( SK 인포섹 블로그 글 참조 )

 

그리고 해당을 이용하여서 전체 수정시 아래와 같이 변경할수 있습니다.

 const uuid = req.params.id;

    if(uuid!==undefined){
      const sql = `SELECT * FROM ${this.table} WHERE uuid = ?`;

      const connection = mysql.createConnection(this.db_config);
      connection.connect();
  
      connection.execute(sql,[uuid],
        function(err,results,fields){
          if(err) {
            console.error(err);
            res.status(500).json({'message':'DB Result error'});
          }
          else{
            console.log(results);
            res.status(200).json({response:results})
            ;
          }
        })
      connection.end();
    }
    else{
      res.json({message:"Not Exist UUID"});
    }

저희는 express로 DB 에 대한 API 를 작성해야 하기 때문에 위와같이 작성이 되었습니다.

http://{serverIP}/action/uuid 와 같은 형태입니다.   action?uuid= 같은 형태가 아니기때문에 

(? 뒤에 붙는 부분들을 fragment라고 하는데 express에서는 req.query로 작성하면 되지만 위와같은 경우는)

req.params으로 받습니다.  

 

유의사항

기존에는 connection.query -> 변경된 코드를 유심히 보면 connection.exeucte 입니다. 

또한 values를 매핑하기 위한 (? 에 대칭 ) 두번째 파라미터는 [ ] -> 배열의 형태를 가지고있습니다. 이부분 유의하여서 작성하시기 바랍니다. 

 

기본적인 sql Injection 에 대한 SQL prepared statements 였습니다.

 

감사합니다.

 

+ Recent posts