보안의 새로운 기능

  • 감사
  • 권한 분석
  • Data Redaction
  • 기타 향상된 보안 기능
  • 보안 기능의 조합과 호환

감사

  • 법률이나 규제 준수 OR 다른 레벨의 감사 ( DBA )

SGA에서의 변경사항

  • Unified Audit
    • Queue : 메모리에서 감사 활동을 기록하는 데 사용
      • 첫 번째 큐가 다 채워지면 두번재 큐에 적재
      • 가득찬 첫 번째 큐는 백그라운드 프로세스인 GEN0이 audsys( Read-only )테이블에 메모리의 기록을 내려쓴다.
      • 크기 : 1MB(디폴트) ~ 30MB ( unified_audit_sga_queue_size

Unified Audit 활성화

  • 디폴트 : 비활성화
  • 활성화 : Relink
  • 1. ORACLE_HOME에서 구동되는 모든 오라클 프로세스를 정지한다 ( 리스너와 데이터베이스 )
  • 2. uniaud_on 파라미터를 사용해서 오라클 데이터베이스 바이너리 파일을 Relink 한다.
  • 3. 오라클 프로세스를 재시작한다.
  • 4. "and Unified Auditing" 라는 텍스트가 로그인 배너에 마지막에 표시


[oracle@localhost lib]$ cd $ORACLE_HOME/rdbms/lib
[oracle@localhost lib]$ make -f ins_rdbms.mk uniaud_on ioracle ORACLE_HOME=$ORACLE_HOME ( 몇분 소요 )


톰 카이트의 한 마디

  • Audit Trail를 시스템의 로드 상황에 따라서 대략적으로 시간 기반으로 3초마다 내려쓸 수 있다.
  • 따라서 SGA상에서 오랜기간 동안 Audit Trail 레코드가 머물러 있지 않아도 된다.
  • 큐 사이즈에 상관없이 정기적으로 디스크에 내려쓰는 편이 훨씬 안전하다.

Immediate Write 모드 지정



EXEC DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_PROPERTY(
  DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
  DBMS_AUDIT_MGMT.AUDIT_TRAIL_WRITE_MODE,
  DBMS_AUDIT_MGMT.AUDIT_TRAIL_IMMEDIATE_WRITE);



의무의 분리

  • Role
    • AUDIT_ADMIN : 감사 정책을 관리 및 설정
    • AUDIT_VIEWER : 감사 결과만을 검토

BAI ( Basic Audit information )

  • MR_SMITH ( 계정 ) : 감사 관리자
  • AUDITMAN ( 계정 ) : 감사 결과 리뷰하는 유저


-- 테이블 생성
CREATE TABLE HR.CC_INFO (
  FNAME VARCHAR2( 30 ),
  LNAME VARCHAR2( 30 ),
  CCNUM VARCHAR2( 30 ),
  CCCODE VARCHAR2( 10 ),
  ZIP_CODE VARCHAR2( 10 )
) TABLESPACE EXAMPLE;


-- 감사 정책을 만드는 AUDIT_ADMIN 롤을 가진 MR_SMITH를 생성한다.
CREATE USER MR_SMITH IDENTIFIED BY sunglasses
DEFAULT TABLESPACE USERS;
GRANT CONNECT, RESOURCE TO MR_SMITH;
ALTER USER MR_SMITH QUOTA 10M ON USERS;
GRANT AUDIT_ADMIN TO MR_SMITH;

-- BAI를 검토할 수 있는 AUDITMAN 유저를 생성한다.
CREATE USER AUDITMAN IDENTIFIED BY auditme
DEFAULT TABLESPACE USERS;
GRANT CONNET, RESOURCE TO AUDITMAN;
ALTER USER AUDITMAN QUOTA 10M ON USERS;
GRANT AUDIT_VIEWER TO AUDITMAN;

-- MR_SMITH 계정으로 HT.CC_INFO 테이블에 T001 정책을 활성화한다.
CREATE AUDIT POLICY T001 ACTIONS SELECT, INSERT, UPDATE, DELETE ON HR.CC_INFO;
AUDIT POLICY T001;

-- 그리고 감사 레코드를 디스크로 바로 쓸 수 있도록 UAT 설정을 변경한다.
EXEC DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_PROPERTY(
  DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
  DBMS_AUDIT_MGMT.AUDIT_TRAIL_WRITE_MODE,
  DBMS_AUDIT_MGMT.AUDIT_TRAIL_IMMEDIATE_WRITE);

-- DML을 수행하기 전에 다음 쿼리로 정책 활성화 유무를 확인한다.
SELECT * FROM AUDIT_UNIFIED_ENABLED_POLICIES
WHERE POLICY_NAME = 'T001';

-- 쿼리 결과가 다음과 같이 표시되어야 한다.
USER_NAME POLICY_NAME ENABLED_OPT SUC FAI
--------- ----------- ----------- --- ---
ALL USERS T001        BY          YES YES

-- HR 계정으로 로그인해서 감사 레코드를 생성하기 위해 다음 DML을 수행한다.
INSERT INTO HR.CC_INFO VALUES( 'TOM', 'LEE', '123456789', '1234', '91729' );
INSERT INTO HR.CC_INFO VALUES( 'CHUCK', 'SMITH', '234567891', '2345', '91730' );
INSERT INTO HR.CC_INFO VALUES( 'DAVID', 'KIM', '345678912', '3456', '91731' );
INSERT INTO HR.CC_INFO VALUES( 'VIK', 'MICHELLE', '456789123', '4567', '91732' );
INSERT INTO HR.CC_INFO VALUES( 'FOCUS', 'VISION', '567891234', '5678', '91733' );

COMMIT;

UPDATE HR.CC_INFO SET ZIP_CODE = '99999'
WHERE ZIP_CODE = '91733';

COMMIT;

DELETE FROM HR.CC_INFO
WHERE ZIP_CODE = '99999';

COMMIT;

-- AUDITMAN 유저가 HR.CC_INFO에 발생한 DML 작업을 확인할 수 있도록 위의 모든 문장을 실행하고
-- AUDITMAN 유저로 HR.CC_INFO에 테이블 생성과 DML 작업을 확인하기 위해 다음 쿼리를 실행한다.
SELECT EVNET_TIMESTAMP,
       OBJECT_SCHEMA || '.' || OBJECT_NAME AS 'AUDIT_OBJECT",
       SQL_TEXT 
  FROM UNIFIED_AUDIT_TRAIL
 WHERE OBJECT_NAME = 'CC_INFO'
   AND OBJECT_SCHEMA = 'HR'
   AND OBJECT_SCHEMA IS NOT NULL
 ORDER BY EVENT_TIMESTAMP;
 
-- MR_SMITH 계정으로 정책을 비활성화하고 삭제한다.
NOAUDIT POLICY T001;
DROP AUDIT POLICY T001;

-- 쓰기 정책을 디폴트로 변경한다.
EXEC DBMS_AUDIT_MGMT.SET_AUDIT_TRAIL_PROPERTY(
  DBMS_AUDIT_MGMT.AUDIT_TRAIL_UNIFIED,
  DBMS_AUDIT_MGMT.AUDIT_TRAIL_WRITE_MODE,
  DBMS_AUDIT_MGMT.AUDIT_TRAIL_QUEUED_WRITE);


EAI ( Extended Audit Information )

  • FGA : Fine Grained Auditing
  • 데이터 펌프 익스포트 / 임포트
  • RMAN 작업
  • OLS
  • DATABASE VAULT
  • RAS

권한 분석 ( PA )

  • 유저나 롤에 과도한 권한이 부여되어 있는지를 확인하는 데 사용

권한 분석 개요

  • 오라클 12c에서 PA 프로세스는 다음의 과정으로 이루어져 있다.
  • 1. 분석 캡쳐 프로세스( ACP )를 생성한다. 다음 4가지 옵션 중 하나를 선택할 수 있다.
    전체 데이터베이스 캡쳐, 롤 캡처, 컨텍스트 캡쳐, 롤과 컨텍스트 조합 캡처
  • 2. ACP 활성화
  • 3. 일정 기긴 동안 ACP가 권한 사용 현황을 기록할 때까지 기다린다.
  • 4. ACP 비활성화
  • 5. ACP의 결과 생성
  • 6. ACP의 결과를 분석

권한 분석 예제



-- 테이터베이스 차원의 분석 캡쳐를 수행
BEGIN DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTURE(
  NAME => 'PRIV_ANALYSIS_DB',
  DESCRIPTION => 'ANALYZE ALL PRIVILEGES IN DB',
  TYPE => DBMS_PRIVILEGE_CAPTURE.G_DATABASE);
END;
/

-- 롤에 의한 캡처를 수행하려는 경우는 다음 문장을 수행
BEGIN DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTURE(
  NAME => 'PRIV_ANALYSIS_DB',
  DESCRIPTION => 'RECORD PRIVILEGES USE BY PUBLIC',
  TYPE => DBMS_PRIVILEGE_CAPTURE.G_ROLE, 
  ROLES => ROLE_NAME_LIST( 'RESOURCE'));
END;
/

-- 롤과 CONTEXT 조합으로 분석 캡처를 하려면 다음을 수행한다.
BEGIN DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTURE(
  NAME => 'PRIV_ANALYSIS_HR_USER_RESOURCE',
  DESCRIPTION => 'RECORD PRIVILEGE USE BY HR USER WITH RESOURCE',
  ROLES => ROLE_NAME_LIST( 'RESOURCE' );
  CONDITION => 'SYS_CONTEXT( ''USERENV'', ''SESSION_USER'' ) = ''HR''');
END;
/

-- 롤과 CONTEXT 조합으로 분석 캡처를 하려면 다음을 수행한다.
BEGIN DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTURE(
  NAME => 'PRIV_ANALYSIS_HR_USER_RESOURCE',
  DESCRIPTION => 'RECORD PRIVILEGE USE BY HR USER WITH RESOURCE',
  TYPE => DBMS_PRIVILEGE_CAPTURE.G_ROLE_AND_CONTEXT,
  ROLES => ROLE_NAME_LIST( 'RESOURCE' );
  CONDITION => 'SYS_CONTEXT( ''USERENV'', ''SESSION_USER'' ) = ''HR''');
END;
/

-- HR 유저에 대해서만 분석 캡처생성한다.
BEGIN DBMS_PRIVILEGE_CAPTURE.CREATE_CAPTURE(
  NAME => 'PRIV_ANALYSIS_HR_USER',
  DESCRIPTION => 'RECORD PRIVILEGE USE BY HR USER',
  TYPE => DBMS_PRIVILEGE_CAPTURE.G_CONTEXT;
  CONDITION => 'SYS_CONTEXT( ''USERENV'', ''SESSION_USER'' ) = ''HR''');
END;
/

EXEC DBMS_PRIVILEGE_CAPTURE.ENABLE_CAPTURE( NAME => 'PRIV_ANALYSIS_HR_USER' );

DROP TABLE HR.CC_INFO PURGE;

-- 테이블 생성
CREATE TABLE HR.CC_INFO (
  FNAME VARCHAR2( 30 ),
  LNAME VARCHAR2( 30 ),
  CCNUM VARCHAR2( 30 ),
  CCCODE VARCHAR2( 10 ),
  ZIP_CODE VARCHAR2( 10 )
) TABLESPACE EXAMPLE;


INSERT INTO HR.CC_INFO VALUES( 'TOM', 'LEE', '123456789', '1234', '91729' );
INSERT INTO HR.CC_INFO VALUES( 'CHUCK', 'SMITH', '234567891', '2345', '91730' );
INSERT INTO HR.CC_INFO VALUES( 'DAVID', 'KIM', '345678912', '3456', '91731' );
INSERT INTO HR.CC_INFO VALUES( 'VIK', 'MICHELLE', '456789123', '4567', '91732' );
INSERT INTO HR.CC_INFO VALUES( 'FOCUS', 'VISION', '567891234', '5678', '91733' );

COMMIT;

UPDATE HR.CC_INFO SET ZIP_CODE = '99999'
WHERE ZIP_CODE = '91733';

COMMIT;

DELETE FROM HR.CC_INFO
WHERE ZIP_CODE = '99999';

COMMIT;

EXEC DBMS_PRIVILEGE_CAPTURE.DISABLE_CAPTURE( NAME => 'PRIV_ANALYSIS_HR_USER' );
EXEC DBMS_PRIVILEGE_CAPTURE.GENERATE_CAPTURE( NAME => 'PRIV_ANALYSIS_HR_USER' );


표 9.1 Previlege Analysis에 관련된 View

  • DBA_USED_SYSPRIVS : system privilege가 사용되었는지 분석
  • DBA_USED_OBJPRIVS : object privilege가 사용되었는지 분석
  • DBA_USED_PRIVS : system과 object privilege가 사용되었는지 분석
  • DBA_USED_OBJPRIVS_PATH : 어떻게 Privilege가 부여되었는지 분석
  • DBA_UNUSED_PRIVS : system과 object privilege가 사용되지 않앗는지 여부 분석


-- System Previlege가 사용되는지 분석
SELECT USERNAME, USED_ROLE, SYS_PRIV
  FROM DBA_USED_SYSPRIVS
 WHERE USERNAME = 'HR';
 
 -- Object Privilege가 사용되는지 분석
 SELECT USERNAME, OBJECT_OWNER,
        OBJECT_NAME, OBJECT_TYPE, OBJ_PRIV
   FROM DBA_USED_OBJPRIVS
  WHERE USERNAME = 'HR';
  
 -- System과 Object Privilege가 사용되었는지 분석
 SELECT USERNAME, SYS_PRIV, OBJ_PRIV,
        OBJECT_OWNER, OBJECT_NAME
   FROM DBA_USED_PRIVS
  WHERE USERNAME = 'HR';
  
-- 어떻게 Previlege가 획득되었는지 분석
SELECT USERNAME, OBJ_PRIV,
       OBJECT_NAME, PATH
  FROM DBA_USED_OBJPRIVS_PATH
 WHERE USERNAME = 'HR';
 
-- system과 Object Previlege가 사용되지 않았는지 분석
SELECT USERNAME, SYS_PRIV, OBJ_PRIV,
       OBJECT_OWNER, OBJECT_NAME
  FROM DBA_UNUSED_PRIVS
 WHERE USERNAME = 'HR';
 
-- 캡처 삭제
EXEC DBMS_PRIVILEGE_CAPTURE.DROP_CAPTURE( NAME => 'PRIV_ANALYSIS_HR_USER' );


Data Redaction

  • Data Masking : 실제 데이터 가공
  • Data Redaction : 데이터 자체는 변경시키지 않고 단지 보여주는 데이타만 가공한다.
    • 11.2.0.4 에서도 사용할 수 있다
    • Oracle Redaction : Oracle Advanced Security

Data Redaction 시나리오



-- 적용 전
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY EMAIL     PHONE_NUMBER
----------- ---------- --------- ------ --------- ------------
        205 Shelly     Higgins    12008 SHIGGINS  515.123.8080
        206 William    Gletz       8300 WGIETZ    515.123.8181

-- 적용 후
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY EMAIL     PHONE_NUMBER
----------- ---------- --------- ------ --------- ------------
        205 Shelly     H******        0 ,T"/&      ***.***.***
        206 William    G****          0 lii4rw>N   ***.***.***
        
CREATE TABLE HR.RDTEST1 AS SELECT * FROM HR.EMPLOYEES;

-- CLERK 롤
CREATE ROLE CLERK;
GRANT CLERK TO SCOTT;
GRANT SELECT ON HR.RDTEST1 TO SCOTT;


Redaction Policy 생성



BEGIN DBMS_REDACT.ADD_POLICY(
  OBJECT_SCHEMA => 'HR'
  OBJECT_NAME => 'RDTEST1'
  COLUMN_NAME => 'SALARY'
  POLICY_NAME => 'REDACT_RDTEST1'
  POLICY_DESCRIPTION => 'REDACT_RDTEST1 PII'
  FUNCTION_TYPE => DBMS_REDACT.FULL,
  EXPRESSION => 'SYS_CONTEXT(''SYS_SESSION_ROLES'',''CLERK'' ) = ''FALSE''');
END;
/

SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME, SALARY, EMAIL, PHONE_NUMBER
  FROM HR.RDTEST1
 WHERE EMPLOYEE_ID IN ( 205, 206 );
 
-- SALARY 적용
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY EMAIL     PHONE_NUMBER
----------- ---------- --------- ------ --------- ------------
        205 Shelly     Higgins        0 SHIGGINS  515.123.8080
        206 William    Gletz          0 WGIETZ    515.123.8181

BEGIN DBMS_REDACT.ALTER_POLICY(
  OBJECT_SCHEMA => 'HR',
  OBJECT_NAME => 'RDTEST1',
  COLUMN_NAME => 'LAST_NAME',
  POLICY_NAME => 'REDACT_RDTEST1',
  POLICY_DESCRIPTION => 'REDACT_RDTEST1 PII',
  ACTION => DBMS_REDACT.ADD_COLUMN, -- 추가
  FUNCTION_TYPE => DBMS_REDACT.PARTIAL, 
  FUNCTION_PARAMETERS => 'VVVVVVVVVVVVVVVVVV,VVVVVVVVVVVVVVVVVV,*,2,25',
  EXPRESSION => 'SYS_CONTEXT(''SYS_SESSION_ROLES'',''CLERK'' ) = ''FALSE''');
END;
/

-- LAST_NAME 적용
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY EMAIL     PHONE_NUMBER
----------- ---------- --------- ------ --------- ------------
        205 Shelly     H******        0 SHIGGINS  515.123.8080
        206 William    G****          0 WGIETZ    515.123.8181

BEGIN DBMS_REDACT.ALTER_POLICY(
  OBJECT_SCHEMA => 'HR',
  OBJECT_NAME => 'RDTEST1',
  COLUMN_NAME => 'EMAIL',
  POLICY_NAME => 'REDACT_RDTEST1',
  POLICY_DESCRIPTION => 'REDACT_RDTEST1 PII',
  ACTION => DBMS_REDACT.ADD_COLUMN,
  FUNCTION_TYPE => DBMS_REDACT.PARTIAL, 
  FUNCTION_PARAMETERS => DBMS_REDACT.RANDOM, --
  EXPRESSION => 'SYS_CONTEXT(''SYS_SESSION_ROLES'',''CLERK'' ) = ''FALSE''');
END;
/

-- EMAIL 적용
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY EMAIL     PHONE_NUMBER
----------- ---------- --------- ------ --------- ------------
        205 Shelly     H******        0 30fjm2os  515.123.8080
        206 William    G****          0 aafaf3-dk 515.123.8181

BEGIN DBMS_REDACT.ALTER_POLICY(
  OBJECT_SCHEMA => 'HR',
  OBJECT_NAME => 'RDTEST1',
  COLUMN_NAME => 'PHONE_NUMBER',
  POLICY_NAME => 'REDACT_RDTEST1',
  POLICY_DESCRIPTION => 'REDACT_RDTEST1 PII',
  ACTION => DBMS_REDACT.ADD_COLUMN,
  FUNCTION_TYPE => DBMS_REDACT.REGEXP, 
  EXPRESSION => 'SYS_CONTEXT(''SYS_SESSION_ROLES'',''CLERK'' ) = ''FALSE''');
  REGEXP_PATTERN => ('(\d\d\d).(\d\d\d).(\d\d\d\d)',
  REGEXP_REPLACE_STRING => '***.***.****',
  REGEXP_POSITION => 1,
  REGEXP_OCCURRENCE => 0, REGEXP_MATCH_PARAMETER => 'i' );
END;
/

-- PHONE_NUMBER 적용
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY EMAIL     PHONE_NUMBER
----------- ---------- --------- ------ --------- ------------
        205 Shelly     H******        0 30fjm2os  ***.***.****
        206 William    G****          0 aafaf3-dk ***.***.****


Data Redaction과 뷰



-- Data Redaction 적용된 테이블 : HR.RDTEST1
CREATE OR REPLACE VIEW HR.V1
AS
SELECT EMPLOYEE_ID, FIRST_NAME, LAST_NAME,
       SALARY, EMAIL, PHONE_NUMBER
  FROM HR.RDTEST1;

BEGIN DBMS_REDACT.ALTER_POLICY(
  OBJECT_SCHEMA => 'HR',
  OBJECT_NAME => 'V1',
  COLUMN_NAME => 'PHONE_NUMBER',
  POLICY_NAME => 'NO_RD_PHONE_NUM',
  FUNCTION_TYPE => DBMS_REDACT.NONE, 
  EXPRESSION => '1=1');
END;
/

-- HR 유저로 다음 쿼리를 수행해서 Data Redaction이 취소된 것을 확인한다.
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY EMAIL     PHONE_NUMBER
----------- ---------- --------- ------ --------- ------------
        205 Shelly     H******        0 30fjm2os  515.123.8080
        206 William    G****          0 aafaf3-dk 515.123.8181




  • CTAS 로 Redaction된 컬럼을 가진 테이블을 복제한다면 Redaction 속성은 상속받지 않지만 편집된 데이터로 해당 컬럼 값이 생성된다. ( == insert select )

기타 향상된 보안 기능

  • 개인적으로 한번 읽어 보죠 ㅠㅠ