Når man lager sikker og robust programvare er det ofte en utfordring å teste applikasjonen under utvikling. Man lager derfor såkalte bakdører for å slå av, eller omgå, sikkerhet. Dette kan være nyttig og tidsbesparende for utviklere og testere mens man utvikler eller tester det man utvikler. Men, det er imperativt at ikke slik kode blir med ut i produksjon på en måte som gjør at utenforstående kan utnytte disse bakdørene for “ondsinnede” angrep. Ofte ser man teknikker hvor utviklere gjør det vanskelig for utenforstående å finne eller aktivere disse bakdørene, men det tryggeste, og etter min mening det eneste riktige, er å utelate slik kode i produksjon.
Nylig utviklet vi en web-applikasjon i Java med flere nivåer av autentisering. Vi benyttet Jetty som container og Maven 2 for bygging og pakking av applikasjonen. Vi lagde en bakdør for enkelt å kunne autentisere og autorisere oss på forskjellige nivåer. Slik ungikk vi å måtte logge oss på hver gang vi ønsket å teste noe vi nettopp hadde utviklet. Når det nærmet seg første produksjonssetting måttte vi for enhver pris unngå at denne bakdøren ble med ut i produksjon. Vi ønsket imidlertid ikke å forkaste løsningen da den ga oss en mye kjappere utviklingssyklus (kode-kjøre-teste, kode-kjøre-teste…) og applikasjonen skulle selvsagt videreutvikles. Vi løste det på følgende måte.
Bakdøra
Vi hadde et servletfilter som het BackDoorFilter. Denne skrur av sikkerhet i applikasjonen hvis systemvariabelen dev.mode er satt til true ved å autentisere med ønsket sikkerhetsnivå i sesjonsobjektet. I tillegg lagde vi en jsp-side med en meny hvor man kunne velge hvilken bruker og hvilken autorisering denne skulle autentiseres med.
For å være helt sikre utelot vi BackdoorFilter.class og JSP-en backdoor.jsp fra den pakkede webapplikasjonen (war-filen) dersom man ikke bygger med profilen dev. I tillegg utelot vi konfigurasjonen av disse i web.xml ved å filtrere deployment-descriptoren (web.xml) ved bygging. Dersom vi aktiverer profilen dev ved bygging pakkes bakdøren med applikasjonen, og konfigurasjonen av bakdøren filtreres inn i web.xml. Dette løste vi ved å konfigurere maven-war-plugin med packagingExcludes og filteringDeploymentDescriptors=true.
pom.xml
web.xml
I web.xml legges placeholdere til for verdiene som skal filtreres inn (backdoor.filter, backdoor.filter-mapping og devInnlogging.servlet).
Vi måtte gjøre en ting til for å få jetty:run til å fungere tilsvarende
Maven-jetty-plugin er en fabelaktig plugin som gir en kjapp utviklingssyklus. Med denne kan man kjøre mvn jetty:run og få opp en kjørende versjon av applikasjonen din som støtter hot deploy (med visse unntak som jeg ikke vil komme inn på her). Maven-jetty-plugin kan kjøre på en utpakket versjon av applikasjonen din og re-laste applikasjonen med jevne mellomrom (i dette tilfellet hvert tiende sekund). Det betyr at man kan endre kildekode mens applikasjonen kjører og man vil se resultatene (nesten) umiddelbart. Utfordringen er at den ikke tar hensyn til maven-war-plugin, og dermed vil ikke oppsettet jeg har beskrevet ovenfor fungere. Dermed måtte vi løse dette på en lignende, men separat måte. Vi ønsket ikke å lage en separat web.xml, da dette ville medføre unødvendig duplisering. Vi tok derfor utgangspunkt i samme web.xml og filtrerte denne som en maven resource. Pluginen build-helper-maven-plugin lar oss legge til nye resource-kataloger i tillegg til default src/main/resources og src/test/resources.
pom.xml
Oppsummert
Bakdører kan være svært nyttig under utvikling og testing, men man må være forsiktig slik at disse ikke blir med ut i produksjon. Derfor bør man utelate slik kode ved normal bygging av applikasjonen. Under utvikling kan man lage en dev-profil i Maven som inkluderer bakdøren ved aktivering:
mvn clean install -Pdevmvn jetty:run -Pdev