Wednesday 11 July 2012

Cryptage de mot de passe (Storing Passwords in an Oracle Database)




Sauvgarde de mot de passe dans une base de donnée Oracle



Quand on parle de gestion de la sécurité des applications,il y'a souvent un besoin de stocker des mots de passe

dans une table de base de données. Ceci peut en soi mener aux questions de sécurité, puisque des utilisateurs

avec des privilèges appropriés peuvent lire le contenu des ces tables . Une approche de sécurité consiste en

le cryptage des mots de passe avant leurs stockages,mais un mécanisme de décryptage pourrait vous exposer a une

faille de sécurité. Une alternative plus sûr est de stocker le hash code du nom utilisateur et de son mot de passe

comme mot passe de sécurité.Dans cette article, je vous montre un processus utilisant le package DBMS_OBFUSCATION_TOOLKIT


qui est disponible sur Oracle9i ou bien en sha_1 avec Oracle 10


Premiérement on va crée une table pour sauvgarder le nom utilisateur et sont mot de passe.


Example


 


> SQLPLUS scott/tiger 


Oracle Database 10g Release 10.2.0.1.0 - Production

SQL>  SET LINESIZE 130
 SQL>  CREATE TABLE demo_users (
      id_user    NUMBER(12)    NOT NULL,
      username  VARCHAR2(128)  NOT NULL,
      password  VARCHAR2(128)  NOT NULL
    );
    
SQL> Table created.

SQL>ALTER TABLE demo_users ADD (
      CONSTRAINT id_users_pk PRIMARY KEY (id_user)
    );
    
SQL> Table altered.
	
SQL>ALTER TABLE demo_users ADD (
      CONSTRAINT users_name_uk UNIQUE (username)
    );
	
SQL> Table altered.
	
SQL>CREATE SEQUENCE demo_users_seq;

SQL> sequence created.



--Création du package pour la sécurisation des informations des utilisateur
SQL>  CREATE OR REPLACE PACKAGE demo_user_security AS

    FUNCTION GET_HASH   (p_username  IN  VARCHAR2,
                         p_password  IN  VARCHAR2)
        RETURN VARCHAR2;
        
    PROCEDURE add_user   (p_username  IN  VARCHAR2,
                          p_password  IN  VARCHAR2);

    PROCEDURE change_password   (p_username      IN  VARCHAR2,
                                 p_old_password  IN  VARCHAR2,
                                 p_new_password  IN  VARCHAR2);

    PROCEDURE valid_user   (p_username  IN  VARCHAR2,
                            p_password  IN  VARCHAR2);

    FUNCTION valid_user   (p_username  IN  VARCHAR2,
                           p_password  IN  VARCHAR2)
        RETURN BOOLEAN;

    END;
 
 SQL> package created.
  
SQL>CREATE OR REPLACE PACKAGE BODY demo_user_security AS

      FUNCTION GET_HASH (p_username  IN  VARCHAR2,
                         p_password  IN  VARCHAR2)
        RETURN VARCHAR2 AS
        v_secur VARCHAR2(30) := 'Test';
      BEGIN
        -- Pre Oracle 10g
        RETURN DBMS_OBFUSCATION_TOOLKIT.MD5(
          input_string => UPPER(p_username) || v_secur || UPPER(p_password));

        -- Oracle 10g+ : Require EXECUTE on DBMS_CRYPTO
        --RETURN DBMS_CRYPTO.HASH(UTL_RAW.CAST_TO_RAW(UPPER(p_username) 
		--|| v_secur || UPPER(p_password)),DBMS_CRYPTO.HASH_SH1);
      END;

      PROCEDURE add_user (p_username  IN  VARCHAR2,
                          p_password  IN  VARCHAR2) AS
      BEGIN
        INSERT INTO demo_users (
          id_user,
          username,
          password
        )
        VALUES (
          demo_users_seq.NEXTVAL,
          UPPER(p_username),
          GET_HASH(p_username, p_password)
        );
        
        COMMIT;
      END;
       
      PROCEDURE change_password (p_username      IN  VARCHAR2,
                                 p_old_password  IN  VARCHAR2,
                                 p_new_password  IN  VARCHAR2) AS
        v_rowid  ROWID;
      BEGIN
        SELECT rowid
        INTO   v_rowid
        FROM   demo_users
        WHERE  username = UPPER(p_username)
        AND    password = get_hash(p_username, p_old_password)
        FOR UPDATE;
        
        UPDATE demo_users
        SET    password = get_hash(p_username, p_new_password)
        WHERE  rowid    = v_rowid;
        
        COMMIT;
      EXCEPTION
        WHEN NO_DATA_FOUND THEN
          RAISE_APPLICATION_ERROR(-20010, 'nom utilisateur/mot de passe incorrect.');
      END;

      PROCEDURE valid_user (p_username  IN  VARCHAR2,
                            p_password  IN  VARCHAR2) AS
        v_numy  VARCHAR2(1);
      BEGIN
        SELECT '1'
        INTO   v_numy
        FROM   demo_users
        WHERE  username = UPPER(p_username)
        AND    password = get_hash(p_username, p_password);
      EXCEPTION
        WHEN NO_DATA_FOUND THEN
          RAISE_APPLICATION_ERROR(-20000, 'nom utilisateur/mot de passe incorrect.');
      END;
      
      FUNCTION valid_user (p_username  IN  VARCHAR2,
                           p_password  IN  VARCHAR2) 
        RETURN BOOLEAN AS
      BEGIN
        valid_user(p_username, p_password);
        RETURN TRUE;
      EXCEPTION
        WHEN OTHERS THEN
          RETURN FALSE;
      END;
      
    END;
    /
SQL> package body created.

 


La surcharge de VALID_USER permet un contrôle de sécurité de façon différente.La fonction de GET_HASH est

utilisée pour hacher la combinaison du nom d'utilisateur et du mot de passe. Il rend toujours un VARCHAR2

indépendamment de la longueur des paramètres de saisie.DBMS_OBFUSCATION_TOOLKIT.MD5 permet de vous générer un

hash code en MD5.

 


 




--Exemple:
--Création des utilisateurs

SQL> exec demo_user_security.add_user('Smith','secret');
     
    PL/SQL procedure successfully completed.
   
SQL> exec demo_user_security.add_user('William','terces121');
     PL/SQL procedure successfully completed.
SQL> select * from demo_users;
    ID      USERNAME                 PASSWORD
 ----------- -----------------------------------------------
    1       Smith                   ãXFõˆC„®W3–E
    2       William                 b¾õmûMÀ*愶}ˆ

--Ensuite on va vérifier la procédure VALID_USER		


SQL> EXEC demo_user_security.valid_user('Smith','secret');

    PL/SQL procedure successfully completed.

SQL> EXEC demo_user_security.valid_user('William','bblsld');
    BEGIN app_user_security.valid_user('william','bblsld'); END;

    *
    ERROR at line 1:
    ORA-20000: nom utilisateur/mot de passe incorrect.
    ORA-06512: at "W2K1.DEMO_USER_SECURITY", line 66
    ORA-06512: at line 1

--Ensuite on vérifiéra la fonction VALID_USER.

SQL> SET SERVEROUTPUT ON
SQL> BEGIN
      2    IF demo_user_security.valid_user('Smith','secret') THEN
      3      DBMS_OUTPUT.PUT_LINE('TRUE');
      4    ELSE
      5      DBMS_OUTPUT.PUT_LINE('FALSE');
      6    END IF;
      7  END;
      8  /
    TRUE

    PL/SQL procedure successfully completed.

SQL> BEGIN
      2    IF demo_user_security.valid_user('William','bblsld') THEN
      3      DBMS_OUTPUT.PUT_LINE('TRUE');
      4    ELSE
      5      DBMS_OUTPUT.PUT_LINE('FALSE');
      6    END IF;
      7  END;
      8  /
    FALSE

    PL/SQL procedure successfully completed.

SQL>

--Au final on vérifiéra la procédure CHANGE_PASSWORD.

SQL> exec demo_user_security.change_password('Smith','secret','tresect');

    PL/SQL procedure successfully completed.

SQL> exec demo_user_security.change_password('William','vfrdtg','vcftg12');
    BEGIN app_user_security.change_password('William','vfrdtg','vfrd14g'); END;

    *
    ERROR at line 1:
    ORA-20000:  nom utilisateur/mot de passe incorrect.
    ORA-06512: at "W2K1.DEMO_USER_SECURITY", line 52
    ORA-06512: at line 1

 




1 comment:

  1. Merci beaucoup Hakim, votre poste m'a énormément aidé

    ReplyDelete