Gestion de bases de données

Faire fonctionner correctement l’expiration du mot de passe SYS dans Oracle et pourquoi vous devriez vraiment le renouveler

Introduction

Récemment, nous avons planifié dans l’un de nos environnements Oracle un rapport listant tous les comptes dont le mot de passe allait bientôt expirer. Après la première exécution, nous avons fait ce que tout le monde devrait faire : nous avons commencé à mettre à jour les mots de passe d’administration, y compris celui de SYS dans la base de données, dans OEM et dans les Oracle Wallets.

C’est alors qu’une anomalie est apparue.

Pour tous les utilisateurs sauf SYS, la date d’expiration du mot de passe a été repoussée comme prévu. Pour SYS, la valeur PASSWORD_EXPIRE restait bloquée sur l’ancienne date, alors que nous avions bel et bien changé le mot de passe.

Après quelques recherches, nous avons constaté qu’il ne s’agissait pas du tout d’un nouveau bogue : il existe depuis des années et se trouve discrètement dans de nombreux environnements. Il passe simplement inaperçu parce que le mot de passe SYS n’est souvent jamais changé (alors qu’il devrait absolument l’être, vu les privilèges en jeu).

Cet article aborde :

  • Pourquoi le renouvellement du mot de passe SYS est important (surtout dans les environnements Multitenant)
  • Les bonnes pratiques pour gérer les identifiants SYS en toute sécurité
  • Comment corriger le problème qui empêche la date d’expiration de SYS de se mettre à jour lorsque son mot de passe est changé
  • Des recommandations concrètes à appliquer dans l’ensemble de vos environnements

1. Pourquoi le renouvellement du mot de passe SYS est souvent négligé (et pourquoi c’est dangereux)

Avant l’arrivée de Multitenant (non-CDB), la pratique courante pour l’administration locale ressemblait à ceci :

sqlplus / as sysdba

L’authentification par le système d’exploitation simplifiait les choses : aucun mot de passe dans les scripts, aucune connexion applicative en tant que SYS et aucune pression immédiate pour renouveler le mot de passe SYS.

Avec l’arrivée d’Oracle Multitenant, ce modèle a changé :

  • Les connexions SYS se font souvent directement dans chaque PDB.
  • L’authentification par l’OS ne s’applique pas toujours de la même façon au niveau des PDB.
  • Le préfixe OP$, qui permettait l’authentification par l’OS seulement, a été déprécié.
  • De plus en plus de scripts, d’outils et de composants de surveillance finissent par exiger de vrais identifiants SYS, et non simplement "/ as sysdba".

Le résultat?
SYS se comporte de plus en plus comme un compte d’administration “normal” dont le mot de passe est stocké à divers endroits (p. ex. wallets, OEM, scripts d’automatisation), ce qui représente un réel risque de sécurité si ce mot de passe ne change jamais.

Puisque SYS contrôle tout, un mot de passe compromis signifie pratiquement la partie perdue pour cette base de données.

2. Bonnes pratiques de gestion des identifiants SYS

Avant d’aborder le bogue et sa correction, il est utile de rappeler quelques bonnes pratiques de base concernant SYS.

2.1 Utiliser les Oracle Wallets plutôt que des mots de passe codés en dur

Si des scripts ou des tâches d’automatisation ont besoin des identifiants SYS (ou de tout autre compte à privilèges élevés) :

  • Ne codez jamais de mots de passe en dur dans les scripts shell ou les fichiers de configuration.
  • Utilisez Oracle Wallet (p. ex. orapki) pour stocker les identifiants en toute sécurité.
  • Configurez les scripts pour qu’ils se connectent au moyen d’alias de wallet plutôt que de mots de passe en clair.

Vous limitez ainsi les dégâts si quelqu’un accède au système de fichiers, et vous facilitez le renouvellement des mots de passe : changez le mot de passe, mettez à jour le wallet, et les scripts continuent de fonctionner.

2.2 Surveiller l’expiration des mots de passe de façon proactive

Il est recommandé de disposer :

  • d’un rapport planifié ou
  • d’une requête d’alerte

qui liste les comptes dont le mot de passe arrive bientôt à expiration, en particulier les comptes d’administration comme SYS, SYSTEM et les propriétaires d’applications.

Vous évitez ainsi :

  • Les pannes imprévues dues à des mots de passe expirés
  • Les interruptions de l’automatisation, de la surveillance, des sauvegardes ou des processus Data Guard
  • Les changements d’urgence de dernière minute, sous pression

Votre compte SYS devrait suivre le même cycle de renouvellement que les autres utilisateurs d’administration, et non être traité comme une exception “qui n’expire jamais”.

2.3 Data Guard : utiliser un REDO_TRANSPORT_USER dédié

Dans les environnements Data Guard, des renouvellements fréquents du mot de passe peuvent perturber le transport des redo si vous comptez sur SYS pour transférer les archives et les journaux entre la base primaire et la base de secours.

Pour dissocier SYS du transport des redo :

  • Créez un utilisateur dédié, p. ex. REDO_TRANSPORT_USER.
  • Accordez-lui uniquement les privilèges nécessaires au transport des redo.
  • Configurez Data Guard pour qu’il utilise ce compte plutôt que SYS.

Avantages :

  • Vous pouvez renouveler le mot de passe SYS de façon indépendante sans interrompre l’envoi des redo.
  • Vous réduisez la portée des changements d’identifiants.
  • Il est plus facile de vous conformer aux politiques de sécurité et aux audits.

3. Le problème : la date d’expiration du mot de passe SYS ne se met pas à jour

Même avec de bonnes politiques de mots de passe en place (p. ex. un profil avec un PASSWORD_LIFE_TIME non illimité), vous pourriez observer ce comportement :

  • Vous attribuez à SYS un profil avec des règles d’expiration.
  • La date d’expiration du mot de passe est d’abord définie correctement.
  • Lorsque vous changez ensuite le mot de passe SYS, la colonne PASSWORD_EXPIRE de CDB_USERS ne se met pas à jour — elle conserve l’ancienne date.

Ce problème est causé par un bogue interne lié à la façon dont Oracle met à jour les métadonnées de SYS dans USER$. Ce comportement dépend d’un paramètre interne (underscore) et d’un correctif précis.

Voyons comment le repérer et le corriger.

4. Étape par étape : corriger la date d’expiration du mot de passe SYS qui ne se met pas à jour

S’applique à : Oracle 12.1, 12.2, 18c, 19c (le bogue a d’abord été corrigé par le correctif 28538439 pour 12.1.0.2.180717).

RENAPS - Comment régler le problème…

Étape 1 – Vérifier les dates de changement et d’expiration du mot de passe SYS

Commencez par confirmer l’état actuel de SYS dans le conteneur racine (CDB$ROOT) :

set lines 220

col CONTAINER_NAME for a12

col PROFILE for a22

SELECT u.con_id,

       c.name AS container_name,

       u.username,

       u.common,

       u.account_status,

       u.profile,

       TO_CHAR(u.password_change_date, 'DD-MON-RRRR HH24:MI:SS') AS password_change_date,

       TO_CHAR(u.expiry_date,           'DD-MON-RRRR HH24:MI:SS') AS password_expire

FROM   cdb_users     u

JOIN   v$containers  c

       ON u.con_id = c.con_id

WHERE  u.con_id   = 1         -- CDB$ROOT only; remove this to see all containers

AND    u.username = 'SYS';

Exemple de résultat lorsqu’aucune expiration basée sur un profil n’est appliquée :

CON_ID CONTAINER_NA USERNAME COM ACCOUNT_STATUS PROFILE PASSWORD_CHANGE_DATE PASSWORD_EXPIRE

------- ------------ -------- --- -------------- ------- -------------------- --------------

      1 CDB$ROOT     SYS      YES OPEN           DEFAULT 27-FEB-2023 13:33:08

Ici, SYS utilise le profil DEFAULT, qui n’impose pas forcément de PASSWORD_LIFE_TIME; aucune date d’expiration n’est donc encore affichée.

Étape 2 – Attribuer un profil qui impose l’expiration du mot de passe

Attribuez à SYS un profil conçu spécialement pour lui, avec une durée de vie du mot de passe et des règles de sécurité appropriées :

ALTER USER sys PROFILE C##PROFILE_SYS;

Vérifiez de nouveau :

SELECT u.con_id,

       c.name AS container_name,

       u.username,

       u.common,

       u.account_status,

       u.profile,

       TO_CHAR(u.password_change_date, 'DD-MON-RRRR HH24:MI:SS') AS password_change_date,

       TO_CHAR(u.expiry_date,           'DD-MON-RRRR HH24:MI:SS') AS password_expire

FROM   cdb_users     u

JOIN   v$containers  c

       ON u.con_id = c.con_id

WHERE  u.con_id   = 1         -- CDB$ROOT only; remove this to see all containers

AND    u.username = 'SYS';

Vous devriez maintenant voir quelque chose comme :

 CON_ID CONTAINER_NA USERNAME COM ACCOUNT_STATUS PROFILE        PASSWORD_CHANGE_DATE PASSWORD_EXPIRE

------- ------------ -------- --- -------------- -------------- -------------------- --------------------

      1 CDB$ROOT     SYS      YES OPEN           C##PROFILE_SYS 27-FEB-2023 13:33:08 26-AUG-2023 13:33:08

Jusqu’ici, tout va bien : le profil est appliqué et la date d’expiration est calculée. 26-AUG-2023 13:33:08

Étape 3 – Changer le mot de passe SYS et observer le bogue

Changez maintenant le mot de passe SYS :

ALTER USER sys IDENTIFIED BY ExpirationDateNOTUpdated;

Relancez la requête :

SELECT u.con_id,

       c.name AS container_name,

       u.username,

       u.common,

       u.account_status,

       u.profile,

       TO_CHAR(u.password_change_date, 'DD-MON-RRRR HH24:MI:SS') AS password_change_date,

       TO_CHAR(u.expiry_date,           'DD-MON-RRRR HH24:MI:SS') AS password_expire

FROM   cdb_users     u

JOIN   v$containers  c

       ON u.con_id = c.con_id

WHERE  u.con_id   = 1         -- CDB$ROOT only; remove this to see all containers

AND    u.username = 'SYS';

Si vous êtes touché par le bogue, vous verrez :

 CON_ID CONTAINER_NA USERNAME COM ACCOUNT_STATUS PROFILE        PASSWORD_CHANGE_DATE PASSWORD_EXPIRE

------- ------------ -------- --- -------------- -------------- -------------------- --------------------

      1 CDB$ROOT     SYS      YES OPEN           C##PROFILE_SYS 27-FEB-2023 13:33:08 26-AUG-2023 13:33:08
  • PASSWORD_CHANGE_DATE et PASSWORD_EXPIRE n’ont pas avancé comme elles l’auraient dû. La valeur affichée est toujours 26-AUG-2023 13:33:08

C’est là le cœur du problème.

Étape 4 – Vérifier le correctif et le paramètre interne

Vérifiez d’abord que le correctif du bogue 28538439 est présent :

$ opatch lsinventory | grep 28538439

Si le correctif est absent, vous devrez passer par votre soutien Oracle ou votre processus de gestion des correctifs pour l’appliquer au home concerné.

Vérifiez ensuite le paramètre interne qui contrôle la mise à jour des métadonnées du mot de passe SYS :

col VALUE for a22

SELECT x.ksppinm  AS name,

       y.ksppstvl AS value

FROM   sys.x$ksppi x,

       sys.x$ksppcv y

WHERE  x.indx = y.indx

AND    x.ksppinm LIKE '%_enable_ptime%';

Exemple de résultat avant la correction :

NAME                            VALUE

------------------------------- --------------------------------

_enable_ptime_update_for_sys    FALSE

Si la valeur est FALSE, la base de données ne met pas à jour le PTIME interne de SYS lors d’un changement de mot de passe.

Étape 5 – Activer la mise à jour des métadonnées du mot de passe SYS

Avertissement : il s’agit d’un paramètre underscore (interne). Suivez toujours votre processus de gestion des changements, testez d’abord hors production et respectez les recommandations du soutien Oracle ainsi que vos normes de gestion des correctifs.

Activez le paramètre dans le SPFILE et redémarrez l’instance :

ALTER SYSTEM SET "_enable_ptime_update_for_sys" = TRUE SCOPE=SPFILE;

Redémarrez la base de données, puis confirmez la valeur :

col VALUE for a22

SELECT x.ksppinm  AS name,

       y.ksppstvl AS value

FROM   sys.x$ksppi x,

       sys.x$ksppcv y

WHERE  x.indx = y.indx

AND    x.ksppinm LIKE '%_enable_ptime%';

Vous devriez maintenant voir :

NAME                            VALUE

------------------------------- ----------------------

_enable_ptime_update_for_sys    TRUE

Étape 6 – Changer de nouveau le mot de passe SYS et valider

Changez maintenant le mot de passe SYS une fois de plus :

ALTER USER sys IDENTIFIED BY ExpirationDateUpdated;

Relancez la requête de vérification :

SELECT u.con_id,

       c.name AS container_name,

       u.username,

       u.common,

       u.account_status,

       u.profile,

       TO_CHAR(u.password_change_date, 'DD-MON-RRRR HH24:MI:SS') AS password_change_date,

       TO_CHAR(u.expiry_date,           'DD-MON-RRRR HH24:MI:SS') AS password_expire

FROM   cdb_users     u

JOIN   v$containers  c

       ON u.con_id = c.con_id

WHERE  u.con_id   = 1         -- CDB$ROOT only; remove this to see all containers

AND    u.username = 'SYS';

Résultat attendu après la correction :

CON_ID CONTAINER_NA USERNAME COM ACCOUNT_STATUS PROFILE        PASSWORD_CHANGE_DATE PASSWORD_EXPIRE

------- ------------ -------- --- -------------- -------------- -------------------- --------------------

      1 CDB$ROOT     SYS      YES OPEN           C##PROFILE_SYS 17-DEC-2025 00:25:28 15-JUN-2026 00:25:28

PASSWORD_CHANGE_DATE (17-DEC-2025 00:25:28) et PASSWORD_EXPIRE (15-JUN-2026 00:25:28) reflètent maintenant correctement le dernier changement de mot de passe et la politique d’expiration du profil.

5. Impact et versions

  • Le bogue 28538439 – “PTIME FOR SYS NOT GETTING UPDATED AFTER APPLYING JULY PSU (Patch)” touche :
  • 12.1
  • 12.2
  • 18c
  • 19c
  • La première correction de ce bogue a été publiée dans le correctif 12.1.0.2.180717; des correctifs équivalents ou rétroportés existent pour les versions ultérieures.

Si vous utilisez l’une de ces versions et que la date d’expiration de SYS ne bouge pas lorsque vous changez le mot de passe, vous êtes très probablement touché par ce problème et devriez :

  1. Vous assurer que le correctif pertinent est appliqué.
  2. Activer _enable_ptime_update_for_sys = TRUE dans le SPFILE et redémarrer la base de données.
  3. Tester de nouveau les changements de mot de passe.

6. Liste de vérification et recommandations pratiques

Pour conclure, voici une liste de vérification pratique à utiliser dans votre environnement :

6.1 Sécurité et gouvernance

  • Intégrez SYS à votre politique standard de renouvellement des mots de passe.
  • Stockez les identifiants SYS dans des Oracle Wallets, et non dans des scripts.
  • Maintenez des rapports ou des alertes réguliers sur les comptes dont l’expiration approche, y compris SYS, SYSTEM et les principaux propriétaires d’applications.
  • Documentez chaque changement de mot de passe pour en assurer la traçabilité (qui, quand, où, pourquoi).

6.2 Data Guard et haute disponibilité

  • Utilisez un REDO_TRANSPORT_USER dédié plutôt que SYS pour le transport des redo.
  • Testez les changements de mot de passe SYS dans les environnements Data Guard pour vous assurer qu’ils n’ont aucun effet sur l’envoi des journaux.

6.3 Correction du bogue et configuration technique

  • Vérifiez si le correctif 28538439 (ou son équivalent) est appliqué.
  • Vérifiez _enable_ptime_update_for_sys — réglez-le à TRUE (SPFILE) et redémarrez selon votre processus de gestion des changements.
  • Confirmez que PASSWORD_CHANGE_DATE et PASSWORD_EXPIRE se mettent correctement à jour pour SYS après le prochain renouvellement.

7. Pour conclure

Le but de cet article n’est pas seulement de corriger un bogue Oracle étrange, mais aussi de vous encourager à traiter SYS comme tout autre compte à privilèges élevés :

  • Renouvelez son mot de passe selon un calendrier défini.
  • Protégez ses identifiants au moyen de wallets et de bonnes pratiques d’exploitation.
  • Surveillez l’expiration de son mot de passe et produisez des rapports à ce sujet, plutôt que de partir du principe que “SYS est un cas à part.”

Une fois le correctif appliqué et le paramètre bien réglé, Oracle garde enfin les métadonnées synchronisées, et vous savez avec fiabilité quand les identifiants SYS changent réellement — une étape importante vers une sécurité solide et vérifiable de vos bases de données.