Numéro de carte, RIB, CIN : vos données sensibles sont-elles vraiment protégées côté SELECT ?

Il y a des colonnes qu’on ne veut pas montrer à tout le monde, même quand l’accès à la table est légitime : un numéro de carte, un montant, une donnée sensible. Le chiffrement ne règle pas ce problème, puisqu’un simple SELECT déchiffre tout. Ce qu’il faut, c’est un mécanisme capable de décider, au moment de la lecture, qui a le droit de voir quoi. C’est le rôle de Data Redaction, une fonctionnalité qui existe depuis longtemps mais qui restait assez limitée sur 19c dès qu’on sortait d’un SELECT basique. Sur 23ai/26ai, ces limitations disparaissent, ce qui rend la fonctionnalité beaucoup plus utilisable en pratique. On va voir ça avec un exemple concret, puis regarder précisément ce qui a changé entre les deux versions.

Le principe

DBMS_REDACT masque le contenu d’une colonne à la volée, pendant l’exécution de la requête. Rien n’est modifié sur disque, la vraie donnée reste intacte dans ses blocs. Seul ce qui s’affiche à l’écran change, selon une règle qu’on définit soi-même.
On confond parfois Redaction avec d’autres mécanismes Oracle (TDE chiffre le stockage, VPD filtre les lignes qu’on voit, Data Masking remplace vraiment la donnée, typiquement pour peupler un environnement de test). DATA Redaction ne touche ni au stockage ni aux lignes, seulement à l’affichage d’une colonne, et elle cohabite bien avec VPD sur une même base.
Un point à garder en tête : Redaction fait partie de l’Advanced Security Option, une option payante, sauf sur Autonomous Database où elle est incluse. À vérifier avant d’activer quoi que ce soit.

Le mot de passe d’un compte technique qui fuite

Un scénario classique en prod, et c’est là que Redaction devient utile. Une table de paiements stocke les numéros de carte bancaire des clients. Elle est utilisée par une application, un service client par exemple, qui consulte l’historique d’achat pour traiter les réclamations. Cette application se connecte avec un compte technique, APP_SUPPORT , qui a un accès en lecture sur la table.
Le risque n’est pas vraiment dans l’application elle-même : elle ne demande jamais le numéro complet, donc en usage normal personne ne le voit. Le problème, c’est que si ce mot de passe fuite un jour, n’importe qui peut se connecter avec ce compte via un simple outil SQL et faire un SELECT * bien plus large que ce que l’application aurait jamais demandé.

Prenons un exemple:

create table paiements (
id number generated always as identity,
client varchar2(50),
num_carte varchar2(19),
montant number
);
insert into paiements (client, num_carte, montant) values ('Leroy Paul', '4539123456781234', 89.90);
insert into paiements (client, num_carte, montant) values ('Girard Marie', '5412345678901234', 154.50);
insert into paiements (client, num_carte, montant) values ('Michel Julien', '4916123456789012', 42.00);
insert into paiements (client, num_carte, montant) values ('Fournier Claire', '4024007123456789', 210.75);
commit;Langage du code : JavaScript (javascript)

Sans policy, une connexion directe avec les identifiants APP_SUPPORT remonte tout :

SQL> select client, num_carte, montant from paiements;

CLIENT            NUM_CARTE           MONTANT
----------------- ------------------- ----------
Leroy Paul        4539123456781234         89.9
Girard Marie      5412345678901234        154.5
Michel Julien     4916123456789012           42
Fournier Claire   4024007123456789       210.75

4 rows selected.Langage du code : CSS (css)

On pose une policy sur ce compte, en PARTIAL pour ne masquer qu’une partie du numéro et garder le dernier
chiffre, suffisant pour le support client, sans exposer le numéro complet :

begin
dbms_redact.add_policy(
object_schema => 'admin',
object_name => 'paiements',
column_name => 'num_carte',
policy_name => 'redact_num_carte',
function_type => dbms_redact.partial,
function_parameters => DBMS_REDACT. REDACT_CCN16_F12,
expression => 'SYS_CONTEXT(''USERENV'', ''SESSION_USER'') = ''APP_SUPPORT'''
);
end;
/Langage du code : PHP (php)

function_parameters indique à Oracle quel masque appliquer quand on choisit PARTIAL .REDACT_CCN16_F12 est une constante prédéfinie pour un numéro de carte à 16 chiffres : elle masque les premiers caractères et garde le dernier visible, au format ****-****-****-9 . Il en existe d’autres pour des formats courants, numéro de sécurité sociale, email, date de naissance, et rien n’empêche de construire son propre masque si aucune ne convient.

Même requête, même compte, désormais protégé (que la connexion vienne de l’application ou d’un mot de passe
compromis) :

SQL> select client, num_carte, montant from paiements;

CLIENT            NUM_CARTE           MONTANT
----------------- ------------------- ----------
Leroy Paul        ****-****-****-4          89.9
Girard Marie      ****-****-****-4         154.5
Michel Julien     ****-****-****-2            42
Fournier Claire   ****-****-****-9        210.75

4 rows selected.Langage du code : CSS (css)

La policy est posée sur le compte, au niveau base de données , pas sur le code applicatif. Peu importe le canal utilisé pour se connecter avec ce compte, la colonne reste masquée. Un compte du service comptabilité, lui, continue de voir le numéro complet, puisque la policy ne le concerne pas.

19c vs 23ai/26ai : le même DISTINCT, deux résultats différents

Prenons une seule requête et regardons ce qu’elle donne sur les deux versions. Toujours connecté avec APP_SUPPORT , on veut simplement savoir combien de numéros de carte distincts sont enregistrés, pour vérifier s’il y a des doublons :

select distinct num_carte
from paiements
order by num_carte;Langage du code : JavaScript (javascript)

Sur 19c, elle ne s’exécute pas :

ORA-01791: not a SELECTed expressionLangage du code : HTTP (http)

Oracle refuse dès qu’un DISTINCT ou un ORDER BY porte sur une colonne redigée. Impossible de faire tourner ce genre de contrôle, même basique, tant que la policy est active. Sur 23ai/26ai, la même requête tourne :

SQL> select distinct num_carte
  2  from admin.paiements
  3  order by 1;

NUM_CARTE
-------------------
****-****-****-9
****-****-****-4
****-****-****-2
****-****-****-4

4 rows selected.Langage du code : JavaScript (javascript)

Le vrai apport de 23ai/26ai n’est pas une fonctionnalité spectaculaire, c’est la fin d’un blocage qui empêchait beaucoup d’équipes d’utiliser Redaction sereinement sur une base existante. Si une policy sur des colonnes sensibles est envisagée sous 19c, mieux vaut tester soigneusement les vues et rapports existants avant de l’activer. Et si une migration vers 23ai/26ai est déjà dans les cartons, c’est un argument de plus en sa faveur.

Soyez le premier à commenter

Poster un Commentaire

Votre adresse de messagerie ne sera pas publiée.


*