Skip to content

CRITICAL: Remote Code Execution (RCE) via Unverified Sideloading of Plugins in ExternalExtensionLoader #380

Description

@basantnema31

Title

CRITICAL: Remote Code Execution (RCE) via Unverified Sideloading of Plugins in ExternalExtensionLoader

Description

The application includes a plugin system intended to load "Cloudstream" extensions (.cs3 files), which are essentially compiled Dalvik Executables (DEX) / APKs containing executable Kotlin/Java code.

The ExternalExtensionLoader.kt handles downloading and dynamically loading these plugins via DexClassLoader. However, the implementation completely lacks any form of cryptographic signature verification, checksum validation, or origin authentication before executing the loaded code.

From ExternalExtensionLoader.kt:

    suspend fun downloadExtension(scraperId: String, downloadUrl: String): File? = withContext(Dispatchers.IO) {
        ...
        val request = Request.Builder().url(downloadUrl).build()
        httpClient.newCall(request).execute().use { response ->
            val bytes = response.body?.bytes() ?: return@withContext null
            val targetFile = getExtensionFile(scraperId)
            targetFile.writeBytes(bytes)
            ...
        }
    }

After downloading, the file is immediately passed to DexClassLoader and its classes are instantiated via reflection, running code inside the application's process and sandbox.

Furthermore, ExternalRepoParser.kt explicitly accepts http:// URLs for these repositories. Since the application also has usesCleartextTraffic="true" enabled globally, an attacker positioned on the same network (e.g., public Wi-Fi, compromised router, or DNS spoofing) can easily intercept the HTTP request for the plugin and swap the .cs3 file with a malicious payload.

Even if HTTPS is used, relying solely on TLS without verifying a cryptographic signature of the downloaded .cs3 file means that if the third-party plugin repository server is compromised, malicious code will be automatically distributed and executed on all users' TVs.

Proof of Concept

  1. A user adds an external Cloudstream repository URL in the app.
  2. The app fetches the repository JSON over HTTP (or HTTPS) and extracts the downloadUrl for an extension.
  3. An attacker performs a MITM attack on the http:// download request, replacing the .cs3 file stream with a crafted DEX file containing a malicious Plugin class.
  4. ExternalExtensionLoader.downloadExtension() saves the file.
  5. DexClassLoader loads the file, and loadClass() instantiates the malicious plugin class.
  6. The malicious plugin achieves Remote Code Execution (RCE) in the context of the Arvio application, gaining access to all permissions and local data held by the app (e.g., reading user tokens, installing malicious APK updates, exfiltrating viewing history).

Recommended Fix

Dynamic code loading (DexClassLoader) of files downloaded from the internet is inherently extremely dangerous.

  1. Implement Signature Verification: All .cs3 extensions must be cryptographically signed by a trusted developer key. Before passing the downloaded file to DexClassLoader, the application must verify the digital signature (e.g., standard APK v2/v3 signature schemes or a custom Ed25519 signature mechanism) against a hardcoded public key or a pinned certificate. If the signature is invalid or missing, the file must be deleted immediately and not loaded.
  2. Enforce HTTPS: Strictly reject any http:// URLs in ExternalRepoParser and ensure that all plugin metadata and payloads are fetched securely over TLS.
  3. Verify File Hashes: If a repository manifest provides SHA-256 checksums for the plugins, the app must hash the downloaded file and ensure it matches the expected checksum before loading it.

/assign

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions