|
DBA: Security
데이터베이스 보안: 패스워드를 넘어서서
저자 - George Jucan
패스워드 보안이 뚫린 경우라도 Oracle Database에 내장된 보안 기능을 이용하여 내부/외부 침입자로부터 기밀 데이터를 보호할 수 있습니다.
최근 들어 개인 정보 보호의 중요성에 대한 인식이 매우 높아지고 있음을 확인할 수 있습니다. 많은 국가에서 개인 정보 보호에 관련한 법규를 새로이 제정하고 있으며, 이제 개인 신상에 관련된 데이터를 보호하는 것은 단순한 기업 이미지 관리 차원이 아닌 법적인 의무가 되었습니다.
이러한 시류에 관계없이, IT 시스템의 기밀 정보를 보호하는 것은 (그것이 OLTP 시스템이든 데이터 웨어하우징 환경이든) 비즈니스 운영의 매우 중요한 요소로 간주됩니다. 기업의 세일즈 데이터베이스에는 예외 없이 고객의 이름, 주소, 신용카드번호와 같은 정보가 저장되어 있습니다. 개인 정보는 기업의 전략적인 자산이며, 따라서 기업은 개인 정보를 사전예방적으로, 안정적으로, 그리고 포괄적으로 보호하기 위한 모든 노력을 다 해야 합니다. 이러한 관점에서 볼 때, 기업의 전략적, 전술적 결정 사항은 특정 프로세스 또는 단기적인 비즈니스 요구 사항이 아닌 비용 절감, 고객 신뢰의 개선과 같은 궁극적인 결과에 그 초점이 맞추어져야 합니다.
패키지 애플리케이션, 커스텀 애플리케이션에 대한 네트워크, 운영 체제 레벨의 불법적인 접근을 차단하기 위해 여러 가지 정교한 솔루션이 구현되고 있습니다. 하지만 실제 정보가 저장되는 데이터베이스는 표준적인 유저네임/패스워드 메커니즘으로만 보호되는 경우를 자주 찾아 볼 수 있습니다. Oracle Database 10g는 가장 최신의 유저네임/패스워드 메커니즘을 구현하고 있지만, 패스워드 보안이 뚫린다면 속수무책일 수 밖에 없습니다. 또 Oracle Database에 포함된 Oracle Virtual Private Database, Oracle Label Security 등의 솔루션으로 보안 체계를 강화하는 것이 가능하지만, 이러한 메커니즘이 실제 운영 환경에서 충분히 활용되지 못하고 있는 것이 현실입니다.
본 문서에서는 데이터베이스 패스워드 보안 체계가 뚫린 경우를 가정하고 보안 메커니즘을 구현하기 위한 방법을 (데모와 함께) 설명하기로 합니다. Oracle Database 10g Release 1의 보안 기능보안 기능 (이중 일부는 Oracle9i에서 제공됩니다)들을 간단한 방법으로 조합하여 침입자가 데이터베이스 연결을 확보한 경우에도 상당한 수준의 보안을 가능하게 하는 방법을 알아 보기로 합니다. 본 문서에서 설명되는 시나리오는 허용되지 않은 사용자(외부 해커이든 아니면 기업 내부의 DBA이든)로부터 기밀 데이터를 보호하는 것을 그 목적으로 합니다. 제공되는 예제는 OLTP 환경을 가정하고 있으나, 동일한 원칙을 비즈니스 인텔리전스, 데이터 웨어하우스 환경에도 적용할 수 있을 것입니다.
데이터베이스 보안 목표
Oracle Database는 운영 환경의 보안을 위한 핵심 구성 요소로 활용됩니다. Oracle Database 엔진을 실행하는 서버는 방화벽에 의해 보호되는 것이 일반적이지만, 이러한 방어 체계로 내부 직원 등에 의한 불법적인 접근을 차단할 수는 없습니다. Oracle Database 엔진은 고전적인 유저네임/패스워드 방식과 별도로, 외부 보안 체계가 모두 뚫린 경우에도 데이터 컨텐트를 보호하기 위한 보안 메커니즘들을 제공하고 있습니다. 아래에서 설명되는 보안 솔루션들은 데이터베이스 레벨의 보안 체계가 뚫린 경우를 가정하고 최후방의 방어 대책으로서 구현되고 있으며, 외부 보안 체계를 대체할 수 있는 대안이 될 수 없음을 참고하시기 바랍니다.
다른 모든 보안 체계가 무력화되고 데이터베이스에 대한 불법적인 접근이 가능해 진 경우를 가정했을 때, 아래에 설명된 솔루션들을 이용하여 다음과 같은 사항을 보장하는 데이터베이스 보안 체계를 구현할 수 있습니다.
- Oracle Application Server의 모든 데이터를 읽거나, 입력하거나, 수정할 수 있음. Oracle Application Server는 내부 보안 메커니즘을 이용하여 프리젠테이션 계층에서 불법적인 사용자의 중요 정보 접근을 차단함.
- SQL*Plus를 이용한 데이터베이스 보안 접근을 통해 개인 정보를 조회할 수 있음.
- 다른 데이터베이스 접근 방식으로는 고객의 개인 정보를 조회할 수 없음.
데모 셋업
예제의 시나리오는 CUSTOMER 데이터베이스, CARD_NO 컬럼 등을 사용하는 고전적인 세일즈 데이터 모델을 포함하고 있습니다. 불법적인 접근을 시도한 경우 테이블은 마치 아무 데이터도 저장하고 있는 것처럼 보입니다. 다시 말해 SELECT * from CUSTOMER; 쿼리를 실행해도 전혀 레코드가 반환되지 않습니다. 침입자들은 아무런 데이터도 저장되지 않은 것처럼 보이는 테이블에 관심을 쉽게 잃어 버리게 될 것입니다.
또 한편으로, DBMS_RLS.ADD_POLICY 호출 방법을 조금만 변경하면 다른 컬럼의 값은 그대로 출력하는 반면 CARD_NO 컬럼의 값을 숨기거나(NULL로 표시) 또는 마스킹하는(****로 표시) 방법이 가능합니다. 이 기능을 활성화하려면 DBMS_RLS.ADD_POLICY 호출 과정에서 sec_relevant_cols, sec_relevant_cols_opt 매개변수를 변경하면 됩니다. 본 문서의 관련 파일에 포함된 initial_setup.sql 스크립트는 예제에서 사용되는 아주 기본적인 형태의 CUSTOMER 테이블을 생성해 줍니다.
어떤 경우든, 스키마 오너의 계정으로 데이터에 접근하는 대신 AppSvr와 같은 별도의 계정을 모든 클라이언트 연결에서 공유하도록 설정하는 것이 권장됩니다. AppSvr 데이터베이스 사용자는 오브젝트를 전혀 소유하고 있지 않으며 CREATE SESSION 시스템 권한만을 갖고 있습니다. SELECT, INSERT, UPDATE, DELETE 권한은 스키마 오너로부터 제공받게 됩니다.
관련 파일의 enable_connection.sql 스크립트는 Oracle Application Server 기반으로 실행되는 애플리케이션에서 사용되는 사용자 계정을 생성합니다.
보안 정책의 구현
위에서 설명한 보안 목표를 실현하기 위해, "허용된(authorized)" 연결이 아닌 경우(다시 말해 특정 IP 주소를 사용한 Oracle Application Server로부터의 접속이 아닌 경우) CUSTOMER 테이블의 레코드를 숨기는 데이터베이스 정책을 구현해야 합니다. 이 정책은 Sec_Manager와 같은 Security Manager 데이터베이스 사용자에 의해 구현되며 SHIP2004, AppSvr 등의 스키마에서는 조회가 불가능합니다.
어떤 환경 변수를 사용할 것인지, 그리고 보안 정책을 통해 어떤 값을 확인할 것인지의 문제는 환경에 따라 달라집니다. 아주 많은 수의 조건들을 조합하여 활용한다면 대부분의 침입 시도를 효과적으로 차단할 수 있을 것입니다.
.
CONNECT 권한조차 허용되지 않는 Sec_Manager와 같은 별도의 스키마에 보안 정책의 모든 정의 사항들을 구현하는 것이 바람직합니다. 모든 오브젝트들은 Sec_Manager 스키마의 DBA 계정에 의해 생성됩니다. 이 계정은 아무런 권한을 작고 있지 않으며 데이터베이스 로그인조차 불가능합니다. 따라서 사용자가 소유한 보안 정의는 효과적으로 보호될 수 잇습니다. (보안 관련 오브젝트의 정의는 아무도 조회할 수 없습니다.)
하지만, 운영 상의 목적으로 일부 직원들이 SQL*Plus 레벨에서 접근해야 한다는 조건이 보안 목표에 포함되었던 것을 상기하시기 바랍니다. 이러한 "비밀 통로"의 접근 방법은 관련자들이 충분히 복잡하면서도 (포스트잇에 써놓지 않고도) 외울 수 있을 정도로 간단해야 합니다. 본 문서의 예제에서는 CLIENT_IDENTIFIER 환경 변수를 사용하고 있지만, 실제 환경에서는 임의의 환경 변수를 이용할 수 있음을 참고하시기 바랍니다.
관련 파일의 create_setup.sql 스크립트는 위에서 설명된 조건을 기준으로 보안 스키마, 조건부 함수, 보안 정책을 구현하는 방법을 예시하고 있습니다. 또 연결 방법에 따라 조회 가능한 CUSTOMER 테이블 데이터가 달라짐을 확인하기 위한 데이터 리스트가 생성됩니다. 그 밖에도 dbms_session.set_identifier 함수를 이용하여 SQL*Plus 연결에서 데이터에 접근하기 위한 "비밀 통로"를 구현하는 방법이 예시되고 있습니다.
SQL*Plus의 직접 접근
Oracle Application Server는 인증 및 권한 할당을 위한 강력한 빌트인 보안 기능을 제공합니다. 오히려 이러한 이유 때문에 SQL*Plus가 침입 경로로 활용되는 경우가 많습니다. 위에서 구현된 보안 정책을 통해 이미 다음과 같은 결과를 얻을 수 있었습니다:
- AppSvr 패스워드가 노출되어, 누군가 SQL*Plus를 통해 AppSvr로 로그인하더라도, ip 주소와 외부 세션 이름이 보안 조건과 일치하지 않기 때문에 CUSTOMER 테이블의 데이터는 표시되지 않습니다. 침입자에게, 테이블은 아무런 데이터도 저장되지 않은 것처럼 보입니다.
- 스키마 오너의 계정은 온라인 애플리케이션에 의해 사용되지 않습니다. 이 계정은 관리 용도로만 사용되며, 따라서 극히 제한된 수의 인원에게만 공개됩니다. 또 환경 변수(예제의 경우 CLIENT_IDENTIFIER)를 올바르게 설정한 경우에만 CUSTOMER 데이터를 조회할 수 있습니다. 패스워드가 노출되었다 하더라도(예를 들어 누군가가 패스워드를 적은 포스트잇을 책상 위에 붙여 놓더라도) 백도어 접근을 위한 보안 조건이 노출되지 않는 이상, 데이터베이스에 무단 침입한 사용자에게는 테이블에 아무런 데이터도 없는 것처럼 보일 것입니다. 테이블에 데이터가 존재하는지조차 파악하지 못한 침입자는 더 이상 조사해 보지 않고 접근을 포기할 것입니다.
- 다른 데이터베이스 사용자들은 설사 DBA 권한을 가지고 있다 하더라도 보호된 테이블의 레코드를 조회할 수 없습니다. 설사 다른 데이터베이스 사용자가 SHIP2004 테이블에 대한 접근 권한을 획득하더라도 달라지는 것은 없습니다. (보안 설정된 데이터를 확인하려면 보안 기능이 어떻게 설정되어 있는지를 미리 알고 있어야만 합니다.)
아래에서 제시되는 샘플 데이터를 통해 같은 결과를 확인할 수 있습니다.
데이터 및 패키지의 암호화
CARD_NO 데이터의 암호화를 통해 기밀 데이터에 대한 추가적인 보안 계층을 구현할 수 있습니다. 암호화는 외부 프로세스 또는 데이터베이스 컬럼에 저장된 정적 키(static key)를 이용합니다. 암호화 컴포넌트(키, 함수)를 두 대의 서버에 분리하여 환경의 복잡성을 높이고 침입자들이 암호로 보호된 데이터를 쉽게 해킹하지 못하도록 하는 것이 좋은 방법입니다.
키가 애플리케이션 내에 정의된 경우, 해커는 데이터를 해독하기 위해 데이터베이스 서버뿐 아니라 애플리케이션 서버까지 해킹해야 합니다. 앞 섹션에서 설명된 보안 체계를 해킹하는데 성공하더라도, 적용된 암호화 함수를 알아 내기 위해 패키지 코드를 다시 한 번 해킹해야 합니다(아래의 "보안 환경의 추가적 보안" 섹션에서 설명합니다). 또 침입자는 사용된 키를 알아내기 위해 애플리케이션 서버에 적용된 컴파일된 애플리케이션 코드를 해킹해야 할 것입니다. 키가 매개변수 파일, 소스 코드 등 일반 텍스트 파일로 저장되어 있지 않고 컴파일된 버전으로만 존재한다면, 보호된 데이터를 해킹하는데 아주 많은 스킬과 노력이 필요합니다.
하지만 본 문서의 예제 코드에서는 애플리케이션 독립성의 확보를 위해, 다른 테이블 컬럼을 암호화 키로 사용하고 있습니다. 키 컬럼에 저장된 값은 정적이어야 합니다. 이 값이 변경되면 CARD_NO 데이터를 더 이상 해독할 수 없기 때문입니다. 예제에서는 레코드 생성 이후 다시 업데이트되지 않는 CREATED_BY 컬럼이 키로 선택되었습니다.
암호화에 필요한 추가적인 작업 요소를 최소화하는 가장 편리한 방법은 오라클 암호화 유틸리티에 대한 호출을 완전히 감추어 주는 패키지를 생성하는 것입니다. 개발자는 보호된 컬럼에 직접 접근하지 않고 함수 호출만을 활용합니다. (이는 추가적인 보안 효과를 위해 치러야 하는 작은 대가로 볼 수 있습니다.) 예제에서는 DBMS_CRYPTO 패키지의 ENCRYPT, DECRYPT 함수를 사용하고 있습니다. 이 두 함수는 암호화 방법에 대한 여러 가지 옵션을 제공합니다. (자세한 정보는 오라클 제품 문서를 참고하시기 바랍니다.) 다양한 보안 옵션과 암호화 키를 조합함으로써 보안 솔루션의 복잡성을 증가시킬 수 있습니다. 특히 커스텀 패키지의 소스 코드를 아래에 설명된 방법대로 래핑(wrapping) 처리할 수 있다면 그 효과가 배가될 것입니다. (create_packages.sql 스크립트는 아래에 설명된 암호화/해독 함수를 위한 샘플 셋업을 제공합니다.)
Oracle Database 10g Release 2는 투명한 데이터 암호화 기능을 기본적으로 제공하고, 정규 데이터베이스 컬럼(날짜, 문자열, 숫자 등)을 투명하게 암호화한 후 액세스 컨트롤 검증 과정을 통과한 사용자를 위해 자동으로 해독합니다. 오라클 엔진은 데이터베이스 사용자 대신 암호화 키를 직접 관리하므로, 애플리케이션 또는 SQL에서 키 관리를 위해 다른 테이블에 접근할 필요가 없습니다. 물론 DBA가 테이블을 관리하도록 설정하는 것도 가능하며, 이 경우 DBA는 테이블의 실제 데이터 값을 조회할 수 없습니다.
암호화된 데이터의 처리
Oracle Application Server 애플리케이션은 Sec_Manager.Secure_Package 패키지의 루틴을 이용하여 CARD_NO 데이터를 Secure_Package.Secure_Data와 같은 암호화된 포맷으로 저장합니다. create_packages.sql(관련 파일 다운로드)에서 설명된 커스텀 암호화 패키지의 정의에 의하면, CARD_NO에 대한 접근은 데이터 암호화에 사용되는 컬럼 및 키의 값을 매개변수로 사용하는 함수 호출에 의해 대체됩니다.
한 예로, 'a1b2c3d4'를 암호화 키로 사용하는 경우를 가정해 봅시다. 기본적인 INSERT 구분이 아래와 같습니다.
insert into CUSTOMER (NAME, CARD_NO)
values ('Jane Doe', '1234123412341234');
must be transformed into:
insert into CUSTOMER (NAME, CARD_NO)
values ('Jane Doe', Sec_Manager.Secure_Package.Secure_Data('1234123412341234','a1b2c3d4'));
마찬가지로, Oracle Application Server 애플리케이션은 Sec_Manager.Secure_Package 루틴을 이용해서 Secure_Package.Clear_Data와 같은 해독된 포맷의 CARD_NO 데이터를 읽어 들입니다. INSERT 작업에 사용된 것과 동일한 암호화 키를 이용해서 보호 대상 정보를 일반 텍스트 형태로 가져올 수 있습니다. 기본적인 SELECT 구문이 아래와 같습니다.
select NAME, CARD_NO
from CUSTOMER;
이 구문을 다음과 같이 변경해 주어야 합니다.
select NAME, Sec_Manager.Secure_Package.Clear_Data(CARD_NO,'a1b2c3d4')
from CUSTOMER;
환경의 보안 구현
개발 작업이 모두 완료되었다면, 이제 코드를 암호화할 차례입니다. 이와 같이 함으로써 스크립트를 사용하는 DBA 자신도 보안 환경이 어떻게 구현되었는지 알 수 없음을 보장할 수 있습니다. 암호화를 위해 오라클에서 제공하는 유틸리티를 운영 체제 시스템 커맨드 프롬프트에서 실행합니다:
wrap iname=Secure_Package.sql oname=Secure_Package.sec
래핑된 상태에서, Secure_Package.sec은 다른 일반 텍스트 포맷의 스크립트와 마찬가지로 SQL*Plus 프롬프트에서 실행할 수 있습니다. 동일한 개념을 다른 보안 관련 PL*SQL 스크립트에도 적용할 수 있습니다. 이러한 방법으로 코드 프로모션 작업에 관여한 당사자들(DBA, 개발자, 지원 및 운영진)이 패키지 컨텐트를 조회할 수 없도록 차단하는 한편, 데이터베이스에 암호화된 상태로 적용함으로써 패키지의 컨텐트를 해킹하기 매우 어렵게 만들 수 있습니다.
DBA 권한을 얻은 침입자가 CONNECT 권한을 보안 오브젝트 홀더인 Sec_Manager에 할당하더라도, 일반 텍스트 형태로 데이터베이스에 저장된 오브젝트가 존재하지 않으므로 그 내용을 확인할 수 없을 것입니다. 오라클은 "unwrap" 유틸리티를 제공하지 않으며, 따라서 침입자는 패키지 컨텐트를 확인하기 위해 오라클의 암호화 알고리즘을 직접 해킹해야만 합니다.
액세스 방식과 무관하게 기밀 데이터에 대한 접근을 감사
이러한 모든 보안 대책을 구현한 상태라 하더라도, 기밀 데이터에 대한 불법적인 접근이 이루어지고 있는지 확인하는 것은 매우 중요합니다. 가장 간단한 방법은 트랜잭션을 요청하는 데이터베이스 연결 방식과 무관하게 테이블 레벨에서 SELECT, INSERT, UPDATE, DELETE 구문의 실행을 모니터하는 데이터베이스 감사 기능을 구현하는 것입니다. 그 방법이 아래와 같습니다:
audit insert, update, select on SHIP2004.CUSTOMER;
하지만, Oracle Fine Grained Auditing(FGA)을 이용하면 한층 정교한 액세스 모니터링 환경을 구현하고 최소한의 프로세싱 오버헤드만으로 의미 있는 정보를 제공받을 수 있습니다. enable_fga.sql 스크립트 예제는 DBMS_FGA 패키지를 이용하여 기본적인 감사 정책을 구현하고 있습니다. 데이터베이스에 내장된 감사 메커니즘을 사용하면 사용자들이 감사 체계를 우회할 수 없으며 따라서 그 정확성이 보장됩니다. 감사 레코드는 DBA_FGA_AUDIT_TRAIL 뷰와 DBA_COMMON_AUDIT_TRAIL 뷰에서 확인할 수 있으며 SQLBIND, SQLTEXT 정보를 추가하려면 정책에 "audit_trail = DBMS_FGA.DB_EXTENDED" 조건을 추가해 주면 됩니다.
또 본 문서에서 사용된 예제들의 기능을 확장하여, 이메일/호출기 통보 기능을 구현하거나 특정 이벤트에 대해서만 감사 레코드를 생성하도록 조건을 설정하는 것도 가능합니다. 데이터베이스 감사 정책과 그 구현 방법에 대한 자세한 정보는 오라클 제품 문서에서 확인할 수 있습니다.
결론
침입자들의 공격 방식은 점점 더 정교해지고 있으며, 시스템 설계자와 운영자는 데이터베이스 컨텐트를 보호하기 위한 개선된 방안을 적용해야만 합니다. 일반적인 보안 방법과 테크닉을 일반적이지 않은 형태로 조합함으로써 공격자들이 쉽게 해킹을 성공하지 못하도록 할 수 있습니다.
본 문서에서 설명된 방법들은 AppSvr, SHIP2004 스키마의 패스워드가 "실수로" 유출된 경우에도 그 효과를 발휘하므로, 기업의 전략적인 데이터 자산에 대한 보안 환경을 개선하고 고객 신뢰도를 보장하기 위한 방편으로 활용될 수 있습니다. 장기적인 관점에서 볼 때, 이러한 환경은 클라이언트 관계를 개선하고 비즈니스 기회를 개선하는 효과를 제공하게 될 것입니다.
다음 단계:
Oracle Platform Security 기술 정보
보안 관련 테크니컬 아티클
보안 경고 정보
George Jucan (gjucan@opendatasys.com)은 Open Data Systems의 창립자이자 CEO입니다. 1998년에 설립된 토론토 기반의 컨설팅 서비스 업체 Open Data Systems는 오라클 테크놀로지, 특히 OLAP, OLTP 환경의 데이터베이스 설계, 셋업, 관리 등을 전문 분야로 하고 있습니다. Jucan은 12년 넘게 OCP 자격을 보유하고 오라클 제품에 대한 경험을 쌓아 왔으며 DBA, 아키텍트, 프로젝트 매니저로서 활동해 왔습니다. |