lördag 31 juli 2010

Remote execution på WebSphere

Ed Schaller höll en intressant presentation om remote execution på IBM WebSphere (WAS).

WAS frontas typiskt av en webbserver såsom Apache eller IIS. Webbservern används för lastbalasering och felhantering. Den kommunicerar i sin tur med WAS via en webbserver-plugin över http. Men inte alla request skickas vidare.

Webservern utgår från url-mappnignar i web.xml och ibm-web-ext.xmi. Om en match hittas så skickas requestet vidare, annars hanteras det av webbservern själv.

JSP:er och null
WAS och andra applikationsservrar översätter jsp till Java, kompilerar och kör det som en servlet. Det fungerar normalt även runtime och jsp:er komplieras först när de efterfrågas.

Det gör att webbservern alltid skickar jsp-request vidare eftersom appservern måste få en chans att kolla om den finns och kompilera den.

Så hur tolkas null i den här översättningen från jsp till Java till bytekod? Jo, det visar sig att WAS accepterar null men i accessen till det underliggande filsystemet så termineras strängen vid null. På det viset kan man fejka att man vill nå en jsp men i själva verket peka ut en annan fil. Så här:

ctxroot/path_till_filen%00.jsp

Det kommer läsa upp den fil attackeraren har anget så länge den finns i den exploderade war:en. Det måste dessutom vara en korrekt jsp. Jobbigt? Nja, i princip allt som inte innehåller <% är en korrekt jsp. T ex textfiler, html, xml, de flesta zip-filer och så vidare. Intressant nog visare det sig att om attackeraren anger en katalog istället för en fil så får han/hon en kataloglistning. Så här:

ctxroot/dir/%00.jsp
ctxroot/.%00.jsp (extra punkt för att komma åt kontextroten)

Web Server Plugin
OK, null gick bra att att skicka till WAS:en men hur går det med den framförliggande webbservern? Pluginen är skriven i C och terminerar därför vid null, dvs text.txt.jsp blir text.txt. Tillbaka på ruta null så att säga.

Men vi kanske kan lura webbservern med teckenkodning? Java lagrar strängar i UTF-16 internt men tolkar inkommande strängar som UTF-8. Men web server-pluginen förstår inte lång UTF-8. Därtill har IBMs jvm haft en allvarlig bugg i hantering av så kallad overly long UTF-8 som är fixad i de senaste patcharna. På det viset kan man injicera UTF-8 som webbserver-pluginen inte förstår och som jvm:en sen misstolkar som null. Tecknet är %C0%80 vilket tolkas som ASCII null.

Med dubbelpunkt kan man dessutom komma åt WEB-INF-katalogen och kodningen för dubbelpunkt i UTF-8 är %C0%AE. Totalt sett så här:

ctxroot/%C0%AE/WEB-INF/web.xml%C0%80.jsp

… för att komma åt web.xml.

Axis och bilagor
Men attackeraren vill inte bara läsa filer utan också få till remote execution. Så han/hon måste få in en jsp-fil i den exploderade war:en. Här vänder vi oss till det populära Axis-ramverket för web services.

Man kan nämligen ha bilagor (attachments) i sin SOAP. Om man lägger bilagan före SOAP:en och dessutom refererar den i SOAP:en, t ex med en href, så kommer Axis ladda bilagan som fil och cache:a den … i war:en!

Men då måste attackeraren kunna kommunicera med en web service väl? Nej. Web services tillåter att klienten skickar ett SOAP Fault det första den gör. Och då kommer Axis hantera det oavsett om det finns någon web service som det kan ha gått fel i. SOAP Fault är kodade på samma sätt som vanlig SOAP så tricket med bilagan funkar bra.

Bilagan rensas av cache-hanteraren så det uppstår en så kallad race condition där attackeraren måste hinna använda den uppladdade jsp:n innan den tas bort.

Allt det här demade Ed på plats. Japp, skal med användaren wasadmin blev det.

Fix?
Alla moderna versioner av WebSphere (6 och framåt) har så kallade fixpack för det här problemet. Ed har varit noga med att rapportera det på rätt sätt. Coolast var att IBM ordnade en patch på två veckor för alla de 60 varianter som var sårbara. Det är respekt.

Men om man kör en opatchad WebSphere så är man alltså sårbar.

Ed tyckte också man skulle överväga att stänga av runtime-kompilering och omladdning av jsp:er (disableJspRuntimeCompilation).

Inga kommentarer: