In questo articolo voglio affrontare il problema del mascheramento di informazioni sensibili utilizzate dalle applicazioni, in particolare password di accesso. E’ abbastanza comune, infatti, per una applicazioni di medie dimensioni di dover utilizzare delle credenziali per l’accesso ad altri sistemi, come ad esempio una base dati. Ed è altrettanto comune conservare tali informazioni in file di property senza alcuna cifratura e quindi assolutamente vulnerabili ad attacchi ma anche alla più semplice ispezione “casuale”. L’esempio che presentiamo si applica all’Application Server JBoss (versione EAP 6.4) ed utilizza il sottosistema Password Vault per il mascheramento delle informazioni sensibili. Tali informazioni invece di essere memorizzate in un file di configurazione in chiaro sono archiviate in un area protetta attraverso un keystore crittografato. Il sistema si compone di due parti: archiviazione e memorizzazione delle chiavi. Un keystore java è utilizzato per memorizzare la chiave crittografica che è utilizzata per cifrare o decifrare le stringhe sensibili memorizzate nell’archivio di Vault.
L’applicazione
La semplice applicazione di esempio che utilizzeremo per la nostra discussione è una web-app creata utilizzando Maven secondo la procedura descritta nell’articolo Creare una Web Application con Maven. Tale applicazione espone una servlet HTTP così configurata nel file web.xml
:
1 2 3 4 5 6 7 8 9 |
<servlet> <display-name>VaultServlet</display-name> <servlet-name>VaultServlet</servlet-name> <servlet-class>it.javaboss.VaultServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>VaultServlet</servlet-name> <url-pattern>/VaultServlet</url-pattern> </servlet-mapping> |
La servlet è implementata dalla classe ValutServlet.java
ed il metodo doGet()
si presenta nel seguente modo:
1 2 3 4 5 |
public class VaultServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().append("Password: ").append( System.getProperty("it.javaboss.HSM_PASSWORD") ); } } |
Ai più attenti non sarà sfuggito che la password (da proteggere) è conservata in una proprietà di sistema identificata dalla stringa it.javaboss.
HSM_PASSWORD e che per i nostri scopi è definita nel file standalone.xml
nella sezione <system-properties>
, che segue immediatamente la sezione <extensions>
,nel modo seguente:
1 2 3 |
<system-properties> <property name="it.javaboss.HSM_PASSWORD" value="questa e' una password in chiaro"/> </system-properties> |
A questo punto possiamo avviare JBoss, eseguire il deploy del war dell’applicazione (io ho utilizzato il JBoss Maven Plugin) ed inserire l’url http://localhost:8080/vault/VaultServlet nella barra degli indirizzi del nostro browser, per ottenere quindi:
Mascheramento della Password
Vediamo ora come possiamo utilizzare il modulo Vault, di JBoss, per mascherare la password del nostro ipotetico sistema da integrare nell’applicazione (nell’esempio si tratta della password di un HSM, Hardware Security Module). Prerequisito necessario per comprendere quanto descritto nel seguito del paragrafo è la conoscenza di concetti di base di crittografia ed all’utilizzo del keytool di java. Per una rapida infarinatura è possibile leggere gli articoli del blog Crittografia in Java e Utilizzo dei certificati in Java.
Generazione del Keystore
Innanzitutto dobbiamo generare il keystore che sarà utilizzato da Vault per la conservazione delle chiavi di cifratura e decifratura delle informazioni sensibili. Allo scopo utilizzeremo il keytool
disponibile nella JRE. Creiamo quindi la directory [EAP_HOME]/standalone/vault
ed apriamo un shell di comando per eseguire l’istruzione:
1 2 |
keytool -genseckey -alias vault -storetype jceks -keyalg AES -keysize 128 -storepass vault123 -keypass vault123 -validity 730 -keystore vault.keystore |
L’effetto sarà la produzione di un keystore denominato vault.keystore
contenente una chiave AES identificata dall’alias vault
e protetta dalla password valut123
. Si noti che la password della chiave e del keystore devono coincidere.
Configurazione di Vault
Configuriamo ora Vault utilizzando il tool contenuto nella cartella [EAP_HOME]/bin
eseguendo il comando vault.sh
. Selezioniamo 0
per la modalità interattiva e procediamo inserendo la directory dove conservare i dati cifrati ([EAP_HOME]/standalone/vault/
), la posizione del keystore ([EAP_HOME]/standalone/vault/vault.keystore
), e le informazioni per l’accesso alle chiavi, come mostrato nello script seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Please enter a Digit:: 0: Start Interactive Session 1: Remove Interactive Session 2: Exit 0 Starting an interactive session Enter directory to store encrypted files:[EAP_HOME]/standalone/vault/ Enter Keystore URL:[EAP_HOME]/standalone/vault/vault.keystore Enter Keystore password: vault123 Enter Keystore password again: vault123 Values match Enter 8 character salt:javaboss Enter iteration count as a number (Eg: 44):50 Enter Keystore Alias:vault Initializing Vault giu 06, 2017 10:47:17 AM org.picketbox.plugins.vault.PicketBoxSecurityVault init INFO: PBOX000361: Default Security Vault Implementation Initialized and Ready |
Il tool stamperà in output una porzione di XML che dovrà essere inserita nello standalone.xml
immediatamente al di sotto della sezione <extensions>
e prima della sezione <management>
:
1 2 3 4 5 6 7 8 9 10 11 12 |
Vault Configuration in configuration file: ******************************************** ... </extensions> <vault> <vault-option name="KEYSTORE_URL" value="[EAP_HOME]/standalone/vault/vault.keystore"/> <vault-option name="KEYSTORE_PASSWORD" value="MASK-3EkUIOWFT68ti1UknJuFHT"/> <vault-option name="KEYSTORE_ALIAS" value="vault"/> <vault-option name="SALT" value="javaboss"/> <vault-option name="ITERATION_COUNT" value="50"/> <vault-option name="ENC_FILE_DIR" value="[EAP_HOME]/standalone/vault/"/> </vault><management> ... |
Cifratura Dati Sensibili
Se stiamo ancora eseguendo il tool vault.sh
(altrimenti rieseguire la procedura di configurazione) il prompt ci consentirà ora di selezionare l’opzione 0: Store a secured attribute
. Le informazioni che ci verranno chieste sono:
- il valore dell’attributo (da cifrare);
- il vault block identificativo univoco di una sezione del vault;
- il nome dell’attributo.
Il risultato dell’elaborazione sarà sarà una stringa identificativa dell’attributo specificato all’interno del vault, come mostrato nello script seguente:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Please enter a Digit:: 0: Store a secured attribute 1: Check whether a secured attribute exists 2: Remove secured attribute 3: Exit 0 Task: Store a secured attribute Please enter secured attribute value (such as password): questa e' una password cifrata Please enter secured attribute value (such as password) again: questa e' una password cifrata Values match Enter Vault Block:HSM Enter Attribute Name:PASSWORD Secured attribute value has been stored in vault. Please make note of the following: ******************************************** Vault Block:HSM Attribute Name:PASSWORD Configuration should be done as follows: VAULT::HSM::PASSWORD::1 ******************************************** |
Nella sezione tra asterischi è riepilogato l’attributo appena inserito e la stringa VAULT::HSM::PASSWORD::1
da sostituire al testo in chiaro nella sezione <system-properties>
come segue:
1 2 3 |
<system-properties> <property name="it.javaboss.HSM_PASSWORD" value="${VAULT::HSM::PASSWORD::1}"/> </system-properties> |
${VAULT::VAULT_BLOCK::ATTRIBUTE_NAME::MASKED_STRING}
dove riconosciamo immediatamente i marcatori dei parametri utilizzati.
Esecuzione dell’Applicazione
Terminata la configurazione possiamo procedere avviando nuovamente JBoss, e questa volta inserire l’url http://localhost:8080/vault/VaultServlet nella barra degli indirizzi del nostro browser, otterremo:
Codice Sorgente
Il codice sorgente dell’applicazione, comprensiva del keystore e del file cifrato, può essere scaricato qui vault.