보안 제품정보


[기고] DB암호화 제품(TDE)의 보안 문제점 분석-6(結) 2011.11.15

결론 : 보안상 드러난 허점에 대해서는 보완 필요


DB보안의 출발점이 DB에 대한 절대적 권한을 행사할 수 있는 관리자 계정(OS관리자인 ‘root’와 DB관리자인 ‘SYSTEM’)은 최우선적으로 통제되어야 하는 1차 통제 대상이라는 것이며, 그렇기 때문에 모든 보안 제품이 SOD(Separate of Duty, 즉 DB관리자의 권한 중 중요 데이터에 대한 접근을 통제하는 권한을 보안관리자가 행사 하도록 분리 하는 것)에 기반하고 있다.


유감스럽게도 태생적으로, DBMS 벤더에서 제공하는 TDE와 같은 보안 제품(또는 Function)들은 DB관리자가 모든 관리와 통제를 하도록 되어 있다. 즉, “DB관리자는 신뢰할 수 있다”는 바람직하지 않은 전제가 깔린 것이다.


MSSQL 2008과 Oracle 11g의 TDE들은 확인 결과 다소의 차이는 있었지만 DB암호화 제품이 갖추어야 할 보안 기능들 중 암호화 기능을 제외하면, 키 기밀성 유지 요건과 키 사용권한 통제 요건 등 중요한 기능들이 제공되지 않거나 미비함을 알 수 있었다. 특히 테이블 스페이스 단위의 암호화 방법은 메모리상에서 평문 데이터가 노출되는 문제점도 지니고 있다.


이로 인한 위험은 아주 쉽게 암호화 한 데이터의 유출이 가능하게 되며, 실제 검증으로 확인 되었다.


[검증 결과 요약]

검증 항목

MSSQL 2008의 TDE

Oracle 11g의 TDE

메모리에 테이블 전체를 평문으로 로딩하는 취약성 검증

메모리에 평문으로 암호화 테이블을 로딩하고 있으며 dump를 통해 평문으로 노출된 것이 확인됨.

메모리에 평문으로 암호화 테이블을 로딩하고 있으며, SGA를 메모리 Dump하면 평문으로 노출된 것이 확인됨.

접근통제가 안 되는 취약성 검증

암·복호키의 사용에 대한 별도의 권한통제 기능이 없어 GRANT된 사용자 또는 DBA는 복호화된 정보를 볼 수 있었다. 결국, DB가 가동되는 동안의 보안성의 암호화 이전과 같다.

좌 동

키 기밀성 유지에 관한 취약성 검증

인증서 및 키 파일과 함께 데이터 파일이 유출 되는 경우, 다른 서버에서도 제약 없이 조회가 가능하다.

wallet과 wallet open script가 함께 데이터 파일과 유출 되는 경우, 다른 서버에서도 제약 없이 조회가 가능하다. 또한 Script 또는 Interactive session에서 패스워드가 화면 상에 평문으로 노출된다.


이번에 검증해 본 방법은 주로 각 벤더사의 구축가이드 문서의 절차에 따라 시연해 보았으며, 이 외에 다른 구현 방법들도 있을 수 있을 것이다. 그러나 중요한 것은 적용 방법에 따라 보안상의 허점을 줄일 수 있는 방법이 있는 경우라 하더라도, 보안 제품은 어떠한 허점도 있어서는 안 된다.


DBMS 벤더사마다 고유한 TDE의 개발 목적이 있을 것이고 기능의 한계점 또한 공식 문서에 명확히 적시하고 있으므로 적용 하려는 입장에서 충분히 인지하고 각종 규정에 맞도록 구성하여 충족이 가능 한 경우는 사용에 문제가 없을 것이다.


유출 위험을 없애기 위해서는 어떠한 경우에도  보안성이 유지되어야 하며 이를 위해서는 필요한 모든 Option(Oracle사의 경우는, HSM과 Data Vault 및 Audit Vault 등의 제품이 준비되어 있음)을 갖추도록 사용자에게 권고하는 것이 타당하다.


국내외의 DB암호화와 관련한 모든 요건 및 규정을 준수하는 전문 보안 제품들과, 일부 요건만 충족되는 제품이 동일한 잣대로 평가 되는 불합리한 문제점에 대한 인식 개선도 필요하다.


본 기고문의 작성 목적 또한 이러한 점을 정확히 알고 한계점이나 보안상의 허점에 대한 보완을 하여야 한다는 취지에서 작성되었으며, TDE를 적용해 개인정보보호 관련 법 규정상의 요건과 DB암호화 제품의 보안 기능 요건을 충족할 수 있는 방법으로 구축 할 경우에 충족되는 부분과 충족할 수 없는 부분이 무엇인지, 그로 인해 감수해야 할 부분은 어떤 것이 있는지를 정확히 알고 이에 대한 대비책을 세우는데 조금이나마 도움이 되었으면 하는 바람이다.


[ Appendix ] findsga 유틸리티의 소스


#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

#include <unistd.h>

#include <sys/errno.h>


#define  OUTLEN   1024


main(argc, argv)

int   argc;

char  *argv[];

{

   key_t key;

   size_t   size;

   unsigned char  *pSGA, *pSGAtmp;

   char  sSearch[1024];

   int   nSearch;

   int   k, l;

   int   nRtn;

int   nShmId = 0;


   if (argc != 4) {

      printf ("%s <key> <size> <search string>\n", argv[0]);

      exit (-1);

   }


   /* Initialization */

   strcpy (sSearch, argv[3]);

   nSearch = strlen (sSearch);


   /* get key and size */

#ifdef LINUX

   key = strtoll (argv[1],NULL,16);

#else

   key = strtol (argv[1],NULL,16);

#endif

   printf ("Key = [%08x][%ld]\n", key, key);

   size = atol (argv[2]);

   printf ("size= [%ld]\n", size);

/* shmget */

   printf ("shmget...\n");

   nShmId = shmget (key, size, SHM_HUGETLB|0440);

   if (nShmId == -1) {

      printf ("Error shmget with SHM_HUGETBL with errno=[%d]\n", errno);

      nShmId = shmget (key, size, 0440);

      if (nShmId == -1) {

         printf ("Error shmget with errno=[%d]\n", errno);

         exit (-1);

      }

   }


   /* attach SGA */

   printf ("shmat...\n");

   pSGA = shmat (nShmId, NULL, 0400);

   if (pSGA == NULL) {

      printf ("Error shmat with errno=[%d]\n", errno);

      exit (-1);

   }


/* find specific string */

   int i, j;

   for (i = 0; i < size; i++) {

      if (pSGA[i] == sSearch[0]) {

         for (j=1; j < nSearch; j++) {

            if (pSGA[i+j] == sSearch[j])

               continue;

            else

               break;

         }

         if (j == nSearch) {

            /* printf ("Found: [%s]\n", &pSGA[i]); */

            printf ("Found: [%s]\n", sSearch);


            /* print data around it */

            pSGAtmp = (&pSGA[i]) - OUTLEN/2;

            for (k = 0; k < OUTLEN;k = k+16) {

               printf ("%08p ", pSGAtmp);

               for (l = 0; l < 8; l++) {

                  printf ("%02x%02x ", pSGAtmp[k+l], pSGAtmp[k+l+1]);

               }

               printf ("    ");

for (l = 0; l < 16; l++) {

                  if (pSGAtmp[k+l] >= 0x20 && pSGAtmp[k+l] <= 0x7E)

                     printf ("%c", pSGAtmp[k+l]);

                  else

                     printf (".");

               }

               printf ("\n   ");

            }  /* end of for k */


            i = i + nSearch;

         }

      }

   }  /* end of for i */




   shmdt (pSGA);


   printf ("\nDone Searching SGA data.\n");


   exit (0);

}


[글_조돈섭 이글로벌시스템 이사(alex@cubeone.co.kr)]


<저작권자: 보안뉴스(http://www.boannews.com/) 무단전재-재배포금지>