The CVE202644212 exploit abuses a gap between email format validation and HTML output encoding. PrestaShop's ValidateisEmail() accepts RFC 5321 quotedstring local parts, which legally allow double quotes, spaces and other special characters. An attacker crafts an email like autofocus onfocus=alert(document.cookie) , submits it through the unauthenticated Contact Us form and the string lands unescaped inside a backoffice <input> attribute. When a support agent opens the thread, the injected handler executes in their session. This page walks through the exploit primitive, a working proof of concept and how defenders can detect attempts for authorized testing and lab use only.Before going further, read this as a case study in a vulnerability class, not a howto for attacking production stores you do own. Every command here assumes a local Docker lab or an engagement with written authorization.For the patch and remediation side of this CVE, see our CVE202644212 patch guide. For the conceptual overview, start with the main CVE202644212 breakdown.
The Vulnerability Class Validation and Encoding Live in Different Worlds
Most exploit writeups for stored XSS stop at the output. CVE202644212 is more interesting because the input was validated just against the wrong standard for the context it ended up addresses have to satisfy a protocol specification (RFC 5321, the SMTP standard) at the point they are collected and an HTML safety rule at the point they are rendered. PrestaShop's validator enforces the first and assumes that's sufficient. It isn't. RFC 5321 permits a quoted string local part, meaning the segment before the @ can be wrapped in double quotes and contain characters including another double quote inside, via escaping rules and critically, spaces and most ASCII punctuation that are meaningless to SMTP but highly meaningful to an HTML parser.
An attacker exploiting a gap like this one is doing classic contextswitching exploitation, finding a value that is legal in its origin context (an SMTP address) but dangerous in its destination context (an HTML attribute). The same reasoning pattern shows up across injection bug classes, which is why practicing it on SQL injection labs builds transferable intuition even though the sink is different.
Reconnaissance Confirming the Target Is Exploitable
Before crafting a payload, confirm two things on an authorized target.Version fingerprint. The vulnerable rendering path exists in PrestaShop builds before 8.2.6 and before 9.1.1 (from 9.0.0alpha.1 onward). Version strings are often visible in changelog files, admin login page metadata, or asset file paths. On an authorized engagement you may have direct backoffice access, which makes this trivial the version is printed in the dashboard form availability. The module ships enabled by default and typically answers at /contactus or via index.php?controller=contact. Load the form and confirm a Customer service subject exists; that's the default subject that routes submissions into the vulnerable Customer Service thread view (AdminCustomerThreads).
Building the Payload
Step 1 Confirm the validator accepts the quotedstring format
Before touching the live form, test the validator logic directly if you have code access to a lab instanceOn a vulnerable build (validator in Symfony loose mode), both lines report VALID. That confirms the intake gate is open.
Step 2 Understand why angle brackets do not survive, but quotes do
PrestaShop runs stored strings through pSQL() before writing to the database. With HTML output disabled (the default for this field), pSQL() calls strip_tags() on the value. strip_tags() removes anything that looks like <tag> so a naive <script>alert(1)</script> payload gets its script tags stripped in storage, even though it passes validation.Double quotes are not touched by strip_tags(). That's the detail that makes the attributebreakout primitive reliable where a taginjection primitive is the exploit has to live entirely in quote and attribute syntax, not anglebracket syntax.
Step 3 Craft the attributebreakout payload
The vulnerable template renders the stored email inside a hidden input's value attribute without escaping A payload that closes the value=... early and appends new attributes achieves the injectionBecause the element type is hidden, browsers suppress autofocus/onfocus triggering on hidden inputs by default so this exact payload confirms the injection primitive (attribute breakout) without an automatic fire. A second injection point exists in the thread's <h3> heading, rendered as unescaped text content, which is where a more reliably triggering payload (or a payload chained with a different event, depending on surrounding markup and admin interaction) should be evaluated during an authorized assessment. Document both sinks; do not assume the first one you find is the only usable one.If you want structured practice finding this exact class of bug a field that passes format validation but carries an injection payload into a different rendering context the CrossSite Scripting (XSS) labs and broader web application hacking tracks are built around exactly this kind of multistage trustboundary failure.
Delivering the Payload
Submitting through the public form requires a session cookie and the page's CSRF token, both obtainable from an unauthenticated GET request.A success response includes a confirmation string indicating the message was sent. At this point the payload is resting in the ps_customer_thread table, waiting for an admin to open it. The defining trait of stored XSS is that the attacker's active work is already finished.
Confirming Storage
On a lab target where you control the database, confirming the row landed intact is a useful sanity check before moving to the rendering stage. If the row shows the quote characters preserved rather than stripped, the storage layer behaves as analyzed above and the chain is ready for the render step.
The Trigger What the Admin Sees
When a backoffice employee opens the poisoned thread in AdminCustomerThreads, the template renders the stored value into both injection points. Reviewing the resulting page source (viewsource, not a rendered screenshot, to avoid accidentally triggering anything beyond scope) shows the broken attribute boundary described above. In a full exploitation chain against an authorized target, the realistic endgame looks like this
Payload submitted via the public form.
Admin or support agent opens the thread during normal triage.
Injected JavaScript executes in the admin's authenticated session.
The script exfiltrates document.cookie (or, more robustly, uses the session to make an authenticated fetch request directly, since modern cookie flags may limit raw document.cookie access) to an attackercontrolled listener.
The attacker replays the session to reach the back office product management, order data, customer PII and module installation which is itself a path to server side code execution.
That escalation from cookie theft to code execution via module install is why the CVSS vector marks Scope as Changed the vulnerability in an unprivileged form component compromises a separate, more privileged component. A session cookie alone is always the whole prize, either if the compromised instance issues bearer tokens to any connected integration, the exploit's real value depends on how those tokens are scoped and how long they live, which is covered in the JWT security guide.Once inside the back office, a tester assessing full impact should stop at the session itself. Order and customer management screens are a natural next stop for checking IDOR and broken access control whether the compromised session can reach records belonging to a different store context than the one the attack originated in.
Automating Detection with Nuclei
For authorized vulnerability scanning across a fleet, a Nuclei template built on the validation behavior (not a live payload fire) is the safer detection method to submit a harmless quotedstring probe and check whether the form accepts or rejects it.A vulnerable target accepts the quotedstring probe and returns the success string. A patched target (validator switched to strict mode) rejects it with an invalid email message instead that rejection is itself the proof the fix is applied, which is also the fastest manual verification step if you do not want to run Nuclei.
Scope, Authorization and Responsible Testing
This exploit touches a production admin's browser session as its final step. That makes scope discipline nonnegotiable
Only test against systems you own or have explicit written authorization to assess.
Prefer the validation behavior probe (accept/reject) over a livefiring payload whenever your goal is to confirm presence of the bug, not to demonstrate full impact.
If a client engagement calls for demonstrating full impact, coordinate the trigger step with the client so a real staff member is the one who inadvertently executes the payload without warning.
Clean up test threads afterward; do leave probe data sitting in a client's support queue.
Unauthorized use of this technique against systems you do not control is illegal under computer crime laws in most jurisdictions, regardless of how low effort the payload looks.
Why This Exploit Pattern Is Worth Internalizing
The CVE202644212 exploit is a compact lesson in three separable failures that defenders and testers alike should learn to isolate
A permissive parser at intake the loose Symfony email mode accepting any RFC 5321legal string.
A lossy sanitization step at storage strip_tags() stopping angle brackets but not quote characters.
Missing contextaware encoding at output the Smarty template skipping |escape'html''UTF8' in an attribute context.
Any one of the three fixes alone would have closed this exploit. PrestaShop shipped two (output escaping plus stricter validation) as defense in depth. When you're testing your own applications, check all three layers independently; a bug fixed at intake can still be exploitable through a different intake path that reaches the same unescaped sink and vice versa.
This exploit chain also won not be the last one in your queue that completely bypasses authentication through a chain of individually valid steps the cPanel authentication bypass, CVE202641940, is a useful comparison for how differently an unauthenticated exploit chain can be shaped depending on whether the target needs a human in the loop or not. A fixed server rendered sink like this one is also a reminder to test the client side separately patched stored XSS on the server does not rule out DOMbased XSS in a custom storefront script handling the same kind of untrusted string.
Conclusion
CVE202644212 rewards attackers who think in terms of context mismatch rather than bruteforce payload lists. The entire exploit chain fits in one crafted email address, because PrestaShop validated the string against the right specification for the wrong destination. For defenders and pentesters alike, the real takeaway is not the specific payload, it is the habit of asking, for every piece of validated input, validated against what and rendered where. Build that habit on live, legal targets through the web security CTF challenges and start practicing.
Frequently Asked Questions (FAQs)
Is a public PoC for CVE202644212 available?
The vulnerability is documented in detail by the discovering researchers, including validator tests, form submission commands and a Nuclei detection template, all intended for authorized testing and defensive verification rather than unauthorized use.
Why does the exploit use double quotes instead of <script> tags?
Because PrestaShop's storage layer strips HTML tags via strip_tags() before saving the value, but does not touch quote characters. A payload built from quotes and attribute syntax survives storage; a payload built from angle brackets does not.
Does the exploit require any authentication?
No. The initial payload delivery is fully authenticated; anyone who can reach the public Contact Us form can plant it. The only authentication involved belongs to the victim; a backoffice employee's already authenticated session is what gets hijacked.
What triggers the payload after it is submitted?
A backoffice employee or administrator opening the Customer Service thread that contains the poisoned email address. Until that happens, the payload sits inert in the database.
How do defenders detect exploitation attempts in logs?
Look for POST requests to /contactus where the form parameter contains a URLencoded double quote (%22) followed by HTML even than older keywords such as on focus, one, or onload, combined with the autofocus attribute. A database query for stored emails starting with a quote character or containing spaces is a useful complementary indicator.


Join the conversation
Discussion0
Join the conversation. Sign in to leave a response or reply to comments.