Incorrect or missing information? SABnzbd 5.1 vulnerabilities
Several security researchers have put a lot of time and effort into examining SABnzbd, responsibly reporting their findings and helping us verify the fixes. We are grateful for their hard work, it has made SABnzbd meaningfully safer for everyone.
SABnzbd 5.1.1, 5.1.2 and 5.1.3 resolve five security vulnerabilities:
- 5.1.3 resolves an unauthenticated API access vulnerability (GHSA-q326-jpxx-jmjc). In version 5.1.2 and earlier, an attacker who can reach the web interface could still reach the protected API handler through an alternative request path, skipping the API-key check. This is a variation on GHSA-rgqj-28c2-gxwp below, which it partially reopens.
- 5.1.3 resolves a high-severity path traversal vulnerability (GHSA-mjwj-v5mr-cmcg). In version 5.1.2 and earlier, a maliciously crafted download containing a symlink could still make SABnzbd write files outside the job’s own folder during post-processing, which could be escalated to execute arbitrary commands on the system running SABnzbd. This is a variation on GHSA-75g3-96fr-7p2r below, which it partially reopens. Like that one, this does not involve the web interface.
- 5.1.2 resolves a critical remote code execution vulnerability (GHSA-rgqj-28c2-gxwp). In version 5.1.1 and earlier, an attacker who can reach the web interface could bypass authentication on privileged configuration endpoints and, from there, execute arbitrary commands on the system running SABnzbd.
- 5.1.2 resolves a high-severity path traversal vulnerability (GHSA-75g3-96fr-7p2r). In version 5.1.1 and earlier, a maliciously crafted PAR2 or SFV file inside a download could make SABnzbd write files outside the job’s own folder during post-processing, which could be escalated to execute arbitrary commands on the system running SABnzbd. Unlike the web interface issues, this is reachable through normal downloading of untrusted content.
- 5.1.1 resolves a critical authentication vulnerability (GHSA-xrfq-jhgh-wqch). In version 5.1.0 and earlier, an attacker who can reach the web interface could obtain a valid login session without knowing the username or password.
For most users the risk is limited, because all of these require your setup to be exposed to someone you do not trust. Check both sections below to see which, if any, apply to you.
Am I affected?
The web interface vulnerabilities and the path traversal vulnerabilities have different exposure, so check both.
Web interface (remote code execution, authentication bypass and unauthenticated API access)
You are only affected if an untrusted party can reach the SABnzbd web interface.
By default, SABnzbd is only accessible from your own device, and External internet access on the
General page of the Config is set to No access.
If either of those is still at its default, or you use a proxy service for authentication, you are
not affected by these.
You are affected if you have exposed SABnzbd to the internet and set External internet access
to Full Web interface or Only external access requires login. In that case an attacker could
exploit these vulnerabilities even when SABnzbd is protected with a username and password.
Path traversal (downloaded content)
These do not involve the web interface, so the settings above do not protect against them. You are affected if SABnzbd processes NZBs or downloads from a source you do not fully trust, such as a public indexer. They are reachable during normal post-processing with default settings. The only protection is to update, or to only download from sources you trust.
The 5.1.3 path traversal additionally requires a filesystem that supports symlinks, so it mainly affects Linux, macOS and other Unix-like systems.
What should I do?
Update to SABnzbd 5.1.3 or newer.
If your web interface was reachable by untrusted parties (see Am I affected? above), an attacker could have gained full control of the system account running SABnzbd through the remote code execution vulnerability. In that case, treat the account as compromised and change the following sensitive information after applying the update:
- SABnzbd username and password.
- SABnzbd API-key.
- Usenet server passwords.
- API-keys from indexers used within RSS-feeds.
- Authentication information for notification services.
If your setup was never reachable by untrusted parties and you only download from sources you trust, no further action is needed beyond updating.
If you cannot update right away
For the web interface vulnerabilities, the mitigations are to ensure the web interface is not
reachable by untrusted parties, or to lower External internet access on the
General page to Full API or below. Limiting
external access to the API keeps those out of reach for attackers on the internet.
The path traversal vulnerabilities have no such mitigation, because they are triggered by the content of a download rather than the web interface. The only way to avoid them is to update, or to only download from sources you trust.
Technical details
Unauthenticated API access (5.1.3)
The 5.1.2 fix correctly restricted the mode-based access decision to the actual API route, but the
protected handler stayed reachable by another route.
secured_expose() marked the original handler as exposed to CherryPy before wrapping it in the
authentication check. Because the wrapper is created with functools.wraps(), the original,
still-exposed handler remained available through the __wrapped__ attribute, and CherryPy’s object
dispatcher could traverse that attribute straight from the request path. A request to the API below
__wrapped__ therefore reached the API handler without ever passing through the authentication
wrapper, and returned data that the normal route refused without an API-key.
5.1.3 makes sure the unprotected original function is no longer dispatchable underneath the authentication wrapper, so the handler can only be reached through the checked route.
Path traversal via symlink (5.1.3)
The 5.1.2 fix blocked literal ../ traversal in names taken from PAR2 and SFV files, but the
containment check compared paths textually. It normalised both sides with os.path.normpath(),
which collapses a .. segment against the name in front of it without looking at the filesystem.
If the download itself contains a symlink pointing back at its own folder, those two disagree. The
check sees a path that stays inside the job folder, while the filesystem resolves the symlink first
and only then applies the .., so the file ends up one level higher than the check believed.
Repeating this walks the destination out of the job folder entirely.
Used this way, a malicious download could reach SABnzbd’s global administration folder and plant
both a queue state file and a queue repair trigger. On the next start, the repair makes SABnzbd read
the planted state file with Python pickle, which executes code as the user running SABnzbd. This
reaches the same outcome as the 5.1.2 issue, but through global queue state rather than another
job’s __ADMIN__ folder.
5.1.3 resolves both sides of the destination on the filesystem before comparing them, so a symlink
can no longer make a contained path resolve elsewhere. Downloaded content is also prevented from
writing into SABnzbd’s global administration folder, and queue state is no longer loaded with
unrestricted pickle.
Remote code execution (5.1.2)
Endpoints protected by the API-key check derived their access decision from the request’s mode
parameter, which describes an API operation. The public version and auth API calls require no
key, so supplying mode=version (or mode=auth) skipped the API-key check on unrelated privileged
configuration endpoints. This let an unauthenticated attacker change settings such as the scripts
folder and pre-queue script, and from there execute commands as the SABnzbd user.
5.1.2 restricts the public version/auth exception, and the mode-based access level, to the
actual API route. Every other endpoint now always requires a valid API-key, regardless of mode.
Path traversal (5.1.2)
During post-processing, SABnzbd uses the file names stored inside PAR2 and SFV files to rename
downloaded files to their intended names. Those names come from the downloaded content and were not
checked for directory traversal, so a crafted name such as ../../evil could move a downloaded file
outside the job’s own folder. By writing into another job’s internal administration folder
(__ADMIN__), whose state files are loaded with Python pickle, this could be escalated into
arbitrary code execution as the user running SABnzbd.
5.1.2 keeps these renames contained to the job folder and blocks writing into the reserved
__ADMIN__ folder, so a planted file can no longer be loaded.
Authentication bypass (5.1.1)
The web interface signed each login session with a cookie derived from a low-entropy, guessable secret, and the logout endpoint returned a usable cookie to unauthenticated callers. Together this allowed a session to be obtained without valid credentials.
5.1.1 fixes both issues: the logout endpoint no longer emits a usable cookie, and the session secret is now generated from a cryptographically secure random source.