CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-3105
7.60.03%

Mautic SQLi: When "Order By" Becomes "Pwned By"

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 25, 2026·6 min read·11 visits

PoC Available

Executive Summary (TL;DR)

Unvalidated input in Mautic's API sort direction parameter allows for Blind SQL Injection via the ORDER BY clause. Attackers can exfiltrate sensitive marketing data. Fixed in versions 4.4.19, 5.2.10, 6.0.8, and 7.0.1.

Mautic, the open-source darling of marketing automation, recently patched a high-severity SQL Injection vulnerability (CVE-2026-3105) that turns a mundane API sorting feature into a database exfiltration pipeline. By failing to validate the direction of a sort (ASC/DESC), the application allowed attackers to append arbitrary SQL commands directly into the query structure. This deep dive explores how a classic 'Order By' injection works in modern ORM environments and why input validation remains the unshakeable law of the land.

The Hook: The Marketer's Honey Pot

Marketing automation platforms are the digital equivalent of a dragon's hoard. They don't just store data; they store relationships. Mautic holds the keys to your leads, your email lists, your tracking pixels, and often, deep integration credentials for your CRM. If you own the marketing platform, you don't just own the data—you own the company's voice.

CVE-2026-3105 targets the jugular of this system: the API. Specifically, the Contact Activity timeline. This is the feature marketers use to see if a lead opened an email or visited a landing page. It’s high-traffic, data-rich, and as it turns out, was casually accepting raw SQL commands from anyone with basic API access.

The irony here is palatable. A system designed to track user behavior failed to track the behavior of the users querying it. By manipulating how this timeline data was sorted, an attacker could force the database to reveal its secrets, one bit at a time.

The Flaw: The Doctrine of Insecurity

To understand this bug, you have to understand the false sense of security provided by modern Object-Relational Mappers (ORMs) like Doctrine (which Mautic uses). Developers often sleep soundly believing that prepared statements shield them from all evil. And for WHERE clauses, they are mostly right. If you try to inject into a standard filter, the ORM treats your input as a literal string, neutralizing the attack.

But ORDER BY is the unruly cousin of SQL clauses. You cannot parameterize a keyword like ASC or DESC using standard prepared statements. The database engine expects a literal token, not a bound variable.

Because of this limitation, developers often resort to string concatenation. They take the user's input (?dir=ASC) and slap it right onto the end of the query string. In Mautic's case, the code handling the Contact Activity timeline API blindly trusted the direction parameter. It assumed users would play nice and only send 'ASC' or 'DESC'.

Spoiler alert: Hackers do not play nice.

The Code: Anatomy of a Screw-up

Let's look at the implementation pattern that caused this mess. While the exact proprietary code snippets vary slightly by version, the logic flow in Doctrine applications usually looks like this:

The Vulnerable Code

// The controller receives the 'dir' parameter from the request
$direction = $request->get('dir', 'DESC');
 
// The repository constructs the query
$queryBuilder = $this->createQueryBuilder('a')
    ->select('a')
    ->where('a.contact = :contactId')
    ->setParameter('contactId', $id);
 
// FATAL ERROR: Direct concatenation of user input
$queryBuilder->orderBy('a.dateAdded', $direction);
 
return $queryBuilder->getQuery()->getResult();

In the code above, the $direction variable is treated as a trusted command. If I send dir=DESC, the query ends with ORDER BY a.dateAdded DESC. Perfect.

The Attack Surface

However, if I send dir=DESC; DROP TABLE leads;--, the ORM might complain about syntax (because ORDER BY injection is tricky with Doctrine's DQL vs SQL translation). But, we don't need to drop tables. We need to read them.

The injection occurs because the resulting DQL (Doctrine Query Language) or SQL is constructed as:

SELECT ... FROM ... ORDER BY date_added [INJECTED_STRING]

The Fix

The remediation is laughably simple. White-listing. If the input isn't 'ASC' or 'DESC', it defaults to 'DESC'.

// The Patched Code
$rawDirection = $request->get('dir');
// Strict validation
$direction = (strtoupper($rawDirection) === 'ASC') ? 'ASC' : 'DESC';
 
$queryBuilder->orderBy('a.dateAdded', $direction);

This simple ternary operator acts as the bouncer, kicking out any payload that tries to sneak in SQL syntax.

The Exploit: Timing is Everything

Since we are injecting into an ORDER BY clause, we can't easily use UNION SELECT to dump data directly to the screen (the resulting columns usually won't match the object hydration expectations of the ORM). Instead, we turn to Blind SQL Injection.

We can inject a subquery that triggers a time delay if a specific condition is true. This allows us to ask the database yes/no questions.

The Payload: DESC, (SELECT 1 FROM (SELECT(SLEEP(5)))a)

The Logic:

  1. The application expects a sort direction.
  2. We provide DESC to satisfy the syntax for the first column.
  3. We add a comma , to start sorting by a second "column".
  4. This second "column" is actually a subquery containing a sleep command.

By automating this process with a tool like sqlmap or a custom Python script, an attacker can extract the administrator's password hash, session tokens, or the entire lead database, character by character.

The Impact: Silent Exfiltration

Why is this a high-severity issue? It's not RCE (Remote Code Execution), so the server won't explode. But in the context of Mautic, confidentiality is king.

1. PII Harvesting: Mautic stores names, emails, addresses, and IP addresses. This is a GDPR nightmare waiting to happen.

2. Corporate Espionage: Competitors could dump your lead activity to see who you are pitching to and what content is performing well.

3. Lateral Movement: Mautic often stores API keys for CRMs (Salesforce, HubSpot) and email providers (SendGrid, AWS SES) in the database. If an attacker dumps the integrations table, they can pivot to your other infrastructure components.

The attack is stealthy. Aside from a few slightly slower API requests, there are no file uploads, no crashed services, and no defaced websites. You simply wake up one day and realize your entire customer list is on the dark web.

The Fix: Closing the Barn Door

If you are running Mautic, you need to update yesterday. The patches are available in versions 4.4.19, 5.2.10, 6.0.8, and 7.0.1.

If you cannot patch immediately (perhaps you have a heavily customized instance that breaks on upgrade), you can implement a WAF (Web Application Firewall) rule.

WAF Mitigation Strategy: Block any request to the Mautic API where the dir, orderDir, or direction parameter contains characters other than A-Z. Specifically, block:

  • Commas ,
  • Parentheses ()
  • Spaces (often encoded as %20 or +)
  • The word SELECT

However, WAFs are just band-aids. The real fix is ensuring that your code never blindly trusts user input, especially when talking to the database.

Official Patches

MauticGitHub Security Advisory and Patch Details

Technical Appendix

CVSS Score
7.6/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:L/A:L
EPSS Probability
0.03%
Top 92% most exploited

Affected Systems

Mautic Marketing Automation

Affected Versions Detail

Product
Affected Versions
Fixed Version
Mautic
Mautic
>= 2.10.0 < 4.4.194.4.19
Mautic
Mautic
>= 5.0.0 < 5.2.105.2.10
Mautic
Mautic
>= 6.0.0 < 6.0.86.0.8
Mautic
Mautic
>= 7.0.0 < 7.0.17.0.1
AttributeDetail
CWE IDCWE-89 (SQL Injection)
CVSS Score7.6 (High)
Attack VectorNetwork (API)
Privileges RequiredLow (Authenticated API User)
Exploit StatusPoC Available (Theoretical)
Confidentiality ImpactHigh

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059Command and Scripting Interpreter
Execution
CWE-89
Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')

The software constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component.

Known Exploits & Detection

NVDBlind SQL injection via sort parameter.

Vulnerability Timeline

Initial internal fix committed for report date filters
2025-08-19
CVE-2026-3105 Published
2026-02-24
Security Releases (4.4.19, 5.2.10, etc.) available
2026-02-24

References & Sources

  • [1]Mautic Security Advisory GHSA-r5j5-q42h-fc93
  • [2]NVD Entry for CVE-2026-3105

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.