Oracle セキュリティ機能

こんにちは。YDC のろっきーです。
今回は Oracle 12c から追加されたセキュリティ機能についてご紹介します。
Oracle Database には、以下のようなセキュリティ機能が実装されています。

◇Oracle Database セキュリティ機能
機能名 概要
暗号化マスキング
Oracle Advanced Security(※1) 透過的データ暗号化(TDE)とOracle Data Redactionで
構成される。
Oracle Data Redaction(※1) 格納データに手を加えず、リアルタイムにデータを
マスキングできる。
Oracle Data Masking Pack(※1) 本番データを不可逆な形式でテスト用にマスキング
できる。
アクセス制御
Oracle Database Vault(※1) 管理者ユーザを含むアクセス制御により、職務分掌を
実現できる。
監査
必須監査/DBA監査/標準監査/ファイングレイン監査(※2) Oracle Databaseの標準機能。4種類あり、それぞれ
監査対象や監査ログの出力場所が異なる。
12cからは従来型監査と呼ばれている。
統合監査(Unified Auditing) ポリシーベースのアーキテクチャを採用し、監査ログを
一元化。
Data PumpやRecovery Manager(RMAN)の操作も
対象にできる。
Oracle Audit Vault and Database Firewall(※3) SQLのモニタリングとブロッキングを行うソフトウェア・
アプライアンス。
SQLインジェクションによる情報漏えいを防げる。

※1 Oracle Database Enterprise Edition有償オプションです。
※2 ファイングレイン監査はOracle Database Enterprise Edition有償オプションです。
※3 Oracle Database Enterprise Edition有償ライセンスです。

今回は Oracle 12c からの新機能である「Oracle Data Redaction」について、どんな機能かみていきましょう。

Oracle Data Redaction

Oracle Data Redacitonは、格納されているデータやアプリケーションに一切変更を加えず、 リアルタイムにデータをマスキング(リダクション)できる機能です。
例えば、アプリケーションやユーザが持つ権限に応じて、SELECT結果に含まれるクレジット カード番号などの機密列をその場で別の文字に置換することができます。
似たような製品としてOracle Data Masking Packがありますが、使用用途は大きく異なります。
Oracle Data Masking Packは格納データを実際にマスキングして本番に近いテスト・データを 生成することを目的とした機能であり、Oracle Data RedactionはSELECT文で取り出したデータ をその場でマスキングして表示させる機能です。
マニュアル等の公式文書では、Oracle Data Masking Packを使用する場合は「マスキング」、 Oracle Data Redactionを使用する場合は「リダクション」と呼び方を分けています。

▽Oracle Data Masking PackとOracle Data Redactionとの違い
実装方法 機能の目的 データへの影響
Oracle Data Masking Pack
Oracle Enterprise Manager テスト・データの生成 格納データを永続的に変更
Oracle Data Redaction
・DBMS Redact パッケージ
・Oracle Enterprise Manager
アクセス制御 格納データを変更しない

Oracle Data Redactionにおけるリダクションのパターンは全部で4種類あります。

▽リダクションの種類
リダクションの種類 特徴
FULL
(フル・リダクション)
データ型に応じて任意の値を返す。
デフォルトでは以下の値を返す。
・文字列型→シングル・スペース(空白)
・数値型→ゼロ(0)
・日付型→01-JAN-01
・LOB型→[ redacted ]
RANDOM
(ランダム・リダクション)
データ型に応じてランダムに値を返す。
・文字列型→ランダム文字
・数値型→ランダム数値
・日付型→ランダム日付
・LOB型→使用不可
PARTIAL
(部分リダクション)
データ型に応じて部分的に任意の値を返す。
・文字列型→部分的に任意の文字列
・数値型→部分的に任意の数値
・日付型→部分的に任意の日付
・LOB型→使用不可
REGEX
(正規表現リダクション)
正規表現を使用して任意の値を返す。

リダクションを試してみよう

今回は以下の環境で検証を行います。

環境
OS Oracle Database ORACLE_HOME ORACLE_SID
Red Hat Enterprise Linux 7.3 Oracle Database 12c Release 2 /u01/app/oracle/product/12.2.0/dbhome_1 orcl

事前準備

検証を行うための準備を行います。

1.HOGEユーザを作成します。

$ sqlplus / as sysdba
SQL>create user hoge identified by hoge;
ユーザーが作成されました。

2.HOGEユーザに権限を付与します。
→リダクション・ポリシーを作成するには、DBMS_REDACTパッケージに対するEXECUTE権限が必要となります。

SQL>grant connect,resource to hoge;
権限付与が成功しました。
SQL>grant execute on sys.dbms_redact to hoge;
権限付与が成功しました。
SQL>alter user hoge quota unlimited on USERS;
ユーザーが変更されました。

3.HOGEユーザにテスト用の表(card_details)を作成します。

SQL>CREATE TABLE card_details(
2 id NUMBER NOT NULL,
3 customer_id NUMBER NOT NULL,
4 card_no NUMBER NOT NULL,
5 card_string NUMBER NOT NULL,
6 expiry_date DATE NOT NULL,
7 sec_code NUMBER NOT NULL,
8 valid_date DATE NOT NULL,
9 CONSTRAINT payment_details_pk PRIMARY KEY (id)
10 );
表が作成されました。

4.HOGEユーザにテスト用の表(card_details)にデータを挿入します。

SQL>INSERT INTO card_details VALUES (1,3000,1234431212344312,'1234-4312-1234-4312',TRUNC(ADD_MONTHE(SYSDATE,12)),123,NULL);(
1行が作成されました。
SQL>INSERT INTO card_details VALUES (1,3001,2345543223455423,'2345-5432-2345-5432',TRUNC(ADD_MONTHE(SYSDATE,12)),234,NULL);(
1行が作成されました。
SQL>INSERT INTO card_details VALUES (1,3002,3456654334566543,'3456-6543-3456-6543',TRUNC(ADD_MONTHE(SYSDATE,12)),345,NULL);(
1行が作成されました。
SQL>INSERT INTO card_details VALUES (1,3003,4567765445677654,'4567-7654-4567-7654',TRUNC(ADD_MONTHE(SYSDATE,12)),456,NULL);(
1行が作成されました。
SQL>INSERT INTO card_details VALUES (1,3004,5678876556788765,'5678-8765-5678-8765',TRUNC(ADD_MONTHE(SYSDATE,12)),567,NULL);(
1行が作成されました。
SQL>commit;
コミットが完了しました。

5.HOGEユーザのテスト用の表(card_details)を確認します。

SQL>select * from card_details order by id;
ID CUSTOMER_ID CARD_NO CARD_STRING EXPIRY_DAT SEC_CODE VALID_DATE
----------- ------------ ---------------- ------------------- ----------- -------- -------------
1 3000 1234431212344312 1234-4312-1234-4312 2019-07-20 123
2 3001 2345543223455423 2345-5432-2345-5432 2019-07-20 234
3 3002 3456654334566543 3456-6543-3456-6543 2019-07-20 345
4 3003 4567765445677654 4567-7654-4567-7654 2019-07-20 456
5 3004 5678876556788765 5678-8765-5678-8765 2019-07-20 567

これで事前準備も完了したので、実際にDBMS REDACTパッケージを使用してリダクションを試してみましょう。

【検証1.FULL Redaction(完全リダクション)】

1.card_no列を型ごとにきめられているデフォルト値(※)に置き換えるポリシーを作成します。
※card_no列は数値型なので、データ・リダクション・ポリシーを設定することでデフォルト値である[0(ゼロ)]に置き換わります。

SQL>BEGIN
2 DBMS_REDACT.ADD_POLICY(
3 object_schema => 'hoge',
4 object_name => 'card_details',
5 column_name => 'card_no',
6 policy_name => 'redact_card_info',
7 function_type => DBMS_REDACT.full,
8 expression => '1=1'
9 );
10 END;
11 /
PL/SQLプロシージャが正常に完了しました。

2.リダクション結果の確認を行います。
16桁の数字によるデータが登録されていたcard_no列については、全て登録データが[0]と表示されています。

SQL>select * from card_details order by id;
ID CUSTOMER_ID CARD_NO CARD_STRING EXPIRY_DAT SEC_CODE VALID_DATE
----------- ------------ ---------------- ------------------- ----------- -------- -------------
1 3000 0 1234-4312-1234-4312 2019-07-20 123
2 3001 0 2345-5432-2345-5432 2019-07-20 234
3 3002 0 3456-6543-3456-6543 2019-07-20 345
4 3003 0 4567-7654-4567-7654 2019-07-20 456
5 3004 0 5678-8765-5678-8765 2019-07-20 567

【検証2.Random Redaction(ランダムリダクション)】

1.card_string列をランダムな値に置き換えるポリシーを作成します。

SQL>BEGIN
2 DBMS_REDACT.ADD_POLICY(
3 object_schema => 'hoge',
4 object_name => 'card_details',
5 column_name => 'card_string',
6 policy_name => 'redact_cust_random',
7 function_type => DBMS_REDACT.RANDOM,
8 expression => '1=1'
9 );
10 END;
11 /
PL/SQLプロシージャが正常に完了しました。

2.リダクション結果の確認を行います。

SQL>select * from card_details order by id;
ID CUSTOMER_ID CARD_NO CARD_STRING EXPIRY_DAT SEC_CODE VALID_DATE
----------- ------------ ---------------- ------------------- ----------- -------- -------------
1 3000 1234431212344312 EMTm(|f~MV\u0%n'U^d 2019-07-20 123
2 3001 2345543223455423 TUX\bYk'\]'djas/def 2019-07-20 234
3 3002 3456654334566543 'Q&]SMhr/Y.e[UpZ7a6 2019-07-20 345
4 3003 4567765445677654 U&WYYQ"2]._aaY/:e6g 2019-07-20 456
5 3004 5678876556788765 I?ps/-h]QG{d5peY0!s 2019-07-20 567

検索する度にランダムな値に置き換えられます。

SQL>select * from card_details order by id;
ID CUSTOMER_ID CARD_NO CARD_STRING EXPIRY_DAT SEC_CODE VALID_DATE
----------- ------------ ---------------- ------------------- ----------- -------- -------------
1 3000 1234431212344312 XlX1q{ZQ't'9y$bYh|h 2019-07-20 123
2 3001 2345543223455423 =GP6=Qx(EOX>EY!0Mw' 2019-07-20 234
3 3002 3456654334566543 (fNe>/>m0nVmF7F68vR 2019-07-20 345
4 3003 4567765445677654 0R|G4|QS8Z)0'tY{@b3 2019-07-20 456
5 3004 5678876556788765 Y73r&=/2a?;zE7:iGCf 2019-07-20 567

3.card_no列もランダムな値に置き換えるよう、ポリシーの内容を追加します。

SQL>BEGIN
2 DBMS_REDACT.ALTER_POLICY(
3 object_schema => 'hoge',
4 object_name => 'card_details',
5 policy_name => 'redact_cust_random',
6 action => DBMS_REDACT.ADD_COLUMN,
7 column_name => 'card_no',
8 function_type => DBMS_REDACT.RANDOM,
9 expression => '1=1'
10 );
11 END;
12 /
PL/SQLプロシージャが正常に完了しました。

4.リダクション結果の確認を行います。

SQL>select * from card_details order by id;
ID CUSTOMER_ID CARD_NO CARD_STRING EXPIRY_DAT SEC_CODE VALID_DATE
----------- ------------ ---------------- ------------------- ----------- -------- -------------
1 3000 1357715814234 .8.:6M9L6@6B>UAT>H 2019-07-20 123
2 3001 869462696531888 J0'ki4EHewhsq1MPmq 2019-07-20 234
3 3002 3053211707019840 M@W2)IP-UH_:1QX5]P 2019-07-20 345
4 3003 3609472769952038 hpuOLS#tpx{WT}+|x! 2019-07-20 456
5 3004 1040808087830761 zWWAwWj_#_ImMrg+gg 2019-07-20 567

最初にポリシーを設定したcard_string列と、後からポリシーに追加したcard_no列が両方ともランダムな値に
置き換えられています。

【検証3.Partial Redaction(部分リダクション)】

<文字データ型を使用した部分リダクション>

1.card_string列の値の最後の4桁は表示したまま、その他を[*]に置き換えるポリシーを作成します。

SQL>BEGIN
2 DBMS_REDACT.ADD_POLICY(
3 object_schema => 'hoge',
4 object_name => 'card_details',
5 column_name => 'card_string',
6 policy_name => 'redact_card_info_var',
7 function_type => DBMS_REDACT.PARTIAL,
8 function_parameters => DBMS_REDACT.REDACT_CCN16_F12,
9 expression => '1=1'
10 );
11 END;
12 /
PL/SQLプロシージャが正常に完了しました。

2.リダクション結果の確認を行います。

SQL>select * from card_details order by id;
ID CUSTOMER_ID CARD_NO CARD_STRING EXPIRY_DAT SEC_CODE VALID_DATE
----------- ------------ ---------------- ------------------- ----------- -------- -------------
1 3000 1234431212344312 ****-****-****-4312 2019-07-20 123
2 3000 1234431212344312 ****-****-****-5432 2019-07-20 234
3 3000 1234431212344312 ****-****-****-6543 2019-07-20 345
4 3000 1234431212344312 ****-****-****-7654 2019-07-20 456
5 3000 1234431212344312 ****-****-****-8765 2019-07-20 567

card_string列の最後の4桁以外が[*]に置き換えられています。

<数値データ型を使用した部分リダクション>

1.card_no列の値の最初の5桁を[9]に置き換えるポリシーを作成します。

SQL>BEGIN
2 DBMS_REDACT.ADD_POLICY(
3 object_schema => 'hoge',
4 object_name => 'card_details',
5 column_name => 'card_no',
6 policy_name => 'redact_card_info_num',
7 function_type => DBMS_REDACT.PARTIAL,
8 function_parameters => '9,1,5',
9 expression => '1=1'
10 );
11 END;
12 /
PL/SQLプロシージャが正常に完了しました。

2.リダクション結果の確認を行います。

SQL>select * from card_details order by id;
ID CUSTOMER_ID CARD_NO CARD_STRING EXPIRY_DAT SEC_CODE VALID_DATE
----------- ------------ ---------------- ------------------- ----------- -------- -------------
1 3000 9999931212344312 1234-4312-1234-4312 2019-07-20 123
2 3001 9999943223455423 2345-5432-2345-5432 2019-07-20 234
3 3002 9999954334566543 3456-6543-3456-6543 2019-07-20 345
4 3003 9999965445677654 4567-7654-4567-7654 2019-07-20 456
5 3004 9999976556788765 5678-8765-5678-8765 2019-07-20 567

card_no列の最初の5桁が[9]に置き換えられています。

<日付データ型を使用した部分リダクション>

1.expiry_date列の西暦を[2099]に置き換えるポリシーを作成します。

SQL>BEGIN
2 DBMS_REDACT.ADD_POLICY(
3 object_schema => 'hoge',
4 object_name => 'card_details',
5 column_name => 'expiry_date',
6 policy_name => 'redact_card_info_date',
7 function_type => DBMS_REDACT.PARTIAL,
8 function_parameters => 'Mdy2099HMS',
9 expression => '1=1'
10 );
11 END;
12 /
PL/SQLプロシージャが正常に完了しました。

2.リダクション結果の確認を行います。

SQL>select * from card_details order by id;
ID CUSTOMER_ID CARD_NO CARD_STRING EXPIRY_DAT SEC_CODE VALID_DATE
----------- ------------ ---------------- ------------------- ----------- -------- -------------
1 3000 1234431212344312 1234-4312-1234-4312 2099-07-20 123
2 3001 2345543223455423 2345-5432-2345-5432 2099-07-20 234
3 3002 3456654334566543 3456-6543-3456-6543 2099-07-20 345
4 3003 4567765445677654 4567-7654-4567-7654 2099-07-20 456
5 3004 5678876556788765 5678-8765-5678-8765 2099-07-20 567

expiry_date列の西暦が[2099]に置き換えられています。

【検証4.Regular Expression-based Redaction(正規表現ベースリダクション)】

1.card_string列の末尾4桁以外は[#]に置き換えるポリシーを作成します。
その際、正規表現でマスキングパターンを指定し、指定されたパターンに一致した情報が置き換えられます。

SQL>BEGIN
2 DBMS_REDACT.ADD_POLICY(
3 object_schema => 'hoge',
4 object_name => 'card_details',
5 column_name => 'card_string',
6 policy_name => 'redact_cust',
7 expression => '1=1',
8 function_type => DBMS_REDACT.REGEXP,
9 regexp_pattern => '(\d\d\d\d)-(\d\d\d\d)-(\d\d\d\d)-(\d\d\d\d)',
10 regexp_replace_string => '####-####-####-\4',
11 regexp_position => 1,
12 regexp_occurrence => DBMS_REDACT.RE_ALL/
13 );
141 END;
15 /
PL/SQLプロシージャが正常に完了しました。

2.リダクション結果の確認を行います。

SQL>select * from card_details order by id;
ID CUSTOMER_ID CARD_NO CARD_STRING EXPIRY_DAT SEC_CODE VALID_DATE
----------- ------------ ---------------- ------------------- ----------- -------- -------------
1 3000 1234431212344312 ####-####-####-4312 2019-07-20 123
2 3000 1234431212344312 ####-####-####-5432 2019-07-20 234
3 3000 1234431212344312 ####-####-####-6543 2019-07-20 345
4 3000 1234431212344312 ####-####-####-7654 2019-07-20 456
5 3000 1234431212344312 ####-####-####-8765 2019-07-20 567

card_string列の末尾4桁以外は[#]に置き換えられています。

以上で、Oracle Data Redactionの基本的な使用方法について一通り確認ができました。

まとめ

Oracle Data Redactionを使用することで、アプリケーションに変更を加えることなく、また、 実データに影響を与えることなく、権限のないユーザやアプリケーションの開発者が機密 データを参照することを防ぐことができます。
Oracle Data RedactionはEnterprise Editionライセンスのオプション機能となりますが、 もし機会があればご使用を検討ください。

Standby Expressに関するお問合わせ

  • TEL 042-333-6217
  • FAX 042-352-6101
  • LINE
  • Mail