This is finding a locked door in the UI, then checking whether the same room is still open through the side entrance
Tenable plugin 121039 is a generic web-application authorization test, not a product-specific CVE. It looks for cases where a remote web app exposes privileged functionality to a low-privileged or even unauthenticated user because the server fails to enforce authorization on the function itself. Tenable published this plugin on 2019-01-09 and currently scores it as Critical / CVSS 9.1; the scan only runs when generic web application tests are enabled, and the plugin documentation shows it depends on web-app test settings rather than any affected software version range.
The vendor score is too aggressive for patch prioritization at enterprise scale. Broken access control is absolutely dangerous when confirmed, but this plugin is a category-level DAST signal with heavy real-world friction: it often requires hidden endpoint discovery, role-context testing, and manual confirmation that a privileged action actually succeeded. In other words, the bug class is severe; the *scanner finding* is not automatically a Critical patch event.
4 steps from start to impact.
Map privileged endpoints with Burp Suite Spider or ffuf
/admin, /api/admin/*, workflow actions, export functions, and hidden POST endpoints. This step is routine in web testing, but it is still application-specific and not guaranteed to produce anything useful.- Reachable web application endpoint
- Ability to browse or crawl the application
- Sufficient route predictability or discoverability
- Modern SPAs can hide routes behind client state and API choreography
- Unlinked endpoints may not be guessable
- Rate limiting, WAFs, and bot controls often slow enumeration
Obtain a low-priv session using normal app registration or credentials
Burp Repeater or OWASP ZAP replay requests from that weaker session against privileged functions. If the issue is truly unauthenticated, severity rises fast, but that is not the default assumption for this plugin.- Valid session token, cookie, or API key for a lesser role, or an unauthenticated route if exposed
- Ability to preserve and replay HTTP requests
- Registration may be closed or approval-gated
- MFA, anti-automation, and device binding can limit session acquisition
- Role separation may be sparse in non-admin workflows
Replay the privileged function directly with Burp Repeater or curl
- Known privileged endpoint and parameters
- Server-side authorization missing or inconsistently applied
- Many apps do block with
401/403once the direct request is replayed - CSRF tokens, nonce values, and workflow state can break simple request replay
- Some findings are read-only or cosmetic rather than impactful
Convert access into impact with app-native actions
- Privileged function performs a meaningful action
- Application trusts the caller once the route is reached
- Impact may be limited to a single object, tenant, or workflow step
- Many findings do not grant code execution or infrastructure compromise
- Tenant isolation or secondary approval steps can cap damage
The supporting signals.
| In-the-wild status | No CVE is tied to this plugin, so there is no KEV entry and no product-specific in-the-wild evidence to anchor on. Treat it as an application-specific logic finding, not a mass-exploitation signature. |
|---|---|
| Proof-of-concept availability | Generic tradecraft is widely available via Burp Suite Repeater, OWASP ZAP, and public access-control testing guidance from PortSwigger and OWASP WSTG. |
| EPSS | N/A — EPSS is CVE-based, and this Tenable plugin is a generic vulnerability class finding rather than a CVE record. |
| KEV status | Not applicable — no CVE, therefore no CISA Known Exploited Vulnerabilities catalog entry or KEV listing date. |
| CVSS vector | Tenable assigns CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N = 9.1. That vector assumes a clean network-path exploit with no role or workflow friction, which is often too optimistic for real deployments. |
| Affected versions | No vendor product/version range is defined. The finding applies to any web application route where privileged functionality is reachable without correct server-side authorization. |
| Fixed versions | None published. Remediation is code/config based: enforce authorization checks on the server for every privileged function and role boundary. |
| Scanning and exposure reality | Internet search engines like Shodan/Censys cannot reliably fingerprint this flaw class. Exposure only exists where a specific application publishes reachable privileged functionality and the server-side authorization check is missing. |
| Disclosure date | Tenable plugin published 2019-01-09; current plugin page shows it updated 2026-03-23. |
| Research lineage | This is aligned with OWASP A01 Broken Access Control and MITRE CWE-862 Missing Authorization, not a named researcher-disclosed product bug. |
noisgate verdict.
The decisive downgrade factor is attack-path friction: most real exploits here require endpoint discovery plus a low-privileged or contextual session, which makes this a post-enumeration application-logic issue rather than a turnkey internet-scale compromise. The impact can be severe once validated, but the reachable population and exploit reliability are too uncertain to treat every hit as Critical.
Why this verdict
- Vendor baseline is inflated for patch ops: Tenable's 9.1 assumes
PR:N/UI:N, but real exploitation commonly requires route discovery, a valid low-priv session, or a role boundary to abuse. - Reachable population is narrow: this is only exploitable on the specific application paths where authorization is missing; it is not a fleet-wide software defect with a universal exploit.
- Modern controls add friction: authenticated scanning gaps, MFA, anti-automation, WAFs, CSRF/workflow state, and tenant segmentation frequently break the clean exploit path implied by CVSS.
Why not higher?
I am not calling this HIGH or CRITICAL because the finding is not a vendor-confirmed product vulnerability with known affected versions, known exploit code, or broad exploitation telemetry. In many environments it is a candidate logic flaw that still needs a human to prove an actual unauthorized action succeeded and to measure blast radius.
Why not lower?
I am not pushing this to LOW because broken access control remains one of the most damaging web-app classes when validated. If the privileged function exposes sensitive data, admin actions, or cross-tenant impact, the practical business risk is real even without a CVE.
What to do — in priority order.
- Validate the route manually — Use an auditor workstation with
Burp Suite,OWASP ZAP, orcurlto confirm whether the exact endpoint found by Tenable returns a meaningful privileged action to an unauthenticated or low-privileged session. Because this is a MEDIUM verdict, there is no mitigation SLA; validate before mobilizing engineering, then place confirmed issues into the remediation queue within 365 days unless business impact justifies faster handling. - Enforce server-side authorization centrally — Move authorization checks into middleware, route guards, controller decorators, or policy engines rather than relying on hidden UI elements or client-side role checks. For confirmed findings, ship that control as the durable fix within the 365-day remediation window for MEDIUM, sooner if the route is internet-facing and touches admin or regulated data.
- Constrain sensitive endpoints at the edge — Where practical, put admin routes behind SSO groups, VPN, IP allowlists, or API gateway policy so the reachable population shrinks even if application logic is imperfect. This is a useful compensating control while the application team works the code fix inside the 365-day remediation window.
- Log authorization failures and privileged actions — Instrument the app and gateway to record
401/403, role mismatches, admin route access, export actions, and state-changing privileged API calls. Detection does not fix the bug, but it reduces dwell time and gives you evidence if a confirmed finding is probed before code remediation lands.
- Hiding admin links in the UI or client-side JavaScript does not help; direct requests to the endpoint still work if the server never checks authorization.
- TLS, secure cookies, and WAF signatures do not solve missing authorization logic; they protect transport and some attack patterns, not business-rule enforcement.
- MFA alone does not fix this class when the attacker can authenticate as a normal user and then replay a forbidden function.
Crowdsourced verification payload.
Run this from an auditor workstation against the affected application after you identify the suspected privileged route from the Tenable output. Invoke it as python verify_mflac.py https://app.example.com /admin/users --cookie "session=LOWPRIVCOOKIE" --allow-text "User Administration"; no local admin rights are needed, but you do need a known low-priv session if the route is authenticated.
#!/usr/bin/env python3
# verify_mflac.py
# Purpose: sanity-check a suspected Missing Function Level Access Control finding.
# Output: VULNERABLE / PATCHED / UNKNOWN
# Exit codes: 0=PATCHED, 1=VULNERABLE, 2=UNKNOWN, 3=usage/network error
import argparse
import sys
import requests
from urllib.parse import urljoin
DENY_CODES = {401, 403}
REDIRECT_DENY_HINTS = ('login', 'signin', 'auth')
def build_session(cookie_header: str, header_list):
s = requests.Session()
if cookie_header:
s.headers['Cookie'] = cookie_header
for item in header_list:
if ':' not in item:
continue
k, v = item.split(':', 1)
s.headers[k.strip()] = v.strip()
s.headers.setdefault('User-Agent', 'noisgate-mflac-check/1.0')
return s
def is_redirect_to_login(resp):
if not resp.history and resp.status_code not in (301, 302, 303, 307, 308):
return False
loc = resp.url.lower()
return any(hint in loc for hint in REDIRECT_DENY_HINTS)
def main():
parser = argparse.ArgumentParser(description='Verify suspected Missing Function Level Access Control')
parser.add_argument('base_url', help='Base URL, e.g. https://app.example.com')
parser.add_argument('path', help='Suspected privileged path, e.g. /admin/users')
parser.add_argument('--cookie', default='', help='Cookie header for low-priv session, e.g. "session=abc"')
parser.add_argument('--header', action='append', default=[], help='Additional header, repeatable, e.g. "X-CSRF-Token: abc"')
parser.add_argument('--method', default='GET', choices=['GET', 'POST', 'HEAD'], help='HTTP method to use')
parser.add_argument('--data', default='', help='Optional POST body')
parser.add_argument('--allow-text', default='', help='Text that indicates the privileged page/action really loaded')
parser.add_argument('--timeout', type=int, default=15, help='HTTP timeout in seconds')
args = parser.parse_args()
url = urljoin(args.base_url.rstrip('/') + '/', args.path.lstrip('/'))
session = build_session(args.cookie, args.header)
try:
if args.method == 'GET':
resp = session.get(url, timeout=args.timeout, allow_redirects=True, verify=True)
elif args.method == 'HEAD':
resp = session.head(url, timeout=args.timeout, allow_redirects=True, verify=True)
else:
resp = session.post(url, data=args.data, timeout=args.timeout, allow_redirects=True, verify=True)
except requests.RequestException as exc:
print(f'UNKNOWN - request failed: {exc}')
sys.exit(3)
body = resp.text[:200000] if hasattr(resp, 'text') else ''
if resp.status_code in DENY_CODES or is_redirect_to_login(resp):
print(f'PATCHED - access denied ({resp.status_code}) for {url}')
sys.exit(0)
if 200 <= resp.status_code < 300:
if args.allow_text:
if args.allow_text.lower() in body.lower():
print(f'VULNERABLE - privileged content marker matched on {url} ({resp.status_code})')
sys.exit(1)
else:
print(f'UNKNOWN - got {resp.status_code} but privileged content marker not found on {url}')
sys.exit(2)
else:
print(f'UNKNOWN - got {resp.status_code} on {url}; provide --allow-text to confirm real privileged access')
sys.exit(2)
if resp.status_code in (301, 302, 303, 307, 308):
print(f'UNKNOWN - redirect observed ({resp.status_code}) to {resp.url}')
sys.exit(2)
print(f'UNKNOWN - unexpected status {resp.status_code} for {url}')
sys.exit(2)
if __name__ == '__main__':
main()
If you remember one thing.
Sources
- Tenable Plugin 121039
- Tenable Nessus Web Application Scanning
- Tenable Nessus User Guide PDF - Generic web application tests
- OWASP Top 10 A01 Broken Access Control
- OWASP WSTG - Testing for Bypassing Authorization Schema
- MITRE CWE-862 Missing Authorization
- PortSwigger Web Security Academy - Access control vulnerabilities
What defenders are saying.
Crowdsourced verification outputs.
Results submitted by users who ran the verification payload against their environment.