Hur man hackar en oparpad Exchange-server med oseriös PowerShell-kod

Källnod: 1760191

För knappt två månader sedan kom några oroande buggnyheter: ett par nolldagssårbarheter tillkännagavs i Microsoft Exchange.

Som vi rådde då, dessa sårbarheter, officiellt utsedda CVE-2022-41040 och CVE-2022-41082:

[var] två nolldagar som [kunde] kedjas samman, med den första buggen som användes på distans för att öppna tillräckligt med ett hål för att utlösa den andra buggen, vilket potentiellt tillåter fjärrkörning av kod (RCE) på själva Exchange-servern.

Den första sårbarheten påminde om den besvärliga och allmänt missbrukade ProxyShell säkerhetshål från tillbaka i augusti 2021, eftersom det förlitade sig på farligt beteende i Exchanges Autodiscover-funktion, beskrivs av Microsoft som ett protokoll alltså "används av Outlook- och EAS [Exchange ActiveSync]-klienter för att hitta och ansluta till postlådor i Exchange".

Lyckligtvis var felfunktionen i Autodiscover som kunde utnyttjas i ProxyShell-attacken av vilken fjärranvändare som helst, vare sig inloggad eller inte, patchad för mer än ett år sedan.

Tyvärr gjorde ProxyShell-korrigeringarna inte tillräckligt för att stänga av utnyttjandet för autentiserade användare, vilket ledde till den nya CVE-2022-40140 noll-dag, som snart var lakoniskt, om än missvisande, dubbade ProxyNotShell.

Inte lika farligt, men farligt ändå

Uppenbarligen var ProxyNotShell inte i närheten av så farlig som den ursprungliga ProxyShell, med tanke på att den krävde vad som kallas autentiserad åtkomst, så den var inte öppen för missbruk av vem som helst var som helst.

Men det visade sig snabbt att på många Exchange-servrar skulle det räcka att känna till alla användares inloggningsnamn och lösenord för att passera som autentiserade och starta denna attack, även om den användaren själv skulle behöva använda tvåfaktorsautentisering (2FA) för att logga in ordentligt för att komma åt deras email.

Som Sophos-experten Chester Wisniewski Ställ det just då:

Det är en "mid-autentiseringssårbarhet", om du vill kalla det så. Det är en blandad välsignelse. Det betyder att ett automatiserat Python-skript inte bara kan skanna hela internet och potentiellt utnyttja alla Exchange-servrar i världen på några minuter eller timmar, som vi såg hända med ProxyLogon och ProxyShell 2021. […]

Du behöver ett lösenord, men att hitta en kombination av e-postadress och lösenord som är giltig på en given Exchange-server är förmodligen inte så svårt, tyvärr. Och du kanske inte har blivit utnyttjad hittills, eftersom för att lyckas logga in på Outlook Web Access [OWA] krävs deras FIDO-token, eller deras autentisering, eller vilken andra faktor du kan använda.

Men denna attack kräver inte den andra faktorn. […] Bara att skaffa en kombination av användarnamn och lösenord är en ganska låg barriär.

Som du säkert minns antog (eller åtminstone hoppades) många av oss att Microsoft skulle skynda sig att fixa till ProxyNotShell-hålen, med tanke på att det fortfarande var två veckor kvar till oktobers patchtisdag.

Men vi blev besvikna när vi upptäckte att en tillförlitlig fix tydligen var mer komplex än väntat, och oktober kom och gick med ProxyNotShell adresserad endast av lösningar, inte av korrekta patchar.

Inte ens Novembers Patch Tuesday gav direkt de nödvändiga korrigeringarna, även om patcharna kom ändå ut samma dag som en del av en Exchange-specifik säkerhetsuppdatering som kan hämtas och installeras separat:

Proof-of-concept avslöjat

Nu när dammet har lagt sig och alla har hunnit patcha sina Exchange-servrar (de som de inte har glömt, åtminstone), forskare vid Zero Day Initiative (ZDI), som dessa sårbarheter ursprungligen avslöjades för att skickas till Microsoft, har förklarat hur buggarna kan utnyttjas.

De dåliga nyheterna, beroende på din åsikt om uppenbara exploateringsavslöjanden, är att ZDI-teamet nu effektivt har tillhandahållit en proof-of-concept (PoC) som förklarar hur man attackerar Exchange-servrar.

De goda nyheterna är naturligtvis att:

  • Vi kan nu studera och förstå buggarna själva. Detta hjälper oss inte bara att säkerställa att de övergripande försiktighetsåtgärderna vi har vidtagit (inte bara begränsade till lappning) sannolikt kommer att ge det skydd vi förväntar oss, utan informerar oss också om programmeringsmetoder som vi kommer att vilja undvika i framtiden, så vi inte inte fastna i att öppna upp buggar av det här slaget i vår egen kod på serversidan.
  • Vi har nu inga ursäkter kvar för att inte applicera plåstren. Om vi ​​har dragit på oss för att uppdatera, gör ZDI:s förklaring till varför attacken fungerar klart att botemedlet definitivt är att föredra framför sjukdomen.

Hur det fungerar

ZDI:s förklaring av denna sårbarhet ger en fascinerande berättelse om hur komplext det kan vara att kedja ihop alla delar du behöver för att förvandla en sårbarhet till en livskraftig exploatering.

Det är också värt att läsa för att hjälpa dig förstå varför att gräva i en befintlig exploatering kan hjälpa till att avslöja andra sätt som en sårbarhet kan missbrukas, potentiellt föranleda ytterligare patchar, uppmana till konfigurationsändringar och främja nya programmeringsmetoder som kanske inte var uppenbara bara från att åtgärda det ursprungliga hålet.

Förklaringen är med nödvändighet komplicerad och ganska teknisk, och leder dig framåt genom en lång rad steg för att uppnå fjärrkodexekvering (RCE) i slutet.

I hopp om att hjälpa dig att lättare följa detaljerna på hög nivå om du bestämmer dig för att läsa ZDI-rapporten, här är en förhoppningsvis inte alltför förenklad sammanfattning med stegen listade i omvänd ordning...

…så att du i förväg vet varför berättelsen tar de riktningar den gör:

  • STEG 4. Lura Exchange på distans att instansiera ett .NET-objekt som du väljer, med en valfri initialiseringsparameter.

I modern kodning, en instansierat objekt är jargongordet för en allokerad minnesbit, som automatiskt initieras med de data och resurser den behöver när den används, och knuten till en specifik uppsättning funktioner som kan arbeta på den. (Instantiera är bara ett fint ord för skapa.)

Objekt kan hanteras och kontrolleras av operativsystemet självt, för att undvika den typ av minnesfelhantering som är vanliga i ett språk som C, där du vanligtvis behöver allokera minne själv, fylla i relevanta datafält för hand och komma ihåg att frigör minnet och resurserna du använder, som nätverksuttag eller diskfiler, när du är klar.

Objekt har i allmänhet en programmatisk funktion kopplad till dem som kallas a konstruktör, som exekveras automatiskt när ett nytt objekt skapas för att allokera rätt mängd minne och rätt uppsättning systemresurser.

Vanligtvis måste du skicka en eller flera parametrar som argument till konstruktorn, för att ange hur du vill att objektet ska konfigureras när det startar.

Enkelt uttryckt, om du instansierar, säg, en TextString objekt (vi hittar på dessa namn, men du fattar) med en parameter som i sig är en textsträng som t.ex. example.com:8888.

… du kommer förmodligen att få en minnesbuffert tilldelad för att hålla din text, initierad så att den har samma värde som du skickade in, nämligen den råa texten example.com:8888.

I det sammanhanget utgör textsträngen som skickas in som data till objektkonstruktören inte omedelbart något uppenbart cybersäkerhetshot när du triggar konstruktören på distans, annat än en möjlig överbelastning (DoS) genom att upprepade gånger be om större och större strängar för att försök att tömma minnet.

Men om du skulle instansiera, säg, en ConnectedTCPClient objekt som använder samma textsträngsparameter som example.com:8888, kan du sluta med en minnesbuffert redo att hålla temporär data, tillsammans med ett nätverksuttag tilldelat av operativsystemet som är redo att utbyta data med servern example.com över TCP-porten 8888.

Du kan se risken för fjärrkörning av kod där, även om du aldrig får skicka någon data till den öppna uttaget, med tanke på att du har lurat servern att ringa hem till en plats som du kontrollerar.

Du kanske till och med hittar ett föremål som heter t.ex. RunCmdAndReadOutput, där textsträngen du skickar som parameter, bokstavligen, är ett kommando som du vill köra automatiskt så snart objektet skapas, så att du kan samla in dess utdata senare.

Även om du aldrig får återskapa kommandots utdata, skulle bara instansiera ett sådant objekt ändå låta dig välja ett kommando att köra, vilket ger dig generisk fjärrkörning och utgör en risk som endast begränsas av åtkomsträttigheterna för själva serverprocessen. .

Naturligtvis är attacken bara så lätt när du kommer till det sista steget, vilket du inte ska kunna göra, eftersom Exchange har en strikt godkännandelista som hindrar dig från att välja något gammalt objekt att instansiera.

I teorin kan endast säkra eller lågriskobjekt skapas på distans via PowerShell, så att instansiera vår imaginära TextString ovan, eller a SimpleIntegerValue, kan anses godtagbart, medan en ConnectedTCPClient eller ett RunCmdAndReadOutput skulle definitivt inte vara det.

Men ZDI-forskarna märker att innan de utlöste det sista steget kunde de göra detta:

  • STEG 3. Lura Exchange på distans att tro att ett lågriskobjekt som klarat säkerhetstestet i själva verket är något annat objekt du väljer.

Trots det kan du förvänta dig att Exchange förhindrar fjärrskapande även av lågriskobjekt, för att minimera hotet ytterligare.

Men forskarna fann att de kunde:

  • STEG 2. Lura Exchange på distans att använda sin PowerShell Remoting funktion för att skapa ett objekt baserat på initialiseringsparametrar som styrs externt.

Och det var möjligt på grund av det ProxyShell-liknande hålet som bara var halvlappat:

  • STEG 1. Lura Exchange på distans att acceptera och bearbeta en webbförfrågan med kod in genom att packa en giltig username:password fältet i begäran också.

Även om användaren som nämns i begäran inte faktiskt var inloggad och skulle behöva gå igenom någon form av 2FA-process för att komma åt sin egen brevlåda, kan en angripare som kände sina username:password kombination skulle ha tillräckligt med autentiseringsinformation för att lura Exchange att acceptera en webbanslutning som kan användas för att starta attackkedjan som beskrivs i steg 2 till 4 ovan.

Löst sagt, alla giltiga username:password kombination skulle göra, med tanke på att "autentiseringen" behövdes helt enkelt för att förhindra Exchange från att avvisa HTTP-förfrågan i förväg.

Vad göra?

Observera att denna attack bara fungerar:

  • Om du har lokala Exchange-servrar. Microsoft säger sig ha låst sina egna molntjänster snabbt, så Exchange Online påverkas inte. Se till att du vet var dina Exchange-servrar finns. Även om du nu använder Exchange Online kan du fortfarande ha lokala servrar igång, kanske överblivna av misstag från din migreringsprocessen.
  • Om dina servrar inte är patchade. Se till att du har tillämpade Exchange Software Update från 2022-11-08 till stänga av sårbarheterna som utnyttjandet kräver.
  • Om dina servrar fortfarande accepterar grundläggande autentisering, även känd som äldre autentisering. Se till att du har blockerade alla aspekter av äldre autentisering så att dina servrar inte accepterar username:password rubriker som nämns ovan, och accepterar inte riskfyllda Autodiscover-protokollförfrågningar i första hand. Detta stoppar angripare lura en server att acceptera deras tricks för instansiering av booby-fällda objekt, även om den servern inte är patchad.

Du kan hålla reda på av våra officiella råd om förebyggande, åtgärdande och svar, och Sophos-kunder kan hålla reda på namnen på hotdetektion som används av våra produkter, via Sophos X-Ops Twitter-flöde (@SophosXOps).


LÄS MER OM EXCHANGE AUTENTICERING OCH OAUTH2

Klicka och dra på ljudvågorna nedan för att hoppa till valfri punkt. Du kan också lyssna direkt på Soundcloud.

Med Paul Ducklin och Chester Wisniewski
Intro och outro musik av Edith Mudge.


Tidsstämpel:

Mer från Naken säkerhet