fredag 13 november 2009

Java Enterprise Rootkits

Allvarligt talat så vill jag inte skriva det här blogginlägget. Jeff Williams presentation om Java-rootkits fick mig nämligen att må dåligt. Om du inte riktigt har koll på vem som utvecklar dina applikationer (eller alla open source-bibliotek ni använder) så kommer du också må dåligt.

Vad kan en elak Javautvecklare åstadkomma på en vecka? Vad kan han/hon smyga in i koden? Det frågade sig Jeff och ägnade en vecka åt att göra rootkits i Java. De presenterar det i en 40-sidig rapport med tillhörande Eclipse-projekt (zip) men här kommer några godbitar.

Vad är ett rootkit?
Rootkits är gömda bakdörrar. Att bara göra en bakdörr i Java är inte svårt (servlet som lyssnar dina instruktioner). Att gömma dem är utmaningen.

Default: Ingen Security Manager
De flesta bakdörrar stoppas av en konfigurerad Security Manager. Men eftersom ingen kör med en Security Manager (avstängd som default i Tomcat, Websphere ...) så får all egenutvecklad kod göra vad som helst på maskinen. Alltså kommer rootkit-koden fungera bra i produktion.

Hur gömmer vi kod?
Det finns flera sätt att gömma sin bakdörr. Grundtricket är att göra data till bytekod i JVM:en. Så vi behöver bara kunna gömma data och några kodrader som omvandlar vår data till kod.

Lämpliga ställen för att gömma data är i en byte-array någonstans, i en åsidosatt toString()-metod som returnerar vår kod som en sträng, eller i databasen för att sen fiska upp den med SQL.

Skapa bytekod
För att skapa bytekod ur data så skriver vi ner den direkt på på class path:en och kör den, ungefär så här:

new File(getDirOnClasspath(), "Attack.class");
Class.forName("Attack").newInstance();

Vi kan också kompilera direkt i koden eftersom kompilatorn är tillgänglig i JDKn:

ToolProvider.getSystemJavaCompiler();

Om produktionssytemet körs på en JRE utan kompilator så finns alltid JSP-kompilatorn.

Eller så skapa vi en ny klassladdare (new ClassLoader()) åsidosätter defineClass() i den och skickar in vår Base64-kodade bytearray och den laddas och exekveras.

Lura kodgranskaren
Vi kan behöva lura kodgranskaren så han/hon inte förstår vad vi gör. Det görs bäst med förvillande kodkommentarer och genom att skriva svår kod med inspiration från javapuzzlers.com.

En riktigt elak grej är att skapa enhetstester som körs på byggservern och där injicerar skadlig kod. Vem kodgranskar enhetstesterna?

Andra slimmade bakdörrar
Som alternativ till data-till-bytekod så kan vi införa ett vanligt servletfilter som åsidosätter isUserInRole och kollar ifall en förvald parameter (typ 'backdoor') finns i requestet. Om den förvalda parametern finns så returnerar isUserInRole sant. Visst vi får lägga till det i web.xml men vem kommer hitta det?

I Servlet 3.0-API:et kan man dessutom lägga till och ta bort servlets och filter programmatiskt, dvs utan att ändra i web.xml.

Eller mygla in din skadliga jar i ext-katalogen så hamnar du direkt på classpath:en

Rootkits i open source
Tänk er nu att någon lägger en trojan i Log4J. Kanske inte ens i källkoden utan genom att ändra direkt i klassfilen/jaren som du laddar hem. Hur många skulle åka dit på den? Typ alla större Javasystem i världen.

Några andra mjukvaror som du kanske använder bygger på mycket öppen källkod:
  • Hudson core innehåller 103 open source-projekt
  • Maven core innehåller 15 open source-projekt
  • Subversion innehåller 3 open source-projekt
Vad göra åt det?
Det som får mig att må dåligt över allt det här är att jag inte riktigt vet vad vi ska göra åt det. Jeff och Bruce Schneier har tillsammans skrivit ihop råd till den som är orolig:
  • Begränsa antalet utvecklare
  • Se till att du har pålitliga utvecklare
  • Begränsa vilken kod du litar på (begränsa vilka api:er som får användas, t ex inte reflection)
  • Begränsa beroenden under byggprocessen (kör vanliga javac istället för magiska saker som Maven när du bygger release)
  • Begränsa antalet personer du är beroende av i produktion/drift
  • Leta aktivt efter skadlig kod
Listan ovan får mig bara att tänka -- "Det kommer aldrig hända.". Så vi får väl lugnt vänta på de första avslöjandena om stora, hemska rootkits istället. :(

Inga kommentarer: