Abbiamo visto nella precedente lezione che i security tokens sono collezioni di uno o più claims, ossia contengono una serie di dichiarazioni che possono servire a fornire informazioni d’autenticazione e, combinandoli con gli standard per la criptazione e la firma, possono permettere di instaurare confidenzialità e integrità. La specifica OASIS per WS-Security 1.1 descrive diversi tipi di security tokens e l’estensibilità dell’header <wsse:Security> ne garantisce il supporto. La specifica non definisce se e come i claims vadano confermati, ma come utilizzare la firma in associazione con i security tokens a conferma del claim. Per una prima divisione dei security tokens abbiamo:
Security tokens | Descrizione |
---|---|
User Name Tokens | L’identità dell’utente (tipicamente username e password) è inserita nel messaggio e messa a disposizione degli end-users. |
Binary Security Tokens | Usati per tokens come X.509, Kerberos o altri tokens non formattati in XML che richiedono una speciale codifica per l’inclusione in messaggi XML. |
XML Tokens | Base per utilizzare altri security tokens realizzati tramite l’XML. |
User Name Tokens
L’elemento <wsse:UsernameToken> offre un modo semplice per fornire un username, tipicamente formato da username e password, per fornire l’identità di chi invoca il servizio e permettere al fornitore del servizio di valutare le azioni da compiere in risposta all’invocazione. Il server verificherà se il timestamp è ancora valido, se l’username è previsto nel proprio repository, se la password relativa è valida:
<wsse:UsernameToken>
<wsse:Username>user</wsse:Username>
<wsse:Password Type="wsse:PasswordText">password</wsse:Password>
</wsse:UsernameToken>
Nel token descritto vengono passati user e password. Da notare che l’elemento wsse:Password
ha un attributo Type
settato in modo da fornire una semplice stringa testuale ("Plain Text"). La password può essere passata in modalità testuale o in forma di firma, il che fornisce un grado di sicurezza maggiore. Segue un esempio di password in forma di firma:
<wsse:UsernameToken>
<wsse:Username>scott</wsse:Username>
<wsse:Password Type="wsse:PasswordDigest">
KE6QugOpkPyT3Eo0SEgT30W4Keg=</wsse:Password>
<wsse:Nonce>5uW4ABku/m6/S5rnE+L7vg==</wsse:Nonce>
<wsu:Created xmlns:wsu=
"http://schemas.xmlsoap.org/ws/2002/07/utility">
2002-08-19T00:44:02Z
</wsu:Created>
</wsse:UsernameToken>
La password ora è oscurata con un hash SHA1. PasswordDigest
è la concatenazione del parametro nonce
(un long da 16 bytes passato come valore codificato in base64), del tempo di creazione e della password. Il server partendo dal tempo di creazione e dal nounce, oltre alla password memorizzata localmente per l’user, dovrebbe essere in grado di riottenere l’esatto valore passato, confermando l’hash. Sicuramente un grado di difesa maggiore rispetto a una password testuale, ma non difende da attacchi di tipo replay, per cui è utile abbinare il tutto a un timestamp sufficientemente breve (wsu:Timestamp
) in grado di essere combinato con la firma per prevenire simili attacchi.
Binary Security Tokens
Un altro sistema di autenticazione consiste semplicemente nell’usare un certificato come X.509 passandolo direttamente tramite il security token. Dato che sono certificati non basati sull’XML, vengono aggregati al messaggio dopo essere stati convertiti in binario. Questo genere di certificati presenta un grado di fiducia maggiore rispetto a un’autenticazione basata su user e password. Usando PKI è possibile mappare il certificato con un user conosciuto all’applicazione. Combinando il meccanismo con la firma è possibile anche evitare attacchi di tipo replay. Passando un certificato Kerberos si avrà qualcosa del tipo:
<wsse:BinarySecurityToken
ValueType="wsse:X509v3"
EncodingType="wsse:Base64Binary"
Id="SecurityToken-f49bd662-59a0-401a-ab23-1aa12764184f">MIIHdjCCB...
</wsse:BinarySecurityToken>
Tramite una politica basata sull’anzianità del messaggio (aggregando un timestamp) è possibile stabilire se scartare o meno il messaggio ricevuto, riducendo la possibilità di subire attacchi di replay. Segue un esempio di timestamp che include tempo di creazione e limite oltre il quale cessa di essere valido.
<wsu:Timestamp>
<wsu:Created
wsu:Id="Id-3beeb885-16a4-4b65-b14c-0cfe6ad26800"
>2002-08-22T00:26:15Z</wsu:Created>
<wsu:Expires
wsu:Id="Id-10c46143-cb53-4a8e-9e83-ef374e40aa54"
>2002-08-22T00:31:15Z</wsu:Expires>
</wsu:Timestamp>
Firma
Firmando un messaggio si può essere certi che il messaggio non sia stato manomesso lungo il percorso, pur non garantendo che terze parti non lo leggano. La specifica consente di allegare al messaggio firme multiple e di diversi formati, ognuna associata a diverse parti del messaggio, anche sovrapposte.
Un header wsse:Security
può contenere una (o più) firme con lo scopo di firmare uno o più elementi dell’envelope SOAP. In teoria, tutte le parti importanti dovrebbero essere firmate per poterle legittimare. Sempre in teoria, applicazioni che implementano WS-Security dovrebbero essere in grado di processare i relativi elementi. Potendo infine firmare anche gli stessi tokens (e persino informazioni esterne), è possibile stabilire con certezza che non solo il corpo del messaggio è giunto incorrotto, ma anche che è giunto da chi è autorizzato a richiedere il servizio.
Ciascuno dei metodi di autenticazione precedentemente descritti dispone di un meccanismo che permette al server di stabilire che il messaggio è autentico. Con l’UsernameToken
la firma viene basata sulla password, X.509 abilita l’user a firmare il messaggio con la chiave privata e infine Kerberos fornisce una chiave di sessione che l’utente crea e trasmette in un ticket che può leggere solo il destinatario.
Un problema può riguardare la presenza di intermediari che vadano a porre la controfirma nel timestamp (wsu:Received
), il che richiede che la firma vada adeguata per contemplare le modifiche apportate nel tragitto.
Criptazione
A volte l’autenticazione e la garanzia della non corruzione del messaggio non sono sufficienti, occorre garantire che il messaggio non sia letto. Tramite l’XML Encryption, WS-Security permette di gestire anche questa esigenza. La specifica consente di combinare la criptazione di blocchi e sottostrutture dell’header e del body di un messaggio SOAP, scegliendo tra chiavi trasportate nel messaggio e criptate a loro volta o con chiavi condivise tra mittenti e destinatari.
Quando un producer o un intermediario attivo criptano una o più parti del messaggio, aggiungono un sotto elemento al security header (o ne creano uno nuovo). Il sotto elemento creato contiene le informazioni necessarie per identificare le porzioni del messaggio da decriptare. L’elemento xenc:ReferenceList
; è usato per creare un manifesto delle porzioni criptate (xenc:DataReference
), identificate a loro volta dall’elemento xenc:EncryptedData
.
Un tipico scenario in cui l’elemento xenc:ReferenceList
è utile è quello in cui destinatario e mittente utilizzano una chiave segreta:
<S11:Header>
<wsse:Security>
<xenc:ReferenceList>
<xenc:DataReference URI="#bodyID"/>
</xenc:ReferenceList>
</wsse:Security>
</S11:Header>
<S11:Body>
<xenc:EncryptedData Id="bodyID">
<ds:KeyInfo>
<ds:KeyName>CN=Mario Rossi, C=IT</ds:KeyName>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>...</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</S11:Body>
Nel caso in cui si utilizzi una chiave simmetrica inclusa nel messaggio, l’elemento xenc:EncryptedKey
può essere utilizzato per trasportare la chiave criptata. Al suo interno si potrà trovare un elemento di tipo xenc:ReferenceList
che annota le porzioni criptate con la relativa chiave. Anche se nell’XML Encryption l’elemento xenc:EncryptedKey
può essere specificato in un elemento di tipo xenc:EncryptedData
, la specifica WS-Security raccomanda di porre tale elemento nell’header wsse:Security
.
Per quanto riguarda infine la criptazione di blocchi dell’header SOAP, la specifica raccomanda l’uso dell’elemento wsse:EncryptedHeader
che contiene esattamente un xenc:EncryptedData
. In generale, un envelope SOAP criptato deve essere ancora un envelope SOAP valido, per cui gli elementi Header, Envelope, Body non vengono criptati, ma possono essere criptati i relativi sotto elementi.
Il costo temporale di WS-Security
WS-Security offre diversi vantaggi rispetto all’utilizzo della sicurezza a livello trasporto, potendo contare su un controllo più fitto. Ciò non è privo di impatti.
Da notare che anche una “semplice” soluzione di tipo username e password in chiaro richiede tempi più pesanti di quelli richiesti da un meccanismo di sicurezza basato su SSL/TLS, a sua volta più pesante rispetto a invocazioni prive di sicurezza. Man mano che aumenta la complessità richiesta a WS-Security aumentano in modo significativo anche i tempi di risposta. La capacità di controllo a un livello di dettaglio più fine non è detto sia necessariamente un bene ma bisogna bilanciare le esigenze di sicurezza con gli altri vincoli non funzionali. Nelle prossime lezioni seguiranno degli esempi pratici in cui applicheremo quanto descritto finora.