Távoli kódfuttatás az XStream segítségével

1. Áttekintés

Ebben az oktatóanyagban egy Távoli kódfuttatás támadást boncolgatunk az XStream XML sorosítási könyvtár ellen. Ez a kihasználás a megbízhatatlan deserializáció támadások kategóriája.

Megtudjuk, hogy az XStream mikor sérülékeny ez a támadás, hogyan működik a támadás, és hogyan lehet megakadályozni az ilyen támadásokat.

2. Az XStream alapjai

A támadás leírása előtt tekintsük át az XStream néhány alapját. Az XStream egy XML-szerializációs könyvtár, amely fordítást végez Java-típusok és XML között. Vegyünk egy egyszerűt Személy osztály:

public class Személy {private String first; privát húr utolsó; // szabványos mérőeszközök és beállítók}

Lássuk, hogyan tud az XStream írni néhányat Személy példány XML-be:

XStream xstream = új XStream (); Karakterlánc xml = xstream.toXML (személy);

Hasonlóképpen, az XStream be tudja olvasni az XML-t a Személy:

XStream xstream = új XStream (); xstream.alias ("személy", Személyosztály); Karakterlánc xml = "JohnSmith"; Személy személy = (Személy) xstream.fromXML (xml);

Mindkét esetben az XStream Java tükrözést használ a Személy gépeljen XML-be és onnan. A támadás az XML olvasása során történik. Az XML olvasásakor az XStream reflektálás segítségével példányosítja a Java osztályokat.

Az XStream példányok osztályait az általa elemzett XML elemek neve határozza meg.

Mivel az XStream-et úgy konfiguráltuk, hogy tisztában legyen a Személy típusú, az XStream egy újat példányosít Személy amikor a „személy” nevű XML elemeket elemzi.

A felhasználó által definiált típusok mellett, mint a Személy, Az XStream a dobozból felismeri az alapvető Java típusokat. Például az XStream képes olvasni a Térkép XML-ből:

Karakterlánc xml = "" + "" + "" + "foo" + "10" + "" + ""; XStream xStream = új XStream (); Térképtérkép ((Térkép) xStream.fromXML (xml); 

Meglátjuk, hogy az XStream azon képessége, hogy olvassa el az alapvető Java típusokat képviselő XML-t, hasznos lesz a távoli kódfuttatás kihasználásában.

3. Hogyan működik a támadás

Távoli kódfuttatási támadások akkor fordulnak elő, amikor a támadók bemenetet nyújtanak, amelyet végül kódként értelmeznek. Ebben az esetben a támadók kihasználják az XStream deserializációs stratégiáját azáltal, hogy a támadási kódot XML-ként adják meg.

Az osztályok megfelelő összetételével az XStream végül a Java reflexión keresztül futtatja a támadókódot.

Készítsünk egy példa támadást.

3.1. Tartalmazza a támadási kódot a ProcessBuilder

Támadásunk célja egy új asztali számológép-folyamat elindítása. A macOS-on ez az „/Applications/Calculator.app”. Windows rendszeren ez a „calc.exe”. Ehhez becsapjuk az XStream-et egy új folyamat futtatására a ProcessBuilder. Az új folyamat elindításához hívja fel a Java kódot:

új ProcessBuilder (). parancs ("végrehajtható név-itt"). start ();

Az XML olvasásakor az XStream csak konstruktorokat hív meg és mezőket állít be. Ezért a támadónak nincs közvetlen módja a ProcessBuilder.start () módszer.

Az okos támadók azonban az osztályok megfelelő összetételét használhatják a ProcessBuilder’S Rajt() módszer.

Dinis Cruz biztonsági kutató blogbejegyzésében megmutatja nekünk, hogyan használják Hasonló felület a támadási kód meghívására a rendezett gyűjtemény másolat-készítőjében TreeSet. Itt foglaljuk össze a megközelítést.

3.2. Hozzon létre egy Hasonló Dinamikus proxy

Ne feledje, hogy a támadónak létre kell hoznia a ProcessBuilder és hivatkozni annak Rajt() módszer. Ennek érdekében létrehozunk egy példányt Hasonló akinek hasonlítsa össze módszer a ProcessBuilder’S Rajt() módszer.

Szerencsére a Java Dynamic Proxies lehetővé teszi számunkra, hogy létrehozzunk egy példányt Hasonló dinamikusan.

Továbbá a Java Eseménykezelő osztály konfigurálható módon biztosítja a támadót InvocationHandler végrehajtás. A támadó konfigurálja a Eseménykezelő hogy felhívja a ProcessBuilder’S Rajt() módszer.

Ezeket az összetevőket összerakva XStream XML ábrázolással rendelkezünk a Hasonló meghatalmazott:

 java.lang.Hasonlítható nyitott /Applications/Calculator.app start 

3.3. Kényszerítsen egy összehasonlítást a Hasonló Dinamikus proxy

Kényszeríteni az összehasonlítást a mi Hasonló proxy, rendezünk egy válogatott gyűjteményt. Építsünk egy TreeSet a kettőt összehasonlító gyűjtemény Hasonló példányok: a Húr és a meghatalmazottunk.

Majd használjuk TreeSetMásolat készítője ennek a gyűjteménynek a felépítéséhez. Végül megvan az XStream XML reprezentációja egy újhoz TreeSet amely tartalmazza a meghatalmazónkat és a Húr:

 foo java.lang.Hasonlítható nyitott /Applications/Calculator.app start 

Végül a támadás akkor következik be, amikor az XStream elolvassa ezt az XML-t. Míg a fejlesztő arra számít, hogy az XStream elolvassa a Személy, ehelyett végrehajtja a támadást:

String sortedSortAttack = // XML felülről XStream xstream = new XStream (); Személy személy = (Személy) xstream.fromXML (sortedSortAttack);

3.4. Támadás összefoglalása

Összefoglaljuk azokat a reflektív hívásokat, amelyeket az XStream akkor hajt végre, amikor deszerializálja ezt az XML-t

  1. Az XStream meghívja a TreeSet másoló konstruktor a Gyűjtemény tartalmazó a Húr „Foo” és a mi Hasonló meghatalmazott.
  2. A TreeSet konstruktor hívja a mi Hasonló meghatalmazottak összehasonlítani módszerrel, hogy meghatározzuk az elemek sorrendjét a rendezett halmazban.
  3. A mi Hasonló dinamikus proxy az összes metódushívást delegálja a Eseménykezelő.
  4. A Eseménykezelő konfigurálva van a Rajt() módszere ProcessBuilder alkot.
  5. A ProcessBuilder új folyamatot forszíroz a támadó által végrehajtani kívánt parancs futtatásával.

4. Mikor sérülékeny az XStream?

Az XStream sebezhető lehet a távoli kódfuttatási támadással szemben, ha a támadó ellenőrzi az általa olvasott XML-t.

Vegyünk például egy REST API-t, amely elfogadja az XML bemenetet. Ha ez a REST API az XStream használatával olvassa el az XML kéréstesteket, akkor kiszolgáltatott lehet egy távoli kódfuttatási támadásnak, mert a támadók ellenőrzik az API-nak küldött XML tartalmát.

Másrészt egy olyan alkalmazás, amely csak az XStream-et használja a megbízható XML olvasására, sokkal kisebb támadási felülettel rendelkezik.

Vegyünk például egy olyan alkalmazást, amely csak az XStream szolgáltatást használja az alkalmazás rendszergazdája által beállított XML konfigurációs fájlok olvasására. Ez az alkalmazás nincs kitéve az XStream távoli kódfuttatásának, mert a támadók nem ellenőrzik az alkalmazás által olvasott XML-t (az adminisztrátor).

5. Az XStream keményítése távoli kódfuttatási támadások ellen

Szerencsére az XStream bevezetett egy biztonsági keretet az 1.4.7 verzióban. A biztonsági keretrendszer segítségével megnehezíthetjük példánkat a távoli kódfuttatási támadásokkal szemben. A biztonsági keretrendszer lehetővé teszi számunkra, hogy az XStream-t olyan típusú engedélyezőlistával állítsuk be, amelyet példányosítani lehet.

Ez a lista csak az alaptípusokat és a mi elemeket tartalmazza Személy osztály:

XStream xstream = új XStream (); xstream.addPermission (NoTypePermission.NONE); xstream.addPermission (NullPermission.NULL); xstream.addPermission (PrimitiveTypePermission.PRIMITIVES); xstream.allowTypes (új osztály [] {Személy.osztály});

Ezenkívül az XStream felhasználói fontolóra vehetik a rendszerek keményítését egy futásidejű alkalmazás önvédelmi (RASP) ügynökkel. A RASP-ügynökök futási időben bytecode műszereket használnak a támadások automatikus észlelésére és blokkolására. Ez a technika kevésbé hibára hajlamos, mint manuálisan elkészíteni a típusok engedélyezési listáját.

6. Következtetés

Ebben a cikkben megtudtuk, hogyan lehet távoli kódfuttatási támadást végrehajtani egy olyan alkalmazással, amely az XStream használatával olvassa el az XML-t. Mivel az ilyen támadások léteznek, az XStream-et meg kell keményíteni, amikor nem megbízható forrásokból olvassa el az XML-t.

A kihasználás azért létezik, mert az XStream reflektálást használ a támadó XML által azonosított Java osztályainak példányosítására.

Mint mindig, a példák kódja a GitHub oldalon található.