Skip to main content
Vulnerability Database/CVE-2026-110104

CVE-2026-110104: Xxyopen Novel Weak Password Hashing Flaw

CVE-2026-110104 is a weak password hashing flaw in Xxyopen novel that stores passwords using unsalted MD5, enabling attackers to recover plaintext credentials. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-110104 Overview

CVE-2026-110104 is a weak password hashing vulnerability affecting Xxyopen Novel through version 3.5.0. The flaw resides in UserServiceImpl.register(), which stores unsalted MD5 digests of user passwords in the user_info.password column. Attackers who obtain the password column through database leaks, backup exposure, or SQL injection can recover plaintext passwords using precomputed rainbow tables or GPU-accelerated brute force. Recovered credentials enable account takeover and credential reuse across other services. The weakness is categorized as [CWE-916] Use of Password Hash With Insufficient Computational Effort.

Critical Impact

Compromise of the user database leads to rapid recovery of plaintext passwords, enabling account takeover and credential stuffing across downstream systems.

Affected Products

  • Xxyopen Novel versions through 3.5.0
  • Deployments using the UserServiceImpl registration flow
  • Downstream forks that retain the unsalted MD5 hashing logic

Discovery Timeline

  • 2026-10-13 - CVE-2026-110104 published to the National Vulnerability Database
  • 2026-10-13 - Last updated in NVD database

Technical Details for CVE-2026-110104

Vulnerability Analysis

The Xxyopen Novel application implements user registration in UserServiceImpl.register(). The method invokes Spring's DigestUtils.md5DigestAsHex() on the submitted password and stores the resulting 128-bit digest in the user_info.password column. No salt, pepper, or key-stretching function is applied.

MD5 is not designed for password storage. Modern commodity GPUs compute billions of MD5 hashes per second. Without a per-user salt, identical passwords produce identical digests, which exposes shared credentials across the user base and allows attackers to query precomputed rainbow tables for instant recovery.

The upstream fix in pull request #53 replaces the MD5 scheme with BCryptPasswordEncoder from Spring Security Crypto. BCrypt applies a per-hash salt and a configurable work factor that makes offline cracking computationally prohibitive.

Root Cause

The root cause is the use of a fast, unsalted cryptographic digest for password storage. DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8)) produces deterministic output. There is no salt generation, no iteration count, and no adaptive work factor. The design assumes digest irreversibility, but modern cracking hardware invalidates that assumption for human-chosen passwords.

Attack Vector

Exploitation requires offline access to the user_info table. Common access paths include database backup exposure, misconfigured object storage, SQL injection in other application endpoints, or insider access. Once the password column is obtained, the attacker runs the digests through tools such as hashcat -m 0 or queries a rainbow table service. Recovered plaintext passwords are then replayed against the Novel login endpoint and other services where users reuse credentials.

java
// Security patch - UserServiceImpl.java (fa82ce7e)
 import java.nio.charset.StandardCharsets;
 import java.time.LocalDateTime;
 import java.util.Objects;
+import java.util.regex.Pattern;
 import lombok.RequiredArgsConstructor;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.stereotype.Service;
 import org.springframework.util.DigestUtils;

Source: GitHub Commit fa82ce7e

Detection Methods for CVE-2026-110104

Indicators of Compromise

  • Password column entries that are exactly 32 lowercase hexadecimal characters, matching the MD5 output length
  • Duplicate password hashes across distinct user accounts, indicating absence of per-user salt
  • Unexpected SELECT password FROM user_info queries in database audit logs
  • Successful logins from new geolocations following a database backup download or exposure event

Detection Strategies

  • Review the user_info.password column schema and sample values to confirm whether unsalted MD5 digests are in use
  • Grep the codebase for DigestUtils.md5DigestAsHex and MessageDigest.getInstance("MD5") in authentication paths
  • Correlate authentication success events with prior database export or backup access events in the data lake
  • Monitor for credential-stuffing patterns such as high-volume login attempts across many usernames from a small set of source addresses

Monitoring Recommendations

  • Enable database audit logging for all read operations against the user_info table
  • Alert on object storage access events targeting database backups, dumps, or .sql files
  • Track authentication failure spikes and burst patterns indicative of offline-cracked credential replay
  • Flag any application deployment that retains spring-security-crypto as absent in pom.xml

How to Mitigate CVE-2026-110104

Immediate Actions Required

  • Apply the upstream fix from pull request #53 that migrates password hashing to BCryptPasswordEncoder
  • Force a password reset for all existing user accounts because stored MD5 digests cannot be upgraded in place without the plaintext
  • Rotate database credentials and audit recent access to the user_info table and all backup locations
  • Enforce multi-factor authentication on administrative and high-value accounts to blunt credential replay

Patch Information

The fix is available in commit fa82ce7e426a5b29db469b8f13d2e29fc1260871 through GitHub Pull Request #53. The patch adds the spring-security-crypto dependency and replaces MD5 digest calls with BCryptPasswordEncoder. Operators should upgrade to a release that incorporates this commit and verify the pom.xml contains the Spring Security Crypto artifact. See the VulnCheck Advisory on Novel for further guidance.

Workarounds

  • Implement a transitional dual-hash strategy that re-hashes stored MD5 digests with BCrypt until users reauthenticate and establish BCrypt-only hashes
  • Restrict network and filesystem access to the database and all backup artifacts to the minimum set of operational accounts
  • Encrypt database backups at rest and require strong authentication for retrieval
  • Deploy rate limiting and account lockout policies on the login endpoint to slow credential replay
bash
# Verify Spring Security Crypto dependency is present after patching
grep -A1 'spring-security-crypto' pom.xml

# Confirm application no longer references MD5 for password hashing
grep -rn 'DigestUtils.md5DigestAsHex\|MessageDigest.getInstance("MD5")' src/main/java

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.