fredag 28 maj 2010

Hur spara applikationslösenorden?

En evig fråga för systemutvecklare och driftansvariga är – hur sparar vi lösenorden som applikationen behöver? Det är ofta flera lösenord som har med applikationen eller applikationsservern att göra. Lösenord till databasen, lösenord till certifikat, lösenord till keystores, lösenord för maskin till maskin-koppel och så vidare.

Alternativen som står till buds
Det finns följande enkla men osäkra alternativ:
  • Lösenord i klartext i konfigurationsfil
  • Lösenord i klartext i koden
Sen har vi de bra mycket säkrare men också jobbigare alternativen:
  • Krypterade lösenord i konfigurationsfil med nyckel i koden (kan vara en masternyckel för hela applikationen)
  • Krypterade lösenord i kod eller kodnära konfigurationsfil och lösenord i driftnära konfigurationsfil (känns lite bakvänt men ibland har man större förtroende för driftansvarig än för utvecklarna, t ex vid outsourcing)
  • Krypterade lösenord i en LDAP eller liknande
Och så har vi hybriden:
  • Krypterade lösenord i konfigurationsfil med delad nyckel – halva i koden, halva i konfigurationsfil.
Till sist har vi de väldigt säkra och grymt jobbiga alternativen:
  • Lösenord i huvudet på driftansvariga (anges vid varje driftsättning medelst många svordomar)
  • Drakonisk hårdvarulösning
Standardlösningar?
Mig veterligen så finns ingen standardlösning på det här i vaniljsmaken på Java EE. Istället så bestämmer varje team sig för hur man ska göra med lösenorden. Synd.

I lakritsjava (=enterprise) så finns det färdiga lösningar. IBMs WebSphere kör tyvärr default med en naiv XOR (ref):

"WebSphere Application Server stores passwords XOR encoded in the XML configuration files."

Men man kan plugga in valfri krypteringslösning genom att implementera deras CustomPasswordEncryption-interface eller sätta customPasswordEncryptionClass och customPasswordEncryptionEnabled i PropFilePasswordEncoder.bat/sh. Bra grejer.

i .NET-världen kanske det ser annorlunda ut, inte minst tack vare integrationen med Windows API:er som Data Protection API (CryptProtectData). Men jag är ingen klippa på .NET. Någon som kan hjälpa till? Kristofer?

Vad ska man brygga om man brygger hemma?
OK, men för oss som inte har betalat för en WebSphere-licens, vad står till buds? En XOR-kryptering med statisk nyckel i koden kanske?

Nja, så här säger min kollega Lars Johansson om XOR-kryptering:

XOR ger visserligen "perfekt sekretess" (bevisat av Shannon 1949), men det förutsätter följande:
  1. Nyckeln måsta vara lika lång som klartextmeddelandet.
  2. Nyckeln måste vara fullständigt slumpmässig. Så fort en nyckel återanvänds går det att knäcka kryptotexten!
Båda dessa ovanstående krav gör att perfekt sekretess med XOR inte går att realisera i praktiken. Använd en etablerad kryptoalgoritm i stället, t.ex. AES. Då är det inte lika noga med nyckellängden (256 bitar duger gott). Nyckeln bör dock fortfarande ha bra slump/entropi.

Vi borde skärpa oss lite
Jag tror de flesta tycker det här är för jobbigt och har alla maskinlösenord i klartext eller med defaultskydd. Vi borde skärpa oss lite. AES-kryptering med nyckeln i källkoden borde vara ett minimum. Gärna genom en snygg öppen källkodslösning som alla kan planka :).

Vad tycker ni andra? Hur gör ni?

5 kommentarer:

Kryptera.se sa...

Solar Designer skrev nyligen en bra artikel om detta: http://to.ly/4LlZ

Stefan Pettersson sa...

För .NET är väl krypterade strängar i web.config mer eller mindre standard?

T ex
http://ondotnet.com/lpt/a/5639

Peter Magnusson sa...

DPAPI på microsoft är en klippa på detta.

- användare A kan inte dekryptera data från användare B

- råkopiering av hårddisken gör att systemkontons DPAPI information kan dekryperas, eftersom de kan självstartas vid bootup. Likaså om man loggar in på datorn utan lösenord är ens DPAPI information svagt skyddad (vanligt på hemdatorer)

- om man har ett bra Windows lösenord och behöver det för att logga in, då är man väl skyddad (fast man måste ju ha 15 eller fler tecken i lösenordet för att ens lösenord inte skall knäckas blixtsnabbt pga den svaga 7+7 hashen LANMAN)

Peter Magnusson sa...

... Och så har man begränsat skydd mot onda administratörer. De kan inte bara byta lösenord och sen läsa ens DPAPI information. Fast onda administratören kan naturligtvis installera keyloggers för att sno lösenordet från användare.

Frågan är väl hur ond administatören skall antas kunna vara innan man anser att ens TCB inte är någon "trusted" computing base. DPAPI kan inte lösa allt!

Synd att det saknas motsvarande API på de flesta andra operativsystem.

Peter Magnusson sa...

Jag håller föresten inte med om att XOR är "dåligt" i dessa sammanhang. Hårdkodad AES är ytterst marginellt säkrare, och då har man infört någon sorts "vi gör något avancerat så det är lite säkrare" filosofi. XOR är mer ärligt; "vi gör detta för att förhindra oavsiktlig läsning utan verktyg" punkt slut. Obfuskering, inte stark kryptering.

Skall man jacka in en en egen Java-klass tycker jag man borde fundera över JNI integration mot Windows DPAPI.

Är Windows inte det som används så tycker jag en agent som hämtar nyckeln till de-obfuskerkings från en lösenordsserver ute på nätverket, så att man kommer bort ifrån att all information som krävs för dekryptering finns i en enda fil.