SQL Injection에 대해서는 많이 들어봣을 것이다.
NoSQL에서도 비슷한 NoSQL Injection 가능하다.
대표적인 NoSQL 중 하나인 MongoDB에서의 NoSQL Injection에 대해 얘기해보겠다.
key-value pair로 이루어진 Json 오브젝트 형태로 데이터를 저장한다.
MongoDB를 사용하면서 가장 편리하다고 느낀 부분은 다음 두 가지이다.
- 자동 생성되는 _id 필드가 Primary Key로 사용된다.
- Json 쿼리를 사용해서 데이터를 얻을 수 있다.
위와 같은 특성 때문에 NoSQL이지만 쿼리를 보다 간편하게 사용할 수 있어서, 관계성이 있는 데이터에 대한 처리도 보다 쉽게 처리할 수 있었다.
아래는 데이터를 삽입 & 검색하는 예시다.
db.dbName.insert({key: 'value'})
key:value로 이루어진 데이터를 DB에 넣는다.
db.dbName.find( { $and: [ { key_1: "value_1" }, { key_2: { $ne: value_2 } } ] } )
mongodb query operator를 사용해서 원하는 값을 가져올 수 있다.
$를 사용해서 검색 조건 및 방식을 특정한다.
( https://docs.mongodb.com/manual/reference/operator/query/ )
이런 MongoDB에서도 NoSQL Injection이 발생할 수 있다.
위에서 봤듯이, mongoDB에서는 Json안에서 쿼리를 $ 표시를 통해 구분한다.
그렇기 때문에 만약에 데이터 타입 검증을 충분히 거치지 않는다면, 이를 이용한 query injection이 발생할 수 있다.
예시를 통해 간단하게 설명해보겠다.
다음과 같이 user db를 조회해서 로그인하는 상황을 가정해보자
db.user.find({
'uid': req.query.uid,
'upw': req.query.upw
})
사용자가 id, pw를 입력하고 이 값을 req.query.uid, req.query.upw로 받아서 사용하는 상황이다.
이때 http://{API주소}/query?uid[$ne]=a&upw[$ne]=b
와 같은 방식으로 요청을 보낸다면, 사용자는 id가 a가 아니고, pw가 b가 아닌 조건문을 통과하여 로그인 할 수 있게 되는 것이다.
이외에도, $where
이나 $regex
를 활용해서 보다 세밀한 데이터 탈취가 가능하다.
단순 sql injection을 통한 조건문 통과를 넘어서, blind injection 방식을 통해 구체적인 정보를 탈취할 가능성도 있는 것이다.
https://www.mongodb.com/docs/manual/reference/operator/query/
https://dreamhack.io/wargame/challenges/90/
https://www.hahwul.com/2016/01/12/web-hacking-nosql-injection-mongodb/