[MongoDB] 초보자를 위한 보안 관련 Tips

-- MongoDB 2013. 1. 7. 10:11
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.
 

2011 platformday 에서 mongoDB적용사례가소개되면서 mongoDB 시작하려는개발자분들이많아진합니다. 그래서 mongoDB대한학습을이제시작하려는분들을위해 mongoDB 설치직후확인해야보안관련내용을공유할까합니다.

 

우선 mongoDB대한간략한소개를하겠습니다.

 

mongoDB ?

 

스키마에 제약 없이 json 형태의 Document 를 저장하는 오픈소스 NoSQL DB 입니다.


schema-free ?

collection(= table) 에 저장할 documents(= row, record) 의 구조에 대해 미리 정의 할 필요가 없습니다. 또한 동일한 collection에 다른 구조를 가진 document를 저장할 수 있습니다.


document ?

document 는 key/value 쌍의 데이터를 저장하며 key는 string 이며, values 는 data type 의 어떤 것도 가능합니다.

 

feature

 

Agility & Scalability

스키마의 제약이 없기 때문에 개발시 유연성을 제공합니다.

auto sharding 을 통해 수평 확장이 가능하며 단순 Master/Slave 구조를 넘어 replica set통해자동으로장애를감지하고복구합니다.

 

mongoDB 구성 방식


  • Stand-Alone – 단독설치… 다 아시죠? ^^
  • Replica-Set
    Master/slave 구조보다 좀 더 안정적인 방법으로 Master와 같은 역할을 하는 Primary서버에 장애가 감지되면 자동으로 새로운 Primary 서버를 선정하고 동작하게 함으로써 일관성 및 가용성을 보장하는 방식입니다. 1.6 버전 이상에서 사용할 수 있습니다.
  • Sharding
    range 파티션 기법으로 shard key를 중심으로 데이터를 여러 shard 서버에 분산하여 저장하는 방식이며 shard 서버들간의 데이터 balancing 도 모두 자동으로 이루어 집니다.
    고가용성을 위해 Replica-set 과 shrding 방식을 함께 사용할 수 있습니다.

 

이외에도 많은 기능과 장점을 갖고 있지만, 소개는 이정도로 하고 본격적으로 제가 알려드리고 싶은 보안 관련 Tips 을 소개하겠습니다.

 

mongoDB 를 학습하고자 stand-alone 방식으로 설치를 하고 제일 먼저 든 의문이 ‘root 계정은 어디에서 설정 하는걸까?였습니다. MySQL 설치해분들이라면저와같은의문을갖게되실 겁니다. 관리자계정을추가하는방법을찾는과정에서몇가지보안관련내용을확인하게되었습니다.

 

mongoDB 보안 관련 Tips

 

mongoDB 는 설치과정이 매우 간단합니다. 물론 replica-set 이나 sharding 방식에서는 몇가지 설정 과정이 더 필요하지만 기본적으로 stand-alone방식으로 설치할 경우에는 mysql의 설치과정보다 조금 더 간단합니다. 그러나 설치 후에 꼭 확인해야 할 보안 관련 항목이 있습니다.

 

Tip1. Configuring Authentication


mongoDB 는 설치 후 누구나 DB에 접속있습니다설치과정 중에 인증과 관련해 설정하는 부분이 없기 때문입니다. mongoDB 에서도 허가된 사람만 DB에 접속할 수 있도록 계정 및 패스워드를 설정할 수 있습니다.


물론 MySQL과 마찬가지로 DB인스턴스(bin/mongod)를 실행할 때 인증 정보를 사용하겠다는 파라미터(–auth)를 포함해야 합니다. database별로 계정과 패스워드를 추가합니다. 아래는 admin과 test2라는 데이터베이스에 계정을 추가하는 모습입니다.

 

[kthserver]$ ./mongodb-linux-x86_64-1.8.1/bin/mongo

MongoDB shell version: 1.8.1

connecting to: test


> use admin

switched to db admin


> db.addUser(“admin”, “1234″)

{

        “user” : “admin”,

        “readOnly” : false,

        “pwd” :“08ccdf34dbb3ca05dcc195e30994b628″

}


> use test2

switched to db test2

> db.addUser(“test2user”,”test2pass”)

{

        “user” : “test2user”,

        “readOnly” : false,

        “pwd” :“94cb14434128765982f33b2a5256fc28″

}


> exit

bye


[kthserver]$ ./mongodb-linux-x86_64-1.8.1/bin/mongo test2

MongoDB shell version: 1.8.1

connecting to: test2


> db.user.find()

{ “_id” :ObjectId(“4df97549e53741341c1d8b72″), “name” : “yhee” }

 

계정 설정 후 DB에 접속해보면 여전히 인증절차 없이 user collection (= table) 의 데이터 확인이 가능합니다. 인증을 적용하기 위해서는 –-auth parameter 를 추가하여 DB 인스턴스(bin/mongod)를 재시작해야 합니다

 

[kthserver]$ ./mongodb-linux-x86_64-1.8.1/bin/mongod –auth

Thu Jun 16 15:54:19 [initandlisten] MongoDB starting : pid=18189port=27017 dbpath=/data/db/ 64-bit

Thu Jun 16 15:54:19 [initandlisten] db version v1.8.1, pdfile version4.5

 

다시 mongo  (mysql에서 bin/mysql 과 같은 client 프로그램) 를 통해 DB 접속을 합니다. test2  DB에서 find (= select ) 실행하자에러가납니다db.auth 구문을 통해 인증을 거치고 나면 비로소 데이터를 확인할 수 있습니다.

 

[kthserver]$./mongodb-linux-x86_64-1.8.1/bin/mongo      

MongoDB shell version: 1.8.1

connecting to: test


> use test2

switched to db test2


> db.user.find()

error: {

        “$err” : “unauthorizeddb:test2 lock type:-1 client:127.0.0.1″,

        “code” : 10057

}


> db.auth(“test2user”,“test2pass”)

1


> db.user.find()

{ “_id” : ObjectId(“4df97549e53741341c1d8b72″), “name” : “yhee” }

 

DB에 접속 후에 db.auth 커맨드로 인증을 하는 과정은 MySQL 을 사용했던 개발자들에겐 다소 어색한 방법이긴 합니다. MySQL 과 같이 DB접속 시 commandline parameter 를 통해 인증 하는 방법도 가능합니다.

 

[kthserver]$ ./mongodb-linux-x86_64-1.8.1/bin/mongo test2 -utest2user2 -p 

MongoDB shell version: 1.8.1

Enter password:

connecting to: test2


> db

test2


> db.user.find()

{ “_id” :ObjectId(“4df97549e53741341c1d8b72″), “name” : “yhee” }

 

각 DataBase별로 계정정보는 system.users 라는 namespace에 저장됩니다. db.removeUser(username) 구문으로 계정 삭제가 가능합니다.

 

[kthserver]$ ./mongodb-linux-x86_64-1.8.1/bin/mongo test2 -utest2user2-p

MongoDB shell version: 1.8.1

Enter password:

connecting to: test2


> show collections

system.indexes

system.users

user


> db.system.users.find()

{ “_id” : ObjectId(“4df9a62a56a9d7ada79dd403″), “user” : “test2user”,“readOnly” : false, “pwd” : “94cb14434128765982f33b2a5256fc28″ }

{ “_id” : ObjectId(“4df9a9cd223b76afab6d4e74″), “user” : “test2user2″, “readOnly” : false, “pwd” : “d0c70872c885f082c5b64c0e71367b61″ }


> db.removeUser(“test2user”)


> db.system.users.find()   

{ “_id” : ObjectId(“4df9a9cd223b76afab6d4e74″), “user” : “test2user2″,“readOnly” : false, “pwd” : “d0c70872c885f082c5b64c0e71367b61″ }

 

이외에도 패스워드 변경이나 데이터 조작 권한 등을 변경 할 수 있습니다.

 

Tip2. Stopping Mongo


DB인스턴스(mongod) 를 안전하게(clean exit) 종료하는 방법은 세가지가 있습니다.


[첫번째]  

DB인스턴스를 위와같이 foreground 로 실행한 경우는 간단히 “Ctrl-C”이용하며  “kill -2 PID,” or “kill -15 PID”가능합니다.


[두번째]  

mongo쉘을이용하여 admin database에서 db.shutdownServer()커맨드를실행합니다.

 

[kthserver]$ ./mongodb-linux-x86_64-1.8.1/bin/mongo admin

MongoDB shell version: 1.8.1

connecting to: admin


> show dbs

Thu Jun 16 20:08:45 uncaught exception: listDatabases failed:{

       assertion :unauthorized db:admin lock type:-1 client:127.0.0.1″,

        “assertionCode” : 10057,

        “errmsg” : “db assertionfailure”,

        “ok” : 0

}


> show collections

Thu Jun 16 20:08:49 uncaught exception: error: {

       $err : unauthorized db:adminlock type:-1 client:127.0.0.1″,

        “code” : 10057

}


> db.shutdownServer()

Thu Jun 16 20:09:04 DBClientCursor::initcall() failed

Thu Jun 16 20:09:04 query failed :admin.$cmd { shutdown: 1.0 } to: 127.0.0.1

server should be down…

Thu Jun 16 20:09:04 trying reconnect to127.0.1

Thu Jun 16 20:09:04 reconnect 127.0.0.1failed couldn’t connect to server 127.0.0.1

Thu Jun 16 20:09:04 Error: error doingquery: unknown shell/collection.js:150

 

매뉴얼에서는 admin DB에서 인증한 경우에  shutdown 가능하다고했지만 현재제가설치한 1.8.1 버전에서는다른결과를보여주고 있었습니다.


mongod (DB인스턴스)는  auth 파라미터와함께구동상태입니다admin DB에 접속을 했을 뿐 인증을 하지는 않은 상태에서 db.shutdownServer() 커맨드가 동작했습니다. 물론 mongod shutdown 되었습니다.

 

마찬가지로 이전 버전인 1.6.5 버전에서테스트를진행해보았습니다.


그런데 1.6.5 버전에서는 admin 계정에 대해서 인증이 된 경우에만 db.shutdownServer()가 실행되는 것을 볼수 있었습니다. 결국 1.8.1 버전에서의 문제로 보입니다.

 

[kthserver]$ ./mongodb-linux-x86_64-1.6.5/bin/mongo test

MongoDB shell version: 1.6.5

connecting to: test


> show collections

Thu Jun 16 20:45:48 uncaught exception: error: {

        “$err” : “unauthorizeddb:test lock type:-1 client:127.0.0.1″,

        “code” : 10057

}


> db.auth(“test_1.6″, “1234″)

1


> db.shutdownServer()

shutdown command only works with the admin database; try ‘use admin’


> useadmin

switched to db admin


> db.shutdownServer()

assert failed : unexpected error: “shutdownServer failed: db assertion failure

Thu Jun 16 20:46:23 uncaught exception: assert failed : unexpectederror: “shutdownServer failed: db assertion failure”


> db.auth(“admin_1.6″,”1234″)

1


> db.shutdownServer()

Thu Jun 16 20:46:50 query failed :admin.$cmd { shutdown: 1.0 } to: 127.0.0.1

server should be down…

Thu Jun 16 20:46:50 trying reconnect to127.0.0.1

Thu Jun 16 20:46:50 reconnect 127.0.0.1failed couldn’t connect to server 127.0.0.1

Thu Jun 16 20:46:50 MessagingPort saysend() errno:9 Bad file descriptor 127.0.0.1:27017

Thu Jun 16 20:46:50 Error: error doingquery: unknown (anon):1526

 

[세번째]

driver통해서 {shutdown : 1 } 커맨드를이용하여 shutdown 하는 방법입니다예를 들면 php 에서는 아래와 같이 테스트 할 수 있습니다. 1.6.5 버전의 mongoDB 를 테스트 한 경우입니다.

 

<?php

// connect

$m = new Mongo();

// select a database

$db = $m->admin;

// authentication

$db->authenticate(“admin_1.6″,”1234″);

// shutdown

$db->command(array(“shutdown”=>1));

……

 

로그를 보면 shutdown 이 이루어지고 있는 과정을 확인 할 수 있습니다.

 

Thu Jun 16 21:29:09 [initandlisten] waiting for connections on port27017

Thu Jun 16 21:29:09 [websvr] web admin interface listening on port28017

Thu Jun 16 21:29:18 [initandlisten] connection accepted from127.0.0.1:47439 #1

Thu Jun 16 21:29:18 [conn1] end connection 127.0.0.1:47439

Thu Jun 16 21:34:33 [initandlisten] connection accepted from127.0.0.1:47226 #2

Thu Jun 16 21:34:33 [conn2] terminating,shutdown command received

Thu Jun 16 21:34:33 dbexit:

Thu Jun 16 21:34:33 [conn2] shutdown: going to close listening sockets…

Thu Jun 16 21:34:33 [conn2] closing listening socket: 5

Thu Jun 16 21:34:33 [conn2] closing listening socket: 6

Thu Jun 16 21:34:33 [conn2] closing listening socket: 7

Thu Jun 16 21:34:33 [conn2] closing listening socket: 8

Thu Jun 16 21:34:33 [conn2] shutdown: going to flush oplog…

Thu Jun 16 21:34:33 [conn2] shutdown: going to close sockets…

Thu Jun 16 21:34:33 [conn2] shutdown: waiting for fs preallocator…

Thu Jun 16 21:34:33 [conn2] shutdown: closing all files…

Thu Jun 16 21:34:33 closeAllFiles() finished

Thu Jun 16 21:34:33 [conn2] shutdown: removing fs lock…

Thu Jun 16 21:34:33 dbexit: reallyexiting now

Thu Jun 16 21:34:33 ERROR: Client::~Client _context should be null butis not; client:conn


마찬가지로 1.8.1 버전을 테스트 한 경우에 mongo shell에서 인증과 상관없이 db.shutdownServer() 가 동작했듯이 driver를 통해서도 인증 없이 shutdown이 진행되었습니다. 1.6.5 버전에서는 인증절차를 통해 shutdown이 동작하지만 1.8.1 버전에서는 shutdown 과 관련한 버그로 보입니다.


이와 관련된 내용입니다. 

https://jira.mongodb.org/browse/SERVER-3048


현재 사용하는 버전이나 또는 사용 계획이 있는 버전에 대해서 확인 하시기 바랍니다.

 

Tip3. HTTP interface Security

 

mongoDB는 db 상태를 확인 할 수 있는 http interface 를 제공합니다. 기본적으로 mongod DB인스턴스가 사용하는 port+1000 번을 사용합니다. mongd 인스턴스를 defult 27017 port 로 구동했다면 HTTP interface 는 아래와 같이 28017port 로 확인 합니다.


–auth parameter 없이 mongod 를 구동했다면 누구나 볼 수 있기 때문에 HTTP interface 역시 보안에 문제가 될 수 있습니다.

 

http://localhost:28017 or http://1.2.3.4:28017

 

(그림생략)

 

물론 매뉴얼에서는 보안을 위해 -–auth 옵션으로 mongod 인스턴스를 구동한 경우에는 http interface 접근 시인증을거쳐야한다고설명했지만 실제로 1.8.1 버전에서는 계속해서 인증에러가 발생하는 것을 확인 할 수 있었습니다. 이 또한 mongdb 1.8.1 버전의 버그로 보입니다.  


관련된내용입니다.

 

https://jira.mongodb.org/browse/SERVER-2917

http://www.mongodb.org/display/DOCS/Http+Interface#HttpInterface-HTTPConsoleSecurity

 

현재 사용하는 버전이나 또는 사용 계획이 있는 버전에 대해서 확인 하시기 바랍니다. 저는 Http interface 를 사용하지 않도록 설정했습니다. mongod  인스턴스시작시–-nohttpinterface 파라미터를 추가하면 됩니다.

 

[kthserver]$ ./mongodb-linux-x86_64-1.8.1/bin/mongod–auth –nohttpinterface

 

이상 세가지보안관련항목에대해서살펴봤습니다. 


요약하면,


1. mongoDB 설치 후 admin 계정과 각 DATABASE 별로 접근을 허용할 계정을 설정하시기 바랍니다. –-authparameter 와 함께 mongod 인스턴스를 구동하시기 바랍니다.


2. DB 를 shutdown 하는 것은 관리자만이 할 수 있어야 합니다. –-auth parameter 와 함께 mongod 인스턴스를 구동하시기 바랍니다. 또한 정상적으로 인증이 이루어지는 현재 사용 중이거나 사용계획이 있는 버전에 대하여 확인 하시기 바랍니다.


3. 누구나 Http interface 에 접근해서는 안됩니다. –-auth parameter 와 함께 mongod 인스턴스를 구동하시기 바랍니다. 물론, mongod 인스턴스구동시 disable 있습니다.

 

출처 : http://dev.kthcorp.com/2011/06/22/mongodb-security-tips-for-beginners/

'-- MongoDB' 카테고리의 다른 글

[MongoDB] Database 명령어  (0) 2013.01.08
[MongoDB] 집계  (0) 2013.01.07
[MongoDB] 인덱스  (0) 2013.01.05
[MongoDB] $where 쿼리  (0) 2013.01.02
[MongoDB] 문서에 배열 사용하기  (0) 2013.01.02
posted by 어린왕자악꿍