Hvordan hacke en uopprettet Exchange-server med useriøs PowerShell-kode

Kilde node: 1760191

For knappe to måneder siden kom noen bekymringsfulle feilnyheter: et par nulldagssårbarheter ble annonsert i Microsoft Exchange.

Som vi anbefalt den gang, disse sårbarhetene, offisielt utpekt CVE-2022-41040 og CVE-2022-41082:

[var] to null-dager som [kunne] være lenket sammen, med den første feilen brukt eksternt for å åpne nok av et hull til å utløse den andre feilen, som potensielt tillater ekstern kjøring av kode (RCE) på selve Exchange-serveren.

Den første sårbarheten minnet om den plagsomme og mye misbrukte ProxyShell sikkerhetshull fra tilbake i august 2021, fordi den var avhengig av farlig oppførsel i Exchanges Autodiscover-funksjon, beskrevet av Microsoft som en protokoll altså "brukes av Outlook- og EAS [Exchange ActiveSync]-klienter for å finne og koble til postbokser i Exchange".

Heldigvis var Autodiscover-feilfunksjonen som kunne utnyttes i ProxyShell-angrepet av enhver ekstern bruker, enten pålogget eller ikke, lappet for mer enn ett år siden.

Dessverre gjorde ikke ProxyShell-oppdateringene nok for å stenge utnyttelsen for autentiserte brukere, noe som førte til den nye CVE-2022-40140 zero-day, som snart var lakonisk, om enn misvisende, dubbet ProxyNotShell.

Ikke like farlig, men farlig likevel

Det er klart at ProxyNotShell ikke var på langt nær så farlig som den originale ProxyShell, gitt at den krevde det som er kjent som autentisert tilgang, så den var ikke åpen for misbruk av hvem som helst fra hvor som helst.

Men det viste seg raskt at på mange Exchange-servere ville det være nok å vite hvilken som helst brukers påloggingsnavn og passord til å passere som autentisert og starte dette angrepet, selv om den brukeren selv måtte bruke tofaktorautentisering (2FA) for å logge på riktig for å få tilgang e-posten deres.

Som Sophos-ekspert Chester Wisniewski sett det den gangen:

Det er en "midt-autentiseringssårbarhet", hvis du vil kalle det det. Det er en blandet velsignelse. Det betyr at et automatisert Python-skript ikke bare kan skanne hele internett og potensielt utnytte alle Exchange-servere i verden i løpet av minutter eller timer, slik vi så skje med ProxyLogon og ProxyShell i 2021. […]

Du trenger et passord, men å finne én e-postadresse og passordkombinasjon som er gyldig på en gitt Exchange-server er sannsynligvis ikke så vanskelig, dessverre. Og du har kanskje ikke blitt utnyttet til dags dato, fordi for å lykkes med å logge på Outlook Web Access [OWA] krever FIDO-tokenet deres, eller deres autentisering, eller den andre faktoren du måtte bruke.

Men dette angrepet krever ikke den andre faktoren. […] Bare det å anskaffe en kombinasjon av brukernavn og passord er en ganske lav barriere.

Som du sikkert husker, antok (eller i det minste håpet) mange av oss at Microsoft ville skynde seg for å få en løsning for ProxyNotShell-hullene, gitt at det fortsatt var to uker til oktobers patch tirsdag.

Men vi var skuffet over å finne at en pålitelig løsning tilsynelatende var mer kompleks enn forventet, og oktober kom og gikk med ProxyNotShell adressert kun av løsninger, ikke av riktige patcher.

Selv Novembers Patch Tuesday ga ikke direkte de nødvendige rettelsene, selv om oppdateringene kom likevel ut samme dag som en del av en Exchange-spesifikk sikkerhetsoppdatering som kan hentes og installeres separat:

Proof-of-concept avslørt

Nå som støvet har lagt seg og alle har hatt tid til å lappe Exchange-serverne sine (de de ikke har glemt, i det minste), forskere ved Zero Day Initiative (ZDI), som disse sårbarhetene opprinnelig ble avslørt for å sendes til Microsoft, har forklart hvordan feilene kan utnyttes.

Den dårlige nyheten, avhengig av din mening om åpenbare utnyttelsesavsløringer, er at ZDI-teamet nå effektivt har levert et proof-of-concept (PoC) som forklarer hvordan man angriper Exchange-servere.

Den gode nyheten er selvfølgelig at:

  • Vi kan nå studere og forstå feilene selv. Dette hjelper oss ikke bare alle til å sikre at de generelle forholdsreglene vi har tatt (ikke bare begrenset til patching) sannsynligvis vil gi den beskyttelsen vi forventer, men informerer oss også om programmeringspraksis som vi ønsker å unngå i fremtiden, så vi ikke ikke bli fanget i å åpne opp feil av denne typen i vår egen serversidekode.
  • Vi har nå ingen unnskyldninger for ikke å bruke lappene. Hvis vi har latt være å oppdatere, gjør ZDIs forklaring på hvorfor angrepet virker det klart at kuren definitivt er å foretrekke fremfor sykdommen.

Hvordan fungerer det

ZDI-er forklaring av denne sårbarheten gir en fascinerende historie om hvor komplisert det kan være å lenke sammen alle delene du trenger for å gjøre en sårbarhet til en levedyktig utnyttelse.

Det er også verdt å lese for å hjelpe deg med å forstå hvorfor graving i en eksisterende utnyttelse kan bidra til å avsløre andre måter som en sårbarhet kan misbrukes, potensielt føre til flere oppdateringer, oppfordre til konfigurasjonsendringer og fremme ny programmeringspraksis som kanskje ikke var åpenbar bare fra å fikse det originale hullet.

Forklaringen er nødvendigvis komplisert og ganske teknisk, og leder deg videre gjennom en lang rekke trinn for å oppnå ekstern kjøring av kode (RCE) på slutten.

I håp om å hjelpe deg med å følge detaljene på høyt nivå lettere hvis du bestemmer deg for å lese ZDI-rapporten, er her et forhåpentligvis-ikke-for-forenklet sammendrag med trinnene som er oppført i motsatt rekkefølge...

…så du vil vite på forhånd hvorfor historien tar retningen den gjør:

  • TRINN 4. Lur Exchange eksternt til å instansiere et .NET-objekt etter eget valg, med en initialiseringsparameter etter eget valg.

I moderne koding, en instansiert objekt er sjargongordet for en tildelt minneklump, initialisert automatisk med dataene og ressursene den trenger mens den er i bruk, og knyttet til et spesifikt sett med funksjoner som kan operere på det. (Instantier er bare et fancy ord for skape.)

Objekter kan administreres og kontrolleres av selve operativsystemet, for å hjelpe til med å unngå den typen minnefeilhåndtering som er vanlig i et språk som C, hvor du vanligvis trenger å tildele minne selv, fylle opp de relevante datafeltene for hånd, og husk å frigjør minnet og ressursene du bruker, for eksempel nettverkskontakter eller diskfiler, når du er ferdig.

Objekter har generelt en programmatisk funksjon knyttet til dem kalt a konstruktør, som kjøres automatisk når et nytt objekt opprettes for å allokere riktig mengde minne og riktig sett med systemressurser.

Vanligvis må du sende en eller flere parametere som argumenter til konstruktøren, for å angi hvordan du vil at objektet skal konfigureres når det starter.

Enkelt sagt, hvis du instansierer, for eksempel, en TextString objekt (vi lager disse navnene, men du skjønner) ved å bruke en parameter som i seg selv er en tekststreng som f.eks. example.com:8888...

...du vil sannsynligvis ende opp med en minnebuffer tildelt for å holde teksten din, initialisert slik at den har samme verdi som du sendte inn, nemlig råteksten example.com:8888.

I den sammenhengen utgjør ikke tekststrengen som sendes inn som data til objektkonstruktøren umiddelbart noen åpenbar cybersikkerhetstrussel når du utløser konstruktøren eksternt, annet enn en mulig tjenestenekt (DoS) ved gjentatte ganger å be om større og større strenger for å prøv å tømme minnet.

Men hvis du skulle instansiere, si, en ConnectedTCPClient objekt som bruker den samme tekststrengparameteren til example.com:8888, kan du ende opp med en minnebuffer klar til å holde midlertidige data, sammen med en nettverkskontakt tildelt av operativsystemet som er klar til å utveksle data med serveren example.com over TCP-porten 8888.

Du kan se risikoen for ekstern kjøring av kode der, selv om du aldri får sendt noen data til den åpne kontakten, gitt at du har lurt serveren til å ringe hjem til et sted du kontrollerer.

Du kan til og med finne en gjenstand som heter for eksempel RunCmdAndReadOutput, hvor tekststrengen du sender som en parameter, bokstavelig talt, er en kommando du vil kjøre automatisk så snart objektet er opprettet, slik at du kan samle ut det senere.

Selv om du aldri får gjenopprettet utdataene fra kommandoen, vil bare instansiering av et slikt objekt likevel la deg velge en kommando som skal kjøres, og dermed gi deg generisk ekstern kjøring av kode og utgjøre en risiko begrenset bare av tilgangsrettighetene til selve serverprosessen .

Selvfølgelig er angrepet bare så enkelt når du kommer til det siste stadiet, noe du ikke skal kunne gjøre, fordi Exchange har en streng tillatelsesliste som hindrer deg i å velge et hvilket som helst gammelt objekt å instansiere.

I teorien kan bare trygge objekter eller objekter med lav risiko opprettes eksternt via PowerShell, slik at instansiering av vår imaginære TextString ovenfor, eller a SimpleIntegerValue, kan anses som akseptabelt, mens en ConnectedTCPClient eller en RunCmdAndReadOutput ville definitivt ikke vært det.

Men ZDI-forskerne legger merke til at før de utløste det siste trinnet, kunne de gjøre dette:

  • TRINN 3. Lure Exchange eksternt til å tro at et lavrisikoobjekt som har bestått sikkerhetstesten, faktisk er et annet objekt du velger.

Likevel kan du forvente at Exchange forhindrer ekstern opprettelse selv av lavrisikoobjekter, for å minimere trusselen ytterligere.

Men forskerne fant ut at de kunne:

  • TRINN 2. Fjernlure Exchange til å bruke sin Fjernstyring av PowerShell funksjon for å lage et objekt basert på initialiseringsparametere kontrollert eksternt.

Og det var mulig på grunn av det ProxyShell-lignende hullet som bare var delvis lappet:

  • TRINN 1. Lur Exchange eksternt til å godta og behandle en nettforespørsel med kode ved å pakke en gyldig username:password feltet i forespørselen også.

Selv om brukeren som er navngitt i forespørselen faktisk ikke var pålogget, og måtte gå gjennom en slags 2FA-prosess for å få tilgang til sin egen postkasse, kan en angriper som kjente deres username:password kombinasjon ville ha nok autentiseringsinformasjon til å lure Exchange til å godta en nettforbindelse som kan brukes til å starte angrepskjeden beskrevet i trinn 2 til 4 ovenfor.

Løst sett, noen gyldig username:password kombinasjon ville gjøre det, gitt at "autentiseringen" var nødvendig ganske enkelt for å forhindre Exchange fra å avvise HTTP-forespørselen på forhånd.

Hva gjør jeg?

Merk at dette angrepet bare fungerer:

  • Hvis du har lokale Exchange-servere. Microsoft hevder å ha låst ned sine egne skytjenester raskt, så Exchange Online er ikke berørt. Vær sikker på at du vet hvor Exchange-serverne dine er. Selv om du nå bruker Exchange Online, kan det hende du fortsatt kjører lokale servere, kanskje til overs ved en feiltakelse fra migreringsprosessen.
  • Hvis serverne dine ikke er oppdatering. Pass på at du har brukte Exchange Software Update fra 2022-11-08 til lukke av sårbarhetene som utnyttelsen krever.
  • Hvis serverne dine fortsatt godtar grunnleggende autentisering, også kjent som eldre autentisering. Pass på at du har blokkerte alle aspekter av eldre autentisering slik at serverne dine ikke godtar username:password overskrifter nevnt ovenfor, og aksepterer ikke risikable Autodiscover-protokollforespørsler i utgangspunktet. Dette stopper angripere lure en server til å godta triksene deres for instansiering av booby-fangede objekter, selv om den serveren ikke er lappet.

Du kan holde styr på av våre offisielle råd om forebygging, utbedring og respons, og Sophos-kunder kan holde styr på trusseldeteksjonsnavnene som brukes av produktene våre, via Sophos X-Ops Twitter-feed (@SophosXOps).


LÆR MER OM EXCHANGE-AUTENTISERING OG OAUTH2

Klikk og dra på lydbølgene nedenfor for å hoppe til et hvilket som helst punkt. Du kan også lytte direkte på Soundcloud.

Med Paul Ducklin og Chester Wisniewski
Intro- og outromusikk av Edith Mudge.


Tidstempel:

Mer fra Naken sikkerhet