Fjernkørsel af kode (RCE), forklaret: hvad det er, og hvordan man forhindrer det

fjernkørsel af kode (RCE) er en klasse af sikkerhedsfejl/sårbarheder. RCE-sårbarheder giver en ondsindet aktør mulighed for at udføre enhver kode efter eget valg på en fjernmaskine via LAN, van eller internet. RCE tilhører den bredere klasse af sårbarheder ved udførelse af vilkårlig kode (ACE). Da internettet bliver allestedsnærværende, vokser RCE-sårbarhedernes indvirkning hurtigt. Så, RCEs er nu nok den vigtigste form for ACE sårbarhed.

da det er tilfældet, ønskede vi at se nærmere på de forskellige typer RCE-sårbarheder og de mulige modforanstaltninger.

RCE-klassificering efter oprindelse

de fleste, hvis ikke alle, af de kendte RCE-sårbarheder har et lille antal underliggende årsager.

dynamisk kodekørsel

dynamisk kodekørsel har tendens til at være den mest almindelige angrebsvektor, der fører til RCE. De fleste programmeringssprog har en eller anden måde at generere kode med kode og udføre den på stedet. Dette er et meget kraftfuldt koncept, der hjælper med at løse mange komplekse problemer. En ondsindet tredjepart kan dog let misbruge den for at få RCE-muligheder.

ofte er koden genereret ved runtime baseret på nogle brugerinput. Oftere end ikke, koden indeholder dette input i en eller anden form. En ondsindet skuespiller, der indser, at den dynamiske kodegenerering vil gøre brug af et givet input, kunne give gyldig kode som et input til at angribe din applikation. Hvis brugerindgangene ikke er undersøgt, udføres denne kode på målmaskinen.

stort set forårsager dynamisk kodekørsel to hovedklasser af RCE-sårbarheder: direkte og indirekte.

direkte

i tilfælde af direkte dynamisk kodekørsel er den ondsindede skuespiller opmærksom på, at deres input vil blive brugt i kodegenerering.

indirekte

en indirekte sag koger igen ned til dynamisk kodegenerering inklusive brugerindgange. Brugerinputtet passerer imidlertid gennem et eller flere lag. Nogle af lagene kan endda omdanne det input, før det ender med dynamisk kodegenerering. Dynamisk kodegenerering kan også være en bivirkning og ikke den primære brug af input. Som sådan er det ikke rigtig tydeligt for brugeren, der leverer input, at input vil blive brugt som en byggesten i et kodestykke, der skal udføres på en fjernmaskine.

deserialisering

deserialisering er et meget godt eksempel på dette scenario. Tilsyneladende bør ingen dynamisk kodegenerering ske ved deserialisering. Det er faktisk tilfældet, når det serialiserede objekt kun indeholder datafelter af primitive typer eller andre objekter af den art. Ting bliver dog mere komplicerede, når metoder/funktioner af et objekt serialiseres. Deserialisering vil derefter normalt omfatte en form for dynamisk kodegenerering.

du tror måske, at dynamiske sprog er det eneste sted, hvor funktionsserialisering giver mening. Problemet vil da være af begrænset omfang. Men det er også et nyttigt scenario på statiske sprog. Det er noget sværere at opnå på et statisk sprog, men langt ikke umuligt.

implementeringen består ofte af deserialiseringsgenererede fuldmagtsobjekter/funktioner. Generering af objekter / funktioner ved kørsel er et tilfælde af dynamisk kodegenerering. Så hvis de data, der skal deserialiseres, stammer fra en anmodning fra en fjernmaskine, kunne en ondsindet skuespiller ændre dem. Omhyggeligt udformede serialiserede kodestykker kan injiceres, der narrer den dynamiske kodegenerering til at udføre dem, når de påberåbes som en del af deserialiseringen.

Hukommelsessikkerhed

en anden årsag til RCE-sårbarheder har at gøre med hukommelsessikkerhed. Hukommelsessikkerhed betyder at forhindre kode i at få adgang til dele af hukommelsen, som den ikke initialiserede eller fik som input. Intuitivt kan du forvente, at manglende hukommelsessikkerhed resulterer i uautoriseret dataadgang. Operativsystemet og det underliggende udstyr bruger dog hukommelse til at gemme den faktiske eksekverbare kode. Metadata om kodekørsel gemmes også i hukommelsen. At få adgang til denne form for hukommelse kan resultere i ACE og muligvis RCE. Så hvad er hovedårsagerne til hukommelsessikkerhedsproblemer?

designfejl i programmel

designfejl i Programmel er en type hukommelsessikkerhedssårbarhed, hvor der er en designfejl i en underliggende komponent. Oftere end ikke, det ville være en compiler, tolk, eller virtuel maskine, eller potentielt operativsystemet kerne eller biblioteker. Der er en række forskellige fejl, der tilhører denne klasse. Vi vil tage et mere detaljeret kig på, hvad der uden tvivl er den mest almindelige.

bufferoverløb eller bufferoverlæsning

bufferoverløb (også kendt som bufferoverlæsning) er en forholdsvis enkel og velkendt teknik til at krænke hukommelsessikkerheden. Det udnytter en designfejl eller en fejl til at skrive til hukommelsescellerne, der følger den faktiske ende af en hukommelsesbuffer. Bufferen selv bliver returneret fra et legitimt opkald til offentlig API. Bufferen fungerer dog kun som et oprindelsessted til at beregne de fysiske hukommelsesadresser for private felt – /medlemsværdier for et objekt eller en programtæller. Deres relative position til bufferen er enten velkendt eller kan gættes. Undersøgelse af koden, hvis den er tilgængelig eller fejlfinding af programudførelsen ved kørsel, kan hjælpe en ondsindet skuespiller med at få relative positioner.

så et bufferoverløb giver mulighed for at ændre hukommelse, der skal være utilgængelig ved design. Denne buffer kan opholde sig i adresserummet på en anden maskine og ændres ved at kalde en ekstern API. Det giver adgang til fjernmaskinens hukommelse. Det er klart, at der er forskellige måder at bruge denne type adgang til instrumentering af en RCE. Den generelle antagelse er, at hvis der findes en bufferoverløbssårbarhed, så er en RCE mulig. Så, kode ejere bør fastsætte bufferoverløb ASAP, godt før den faktiske RCE angreb opstår.

Scope

oftere end ikke målretter bufferoverløb C/C++ – kode, da disse sprog ikke har indbygget bufferstørrelseskontrol. En masse andre populære rammer og teknologier ender med at bruge C/C++ biblioteker dybt nede under overfladen, der automatisk gør dem sårbare over for denne form for angreb.

knude.js er et godt eksempel på dette, da JavaScript-runtime ud over at være baseret på C/C++ også giver mulighed for native C/C++ – tilføjelser. På grund af dette kan en angriber omhyggeligt udforme anmodningerne til en Node.JS server til at forårsage bufferoverløb og dermed ændre systemhukommelsen på den berørte maskine, hvilket forårsager udførelse af vilkårlig kode.

konstruktionsfejl

interessant nok kan brud på hukommelsessikkerheden også forekomme på grund af konstruktionsfejl i udstyrets sikkerhed. Selvom det er mindre almindeligt og sværere at finde, har sådanne sårbarheder normalt en ekstremt stor indflydelse.

afbøjning af RCE-angreb

mens resultatet af hvert RCE-angreb er det samme med hensyn til en angriber, der udfører kode, er angrebsvektorerne meget forskellige. Blokering af dem alle kræver en betydelig indsats. Desuden vokser indsatsen sammen med teknologistakken. Alle angrebsvektorer beskrevet i dette indlæg er teknologi-agnostiske. Alle implementeringer er dog teknologispecifikke, og det samme er forsvarsmekanismerne.

så en traditionel tidsbesparende tilgang er at overvåge netværkstrafik for mistænkeligt indhold i stedet for at overvåge hvert slutpunkt med sin specifikke teknologi. En internetapplikation udfører typisk dette job. Selvom det sparer tid, kommer det også til en pris—vaflen er en netværksydelsesflaskehals, og den mangler al den baggrundsinformation, der er tilgængelig på det faktiske slutpunkt eller på applikations-og brugerniveauer. Derfor kunne trafikanalyse aldrig være perfekt. Heuristik er uundgåelig uden fulde data, så enten ikke alle trusler vil dukke op, eller falske positive vil opstå, eller oftest begge dele.

flytning inde i app: 8639>

vi løser disse mangler uden at øge udviklingsomkostningerne for slutbrugeren ved at flytte synligheden inde i applikationen, hvilket giver mere komplet beskyttelse med en teknologispecifik RASP og In-App-skive. Vi kører inden for den faktiske internetapplikation, API eller microservice, der modtager netværkstrafik. Det kræver dog ingen kodeændring. Det bruger instrumenteringspunkter, der er specifikke for hver teknologi (f.eks.js osv.) for at ændre kode før udførelse på runtime. Således er det i stand til at overvåge og ændre system-og netværkshændelser, mens de har den fulde kontekst af alt, hvad der sker inde i applikationen.

Således kan vi registrere, at appen bruger komponenter med kendte hukommelsessikkerhedsproblemer. Det kan også registrere de faktiske brugerindgange, der gør det til de dynamiske kodeudførelseshændelser. Naturligvis er dette en overlegen tilgang til at opdage og forhindre RCEs sammenlignet med en traditionel VAF, der kun har adgang til netværkstrafik.

indpakning

det er klart, at RCE er en meget potent angrebsvektor. Men heldigvis er det også muligt at forsvare dig mod RCE-angreb. Oplysningerne ovenfor kan virkelig hjælpe med at opbygge din forsvarsstrategi. Hvis du er interesseret i andre angrebsvektorer og detaljer, skal du tjekke vores tidligere indlæg på og LFI.

Leave a Reply