söndag 24 januari 2010

Säkerhet i Java EE 6, HttpOnly och session cookies

Jag bloggade tidigare om nya säkerhetsfunktioner i Java EE 6 HttpServletRequest. Nu har turen kommit till säkerhetsnyheterna kring cookies, eller kakor som jag gillar att kalla dem :).

För er som bara vill läsa om det nya är det bara att hoppa till rubriken "Nyheter i Java EE 6".

Http saknar session och tillstånd
Http som protokoll har ju varken sessionshantering eller tillstånd (state). Kakor används för både och. Internet Explorer sätter de hårdaste begränsningarna på hur mycket tillstånd som får lagras i kakor:
  • Max 4 kB per kaka i IE6 och IE7
  • Max 50 kakor per sajt i IE6, IE7 och IE8
Alla andra webbläsare tillåter större och fler kakor. Men för sessionshantering så räcker 4 kB och en kaka bra. Det man snarare behöver arbeta med är sessionskakans säkerhet.

Hot mot sessioner i kakor
Det finns flera hot mot sessionshantering i kakor:
  • Session hijacking. XSS kan stjäla sessioner direkt ur sidan eftersom document.cookie normalt sett är tillgänglig för JavaScript. Därtill kan okrypterade kakor stjälas direkt på nätet.
  • Cookie replay. Sessionskakan kan öppna upp en avslutad session på nytt. Attackeraren återanvänder den helt enkelt.
  • Cookie poisoning. Applikationen använder inte pseudoslump på ett bra sätt vid sessionshanteringen vilket tillåter en attackerare att generera en giltig sessionskaka.

Skydd av sessioner i kakor
För att skydda sina sessionskakor (och andra kakor för den delen) finns ett antal tekniker:
  • HttpOnly-attributet. Genom att markera sin sessionskaka som HttpOnly så ser webbläsaren till att JavaScript inte får läsa den. XSS-stöld av kakan blir alltså omöjligt. Det har tagit tid för webbläsarna att få ordning på det här. T ex så kunde AJAX-anrop få tillgång till alla Http-headers där ju också kakorna finns. Så XSS med AJAX kunde kringå HttpOnly. Java EE 5-API:et har inte stöd för HttpOnly.
  • Secure-attributet. Genom att markera sin sessionskaka som Secure så ser webbläsaren till att kakan bara skickas vid https-anrop, dvs krypterat.
  • Pseudoslump. Sessionskakor ska genereras med pseudoslump, så kallat salt. Hela den hanteringen är så pass svår att man inte ska sköta sin egen sessionshantering. Låt din applikationsserver göra det åt dig.

Nyheter i Java EE 6
Första nyheten i Java EE 6 är att HttpOnly numer stöds av API:et! I klassen Cookie hittar vi:

public void setHttpOnly(boolean isHttpOnly)
public boolean isHttpOnly()

Därtill kan man via sin servlet-kontext sätta hur sessionshanteringen ska ske. I ServletContext finns från och med nu:

void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)

... där man sätter en eller flera SessionTrackingMode som man vill ha. SessionTrackingMode är en enum som erbjuder sessionshantering med:
  • COOKIE. Precis vad det låter som -- sessionshantering med kakor. Mer om det nedan.
  • SSL. SSL-sessionen används som http-session. Det kräver förstås att det är en https-koppling, formellt att ServletRequest.isSecure() returnerar true.
  • URL. Sessions-id följer med som en URL-parameter.
Sä här sätter man sessionshanteringen till SSL:

ServletContext context = event.getServletContext();
EnumSet<SessionTrackingMode> modes =
EnumSet.of(SessionTrackingMode.SSL);
context.setSessionTrackingModes(modes);

Konfigurera sessionskakan
Sessionshantering med kakor är ju inget nytt som sådant och vår gamla JSESSIONID hänger med än. Men nu kan vi konfigurera bättre hur applikationsservern ska sköta JSESSIONID. Det gör man med SessionCookieConfig som är ny i Java EE 6. Intressantast i det interfejset är förstås:

void setHttpOnly(boolean httpOnly)
void setSecure(boolean secure)

På så vis kan vi säga åt appservern att bara skicka JSESSIONID-kakan krypterat och med HttpOnly-attributet på.

1 kommentar:

kalleg sa...

Bra att det äntligen dyker upp stöd för secure- och HTTP only-flaggorna i API:et.

Många (samtliga?) servletmotorer har redan stöd för secure- och/eller HTTP only-kakor, fast då som en konfigurationsparameter på server- eller applikationsnivå. Att få stöd direkt i API:et är ett steg framåt eftersom det öppnar för mer kontroll över kakorna från applikationens sida och, framför allt, att det fungerar likadant för samtliga servletmotorer. Idag är ofta dokumentationen för hur man konfigurerar kakorna inte helt lätt att hitta.