September 23, 2026
SH3 Public Management System Stored User Credentials Using a Reversible XOR-Based Mechanism
🔎Overview

By 0x5ea3o1f
3 min read
🔎Overview
Vendor: SH3 Sistemas
Product: SH3 Public Management System
Affected modules: SIAM and ARC modules
Affected versions: SH3 versions prior to 2026.0.2.0
Fixed version: 2026.0.2.0
Fix release date: September 2026
Update type: Manual update required
Severity: High
CWE: CWE-257 Storing Passwords in a Recoverable Format
Researcher: Warlley Freire (0x5ea3o1f), DumoSec
Disclosure status: Vendor notified and issue fixed
📝Summary
During an pentest engagement for a government office, a a vulnerability was identified in the SH3 Public Management System that affected the way user credentials were stored in versions prior to 2026.0.2.0.
Instead of storing passwords using a salted one-way password hashing function, the affected SH3 versions stored credential material using a reversible XOR-based mechanism with a fixed key embedded in the application logic. As a result, an attacker with read access to the relevant database tables or backups could recover user passwords in plaintext.
The issue was identified during an authorized internal security assessment conducted for a municipal public-sector client. The SH3 system was part of the authorized scope of the assessment. The finding was isolated as a product-level vulnerability rather than a local misconfiguration, because the credential storage mechanism was implemented by the SH3 application itself.
🛠️Technical Details
In the affected versions, SH3 did not apply a cryptographic password hash to user passwords. The assessment found that password values were stored in database fields associated with user authentication using a reversible byte-by-byte XOR operation with a fixed embedded key. Because the same fixed key was reused across accounts and was not derived from an installation-specific secret, the mechanism did not provide meaningful password protection once the stored credential values and transformation logic were accessed. The credential field identified in the assessment was STR_SH_USR, present in the affected user tables. The report disclosed to the vendor describes the affected storage locations as USUARIOS/siam.gdb and USUARIO/arc.gdb.
How the Issue Was Identified
The vulnerable field was identified during database enumeration. After I obtained authorized read access to the database environment through another assessment vector, I searched Firebird metadata for tables and fields related to users and authentication.
The report states that the internal Firebird catalog was queried to locate candidate authentication tables. This led to the USUARIOS table for the management module and the USUARIO table for the tax/collection module. Further inspection of the table columns revealed fields including STR_NM_USR, used as the login identifier, and STR_SH_USR, used to store the password material.
🧮 Crypto Analysing the stored passwords to find the secret
The first indicator that STR_SH_USR was not a real password hash was the relationship between the password length and the stored value length. In SH3 database, the values stored in STR_SH_USR had different lengths. Short passwords produced short stored values, while longer passwords produced longer stored values.
The second indicator came from byte-level comparison. When a password obteined by other vector during the assessemt was compared against its corresponding stored value, the difference between both values followed a simple positional pattern.
For each byte position i, the following relationship was observed:
key[i] = password[i] XOR stored_value[i]key[i] = password[i] XOR stored_value[i]This is a flag for a XOR-based reversible transformation:
After confirming the XOR pattern, I move to conductc an analysis across other known password and stored-value pairs. Each known plaintext revealed key bytes at specific positions. Some weak passwords and even a default one (same username and password) made this step easier:
Finally, with the 32-byte key recovered, I proceed to validation using the reversible nature of XOR operations:
Vulnerable Logic
The original report reconstructed the password recovery operation as a repeated XOR operation between the stored credential bytes and a fixed key embedded in the application. For public disclosure, the actual key and real credential samples are omitted:
STATIC_KEY = b"<fixed-embedded-key>"
def decode_password(stored_value: bytes, key: bytes = STATIC_KEY) -> bytes:
return bytes(
byte ^ key[index % len(key)]
for index, byte in enumerate(stored_value)
)STATIC_KEY = b"<fixed-embedded-key>"
def decode_password(stored_value: bytes, key: bytes = STATIC_KEY) -> bytes:
return bytes(
byte ^ key[index % len(key)]
for index, byte in enumerate(stored_value)
)The underlying weakness is that the same fixed key was reused to transform stored password values. Since XOR is reversible, the same operation can recover the original plaintext password when the key is known or derived.
The private report demonstrated the recovery operation using known plaintext/ciphertext pairs and then applying the reconstructed transformation to the full tested user set. The report states that the key was reconstructed from known accounts and that the same operation was then applied to all 82 accounts in the tested SIAM database, recovering valid plaintext passwords without brute force.
SH3 corrected the credential storage mechanism in version 2026.0.2.0. Affected customers must apply the update manually.