I begynnelsen av desember ble det kjent at det lå en sårbarhet i Apache Log4j-rammeverket. Sårbarheten går under kallenavnet Log4Shell og minnet noen av oss om at JNDI fortsatt eksisterer.
Den ble utnyttet ganske raskt, og mange virksomheter, både her i Norge og i resten av verden, måtte stenge ned en stund. Noen ble faktisk angrepet, mens andre trengte tid for å få på plass tiltak mot sårbarheten.
Men nå som støvet har lagt seg litt, kan vi stille oss spørsmålet hva vi har lært av denne hendelsen.
Derfor skal jeg bli flinkere til å be andre utviklere om hjelp
#1: Angrep både utenfra og innenfra
Første lærdom er at det er viktig å ha kontroll på datatrafikk i produksjon, både på vei inn og på vei ut. Det er fort gjort å tenke at siden angrep kommer utenfra, så er det først og fremst datatrafikk på vei inn som det er viktig å scanne og filtrere for å unngå problemer.
Men for det første kan truslene også sitte på innsiden av organisasjonen, utro tjenere for å nevne et åpenbart eksempel. Og for det andre kan tilsynelatende legitime datastrømmer på vei inn forårsake illegitim datatrafikk ut, som i dette tilfellet.
Denne gangen kunne en del virksomheter beskytte seg mot Log4Shell-angrepet på en effektiv måte ved å legge til passende regler i WAF-produktet (web application firewall) de brukte. Slik kunne de kjøpe seg litt tid og holde systemene i produksjonsmiljøet oppe mens utviklerne oppdaterte Apache Log4j-biblioteket der det var brukt.
Ekspert: - Norge har stått i en ransomware-pandemi
#2: Oppdaterbar er bedre enn oppdatert
Men når det gjelder det siste, det å oppdatere Apache Log4j der det er brukt, har vi lært (igjen) at det er viktig å være i stand til å oppdatere biblioteker med sårbarheter i løpet av kort tid. Spesielt har vi lært at det er viktigere å ha programvare og komponenter som er oppdaterbare enn at de er oppdatert. Det sier seg selv at du stiller som regel bedre med oppdaterte komponenter enn med utdaterte komponenter, også når det gjelder oppdaterbarhet.
Men en litt utdatert komponent som man på en grei måte kan oppdatere til nyeste versjon, og ha muligheten til å sette den og resten av programvaren i produksjon i løpet av kort tid, er bedre enn en oppdatert komponent som så trenger en seks ukers testperiode.
Å sitte på eldgamle versjoner av biblioteker og rammeverk, selv om de ikke har noen sårbarheter som er allment kjent i dag, er et sikkerhetsproblem. Log4Shell-sårbarheten er en konsekvens av kode som har vært der siden 2013, og man kan trygt anta at de som brukte en Apache Log4j-versjon fra 2021 stilte mye bedre for å oppgradere systemene sine enn de som brukte versjoner fra 2014 eller 2015.
I tillegg er et godt byggemiljø med fungerende CI/CD-pipelines for kontinuerlig leveranse, inkludert automatiserte akseptansetester som reduserer behovet for mye manuell regresjonstesting, gull verdt i slike situasjoner. Log4Shell er et saklig argument neste gang du er med i en diskusjon om man heller skal implementere mer funksjonalitet enn å oppdatere gamle biblioteker eller få på plass bedre testdekning.
Sånn finner du ut om du er ramma av Log4j-hullet, og sånn fikser du det
#3: Software bill of materials (SBOM)
Men hvordan vet man hvilke gamle biblioteker man skal oppdatere? Her kommer tredje lærdom fra Log4Shell: det er viktig å ha en oversikt over alle avhengighetene i programvaren din. Dette gjelder ikke bare direkte avhengigheter, det vil si bibliotekene du har lagt til selv, men også indirekte, det vil si bibliotekene som bibliotekene du har lagt til støtter seg på.
I den forbindelse er det også viktig å huske på at samme bibliotek kan være inkludert i programvaren gjennom flere komponenter, og til og med i forskjellige versjoner. Dette er særlig relevant for et loggrammverk som Apache Log4j, som har eksistert lenge og har blitt brukt i mange andre biblioteker.
En slik fullstendig oversikt, som ikke bare inneholder hvilke biblioteker som har blitt brukt, men også alle versjonsnumrene, kaller man gjerne en software bill of materials (SBOM). Men å ha en fullstendig oversikt er en sak, å kunne trekke riktig informasjon ut av den er en annen. Og enda bedre er det selvfølgelig om man kan stille en slik oversikt målrettede spørsmål. At oversikten må være levende og oppdatert (eller rask oppdaterbar) tar vi for gitt.
Dette kan vi lære av Log4j-hullet: - Beste måten å få til robust kode, er å lage enkel kode
#4: Container-scanning
Fjerde lærdom er at det er viktig å ha verktøy på plass som kan scanne alle komponenter som er i bruk i produksjonsmiljøet. Dette gjelder ikke bare komponentene du har brukt for å utvikle programvaren din, men også komponentene som programvaren din kjører på.
Selv om koden du har utviklet, bygget og rullet ut er til å stole på, kan det fremdeles være sårbarheter i containerne koden din kjører på. Her er det også viktig at man ikke bare scanner stacken idet man setter et system i produksjon, men scanner den om igjen etter hvert som det blir oppdaget nye sårbarheter.
Det hjelper lite at du har ryddet bort gamle versjoner av Apache Log4j fra programvaren din hvis Kubernetes-imaget fremdeles er sårbart for Log4Shell. Aqua Security, som Computas er partner med, er et eksempel på et verktøy som gjør en slik scanning. Selv har Aqua Security skrevet en liten bloggartikkel om Log4Shell, og hvordan deres produkt kan være behjelpelig med å beskytte seg mot eventuelle angrep.
- Naivt å tro at det ikke finnes norske datakriminelle
#5: Statisk kodeanalyse
Og til slutt, så er vår femte lærdom at statisk kodeanalyse er et helt nødvendig verktøy når man utvikler programvare. Denne gangen var man heldig at det fantes enkle, raske løsninger som WAF som kunne kjøpe nødvendig tid til å oppgradere Apache Log4j til nyeste versjon, men det vil ikke alltid og overalt være mulig.
Da er det viktig at man har verktøy tilgjengelig som kan gå inn i koden og finne hvor sårbare biblioteker har blitt brukt, ikke bare som avhengigheter, men også de faktiske kodekallene som man selv har lagt inn. Selv om man da sannsynligvis ikke kan gjøre noe med kallene utført i avhengigheter, kan man i hvert fall begrense og vurdere eget bruk av sårbare biblioteker.
I Computas har vi generelt hatt god erfaring med bruk av statisk kodeanalyse, og at vi anbefaler alle våre kunder å investere i verktøy som f.eks. SonarQube for å holde oversikt over kodekvalitet.
- Angriperne kommer inn, utforsker, ligger lavt, henter ut data, starter kryptering
Bonus: Open source var ikke problemet
Det er kanskje ikke helt en lærdom, men likevel verdt å nevne hva som ikke var problemet med Log4Shell. I begynnelsen av Log4Shell-hendelsen var det noen personer her og der som pekte på Java som grunnproblemet, eller bruk av open source-software. Det var selvfølgelig ikke problemet. Heller ikke Apache Log4j var problemet, selv om det var kasuset i dette tilfellet. Og man kan også si mye om vurderingen av å bygge inn JNDI-oppslag i et loggrammeverk, særlig i etterpåklokskapens lys.
Men også andre loggrammeverk, både i Java og andre programmeringsspråk, og rammeverk til andre formål generelt, har hatt og kommer til å ha sine sikkerhetsproblemer.
Det viktige er å være klar over at slike problemer kan bli oppdaget og utnyttet når som helst –også rett før juleferien–, og at man da må kunne reagere raskt. Å ha de riktige verktøyene, riktig arkitektur og riktig metodikk på plass er derfor alfa og omega for å kunne overleve i dagens IT-verden.