Recuperare una Password cifrata da Pentaho
Connessioni Database
Se si utilizza un repository centralizzato su database,
Pentaho registra le informazioni legate alle connessioni (host_name
, database_name
, ..) nella tabella
r_database
, assieme alle credenziali in formato “offuscato”.
Non si tratta di un hash monodirezionale ma di un formato che, pur non direttamente leggibile, può
essere facilmente decifrato.
select
id_database,
name,
username,
password
from
r_database
Recupero password Offuscate
Le password offuscate sono precedute dalla stringa Encrypted
. Se prendiamo come esempio la password prova
, questa verrà salvata in tabella con la stringa Encrypted 2be98afc86aa7f2e4cb79ce60cc9db9db
.
Quale metodo viene utilizzato per codificare e decodificare le password? Pentaho utilizza la libreria Encr.java
che richiama diverse funzioni presenti in KettleTwoWayPasswordEncoder.java
.
Un sistema per decifrare la password è dimostrato nella trasformazione Pentaho-Kettle-Password-Decrypt che lo trovo interessante perché permette di integrare la libreria Java che gestisce l’offuscamento delle password all’interno di una trasformazione, importanto la libreria e definendo la funzione da richiamare:
import org.pentaho.di.core.encryption.Encr;
Encr.decryptPassword(encrypted_password)
Tuttavia non è strettamente necessario utilizzare questo sistema.
Facendo una breve analisi del codice sorgente, si riesce facilmente ad individuare la logica del funzionamento, ovvero la definizione di una chiave “segreta”:
public KettleTwoWayPasswordEncoder() {
String envSeed = Const.NVL( EnvUtil.getSystemProperty( Const.KETTLE_TWO_WAY_PASSWORD_ENCODER_SEED ), "0933910847463829827159347601486730416058" ); // Solve for PDI-16512
Seed = envSeed;
}
(che corrisponde alla costante KETTLE_TWO_WAY_PASSWORD_ENCODER_SEED
nel caso essa sia configurata,
oppure al valore fisso 0933910847463829827159347601486730416058
)
e l’algoritmo di codifica/decodifica che, senza sorpresa, avviene semplicemente tramite OR esclusivo. Il codice che decifra la password, semplificando al massimo e togliendo diversi controlli, è sostanzialmente questo:
import java.math.BigInteger;
public class Main
{
public static void main(String[] args) {
String envSeed = "0933910847463829827159347601486730416058";
String encrypted = "2be98afc807ce808daa1dab65d281bc8e";
int RADIX = 16;
BigInteger bi_confuse = new BigInteger( envSeed );
BigInteger bi_r1 = new BigInteger( encrypted, RADIX );
BigInteger bi_r0 = bi_r1.xor( bi_confuse );
System.out.println(new String( bi_r0.toByteArray() ));
}
}