안녕하세요 깍돌이 입니다.
저번에는 mysql 을 기본적으로 세팅해서 SELECT 문 정도로만 테스트로 해보았었는데요
이번에는 CRUD 작업들을 작성하기 전에 SQL 을 작성할때 흔히 말하는 "날 쿼리" 를 작성하지 않도록 하는 작업부터
해보도록 하려고 합니다.
DOCS (node-mysql2) & Prepared Statements
우선 SQL 인젝션에 대해서 조사를 하다보면 가장 많이 나오는 이야기 들이 "날 쿼리" 를 사용하지 않아야 한다는 점입니다. 예를 들면
const sql = `SELECT * FROM ${table} where uuid = ${_uuid}`;
위와같이 작성 하였을 때 날 쿼리라고 하게 됩니다. _uuid 값은 사용자가 웹에서 입력해서 넘어오는 값이 될수 있습니다. 그렇기 에 입력하는 입력 폼에서 sql injection 이 가능해지는 경우가 됩니다.
또한 해당 입력되는 값에 SQL 의 예약어가 들어오게되면 서버 에러도 유발 시킬수 있습니다.
우선 Prepared Statements 의 경우 왜 인젝션에 방어가 되는가 에 대한 설명은 블로그로 대체 하도록 하겠습니다.
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 였습니다.
감사합니다.