It was just another day at work, Doing a web application security assessment. Running scans, reviewing endpoints, and validating findings. Nothing unusual yet until one of the automated scans flagged a familiar pattern: a version-based detection.

None

Introduction & Context

The application was identified as running Roundcube version 1.6.7, which is known to be vulnerable to CVE-2024-42009. This is a stored XSS flaw.

At first glance, this looked like many other findings that often end up being reported with limited validation: "version X is vulnerable to Y."

There was also a pre-auth constraint, which meant demonstrating this directly on the target was out of scope. I wanted to go beyond just another version-based finding and actually demonstrate real impact.

This vulnerability wasn't entirely straightforward. It required:

  • An attacker to send a specially crafted email
  • A victim to open that email in their inbox
  • And only then would the XSS payload would execute

So instead of treating this as just another version flag, I decided to answer a more important question:

Can I reliably reproduce this vulnerability and demonstrate its real impact in a way that mimics an actual attack scenario?

Understanding the Vulnerability

CVE-2024-42009 is a stored Cross-Site Scripting (XSS) vulnerability in Roundcube Webmail

We're all familiar with beautifully formatted HTML emails. To keep things safe, Roundcube sanitizes incoming HTML before displaying it in your browser. To prevent dangerous XSS (Cross-Site Scripting) attacks, it relies on a custom server-side sanitizer called washtml.

However, the problem wasn't in the sanitizer itself. The issue appeared after sanitization, in the message_body() function.

Roundcube first cleaned the email with washtml. Then, it ran an additional step html4inline() to convert the full HTML document into an inline snippet suitable for display. This step included a flawed regex that tried to strip legacy attributes like bgcolor from the <body> tag.

Because the regex was imprecise, it could accidentally break the sanitized HTML — a phenomenon called desanitization. A harmless-looking payload that passed the sanitizer could be transformed into a working event handler (like onanimationstart=alert(1)) during this final modification.

None

Basically, the email looked safe after sanitization, but a later processing step made it dangerous again! This allowed attackers to smuggle an XSS payload that executes when you simply open the email.

For a deeper technical breakdown (highly recommended), check out this excellent write-up by SonarSource: Desanitization in Inline Email Rendering (CVE-2024-42009)

Setting Up a Vulnerable Lab with Docker

Since this was a pre-auth assessment, I didn't have valid user accounts or authorization to simulate real user interactions on the client environment. And given that this vulnerability requires a victim to actually open an email, demonstrating impact directly on the target wasn't feasible.

To properly validate and demonstrate the issue, I needed a controlled environment that mimics a real-world deployment.

I built a local lab by writing a custom Docker Compose setup that included: - A vulnerable Roundcube 1.6.7 instance - A fully functional mail server using docker-mailserver - A shared network to simulate realistic email flow between services

Some key implementation details:

  • Service Separation: Defined two core services — a mail server and Roundcube — connected over a shared Docker network to simulate real world email flow.
  • Custom SMTP Port for Testing: Exposed SMTP on port 2525, making it easy to send raw emails using tools like Swaks without interfering with standard ports.
  • Mail Protocol Support: Enabled IMAP (143) and submission (587) to ensure proper mail delivery and retrieval between services.
  • Network Configuration: Leveraged a custom bridge network so both containers could communicate seamlessly using service names.
  • Web Access to Roundcube: Mapped port 8080 → 80, allowing quick access to the webmail interface viahttp://localhost:8080

Using Docker Compose allowed me to spin up the entire environment with a single command and ensured everything was reproducible.

Within minutes, I had a fully functional webmail lab running locally.

Initial Attempt (And Why It Failed)

I logged into two sessions: → One as the Attacker → Another as the Victim

From the attacker account, I sent an email containing the crafted payload.

<body title="bgcolor=foo" name="bar style=animation-name:progress-bar-stripes onanimationstart=alert(1) foo=bar">Foo</body>

Then I switched to the victim's account → inside inbox → opened the email…. and nothing happened.

None

No alert. No execution. Just a normal email.

None

This was a key moment.

The vulnerability was real, I even tried using other payloads but something in the delivery mechanism was preventing the exploit from working.

That's when I realized:

The way the email is sent matters just as much as the payload itself.

Roundcube's UI likely modifies or sanitizes outgoing emails in a way that breaks the exploit. So I needed a way to send a raw, unmodified email payload directly to the server.

None

Crafting the Exploit with Swaks

To bypass client-side modifications, I turned to swaks (Swiss Army Knife for SMTP).

Swaks allows you to send fully customizable emails directly over SMTP, including raw headers and HTML bodies → exactly what was needed here.

Using Swaks, I crafted a payload like this:

swaks --to victim@lab.local \
      --from attacker@lab.local \
      --server localhost:2525 \
      --header "Content-Type: text/html; charset=utf-8" \
      --header "Subject: CVE-2024-42009 PoC" \
      --body '<body title="bgcolor=foo" name="bar style=animation-name:progress-bar-stripes onanimationstart=alert(1) foo=bar">Foo</body>'
None

Triggering the XSS

Now came the moment of truth.

I logged in as the victim again, opened the inbox, and clicked on the malicious email.

Boom! 💣

The payload executed.

None

A JavaScript alert popped up → confirming that the stored XSS was successfully triggered inside the browser.

None

At this point, I had:

  • A reproducible exploit ✅
  • A working PoC ✅
  • And clear visual proof of impact ✅

Open-Sourcing the PoC

While working through this, I noticed something surprising:

There were no complete, working exploits publicly available that: - Set up the vulnerable environment, - Delivered the payload correctly - Demonstrated the XSS end-to-end

I decided to package everything, including the Docker setup, exploit steps, payload, and screenshots, and open-source it so others can learn from it and build on it.

🔗Github Repo: https://github.com/ZaidArif47/CVE-2024-42009

Final Thoughts

This wasn't just about reproducing an XSS, it was about bridging the gap between a scanner finding and a real, demonstrable risk.

In many assessments, especially pre-auth scenarios, it's easy to stop at version-based detections. But without a clear demonstration, these findings often get deprioritized or misunderstood by stakeholders.

Building a controlled lab changed that. It allowed me to:

  • Validate the vulnerability with confidence
  • Understand the exact conditions required for exploitation
  • And most importantly, show impact in a way that's hard to ignore!

It also highlighted an important point: The way a payload is delivered can be just as critical as the payload itself.

Finally, this experience reinforced why tools like Docker are so valuable in security testing. The ability to recreate environments, test safely, and produce high-quality PoCs is a skill that goes beyond just finding bugs.

It's also about communicating risk effectively. Because at the end of the day, a vulnerability only matters if you can prove its impact.

I hope this was an awesome read. Keep Rocking! Keep Hacking!

None