This is graffiti on an internal admin dashboard, not a master key to the building
CVE-2026-28756 is a stored XSS flaw in the *Permissions based on Distribution Groups* report of ManageEngine Exchange Reporter Plus. The vendor advisory says builds 5801 and below are affected and 5802 fixes it. The exploit path is classic persistent XSS: an attacker stores script in report-rendered data, then waits for another user to open the affected report in the web console.
The vendor's HIGH 7.3 overstates operational risk for most enterprises. The decisive friction is that ManageEngine says exploitation requires an authenticated attacker with Exchange administrative privileges and then a second user to view the report; NVD independently rescored it to 4.8 MEDIUM, which is much closer to reality for a post-auth, user-interaction, admin-console bug.
4 steps from start to impact.
Get inside the product with the right role
Burp Suite to map the request flow. ManageEngine's advisory explicitly narrows this to an authenticated attacker with Exchange administrative privileges in the Exchange organization, which already makes this a post-initial-access problem.- Reachability to the Exchange Reporter Plus web console
- Valid authenticated access
- Exchange administrative privileges or equivalent delegated capability
- This is not unauthenticated remote exploitation
- Many deployments keep the console internal or VPN-restricted
- Role delegation in the product can limit who can create or manage the relevant data paths
Plant persistent script in the report path
Burp Suite Repeater or XSS Hunter, the attacker injects HTML/JavaScript that is later rendered by the *Permissions based on Distribution Groups* report. Because this is stored XSS, the payload survives until another user loads the report page.- A writable input path that feeds the affected report
- Insufficient output encoding in the report renderer
- The vulnerable sink appears limited to a specific report, not the whole application
- Payloads may be neutralized by browser hardening, CSP, or view-layer changes in some environments
- Attackers still need the target user to open this specific report
Wait for a victim to open the report
XSS Hunter callbacks or custom JavaScript to steal session material, trigger same-origin actions, or stage follow-on requests inside the product.- A victim user opens the affected report
- The victim browser executes the injected script in the product origin
- No click, no exploit
- The reachable victim set is usually a small operations/admin audience, not all employees
- Modern browsers, SSO controls, and shortened session lifetimes can reduce useful session theft outcomes
Abuse the victim's session within Exchange Reporter Plus
BeEF can help operationalize this. The likely impact is session hijack, unauthorized report access, exports, or configuration actions in the product context rather than direct host-level takeover.- Victim has higher privileges than the attacker
- Session tokens or same-origin requests are usable from script context
- Blast radius is constrained to the victim's product permissions
- There is no stated direct server-side RCE or OS compromise path
- Impact depends heavily on what the victim can actually do inside this one console
- A perimeter IPS or signature-only network control will not reliably catch this, because the payload lives in legitimate authenticated application traffic and fires later in a browser.
- Endpoint AV on the server is not a fix; this is a browser-side script execution issue inside a legitimate web app session.
- MFA helps protect the login step but does not stop a stored payload from abusing an already-authenticated victim session.
The supporting signals.
| In-the-wild status | No evidence of active exploitation surfaced in the reviewed sources. CISA ADP marks Exploitation: none in Vulnrichment, and the CVE is not in KEV. |
|---|---|
| Public PoC availability | No credible public PoC repo or exploit module surfaced in quick review. Realistically this is still easy to weaponize with generic tooling like Burp Suite and XSS Hunter, but there is no named public exploit release to point patch queues at. |
| EPSS | User-supplied EPSS is 0.00019 (~0.019%), which is *very low*. I could not verify the exact percentile from a primary FIRST record in-tool, but the probability signal is clearly bottom-tier. |
| KEV status | Not KEV-listed. The official CISA KEV catalog and the cisagov/kev-data mirror showed no match for CVE-2026-28756 during review. |
| CVSS split | Vendor/CNA score is 7.3 HIGH (AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N), but NVD rescored it to 4.8 MEDIUM with PR:H/UI:R/S:C/C:L/I:L/A:N. That downgrade matters because it aligns with the vendor text saying exploitation needs an authenticated attacker with Exchange admin privileges. |
| Affected versions | ManageEngine advisory: builds 5801 and below. CVE record/NVD: all versions before 5802. |
| Fixed versions | 5802 fixes the issue; ManageEngine says it was fixed on 2026-03-19. Their service-pack matrix specifically maps 5800-5801 -> 5802. |
| Exposure and scanning reality | This is a Windows-hosted admin web console; ManageEngine docs show a default web port of 8181 unless changed. I found no CVE-specific GreyNoise telemetry and no reliable public census result tying internet exposure directly to this flaw, which is another reason not to score it like a mass-exploitation bug. |
| Disclosure and credit | Published 2026-04-03. Reported by C311 through the Zoho BugBounty program. |
Sources.
Why this verdict
- Start from the vendor's 7.3 HIGH, then cut hard for attacker position: the advisory itself says exploitation needs an authenticated attacker with Exchange administrative privileges, which implies the attacker is already inside and already privileged.
- User interaction is mandatory: stored XSS still needs a victim to load the *specific* report, so exploitation is not autonomous and not wormable.
- Reachable population is narrow: Exchange Reporter Plus is an admin console product, commonly internal-only or VPN-restricted, and the victim audience is a small group of operators rather than the general workforce.
- Blast radius is app-context first: the stated impact is actions within Exchange Reporter Plus using the victim's privileges, not direct server-side RCE or operating-system compromise.
- Threat telemetry is cold: no KEV listing, no active-exploitation evidence in reviewed sources, and a very low EPSS signal all argue against emergency-tier handling.
Why not higher?
A higher rating would require either a much broader exposed population or a lower-friction exploit chain. Here you need prior authenticated access, elevated rights in the Exchange environment, and then a victim opening a single report path; that's stacked friction. There is also no evidence of in-the-wild exploitation and no direct server-side code execution outcome.
Why not lower?
This is still a stored XSS in an administrative product, not a cosmetic bug. If a more privileged operator opens the report, the attacker can act in that user's session context and potentially access or export sensitive Exchange reporting data. That is meaningful security impact even if the preconditions keep it out of the high bucket.
Crowdsourced verification payload.
Run this on the Windows host where Exchange Reporter Plus is installed. Invoke it from an elevated PowerShell prompt as powershell.exe -ExecutionPolicy Bypass -File .\check-CVE-2026-28756.ps1; admin rights are recommended so the script can read uninstall registry entries, service metadata, and protected install paths.
# check-CVE-2026-28756.ps1
# Exit codes:
# 0 = PATCHED
# 1 = VULNERABLE
# 2 = UNKNOWN
$ErrorActionPreference = 'SilentlyContinue'
function Write-Result {
param(
[string]$State,
[string]$Detail,
[int]$Code
)
Write-Output "$State - $Detail"
exit $Code
}
function Get-BuildFromString {
param([string]$Text)
if ([string]::IsNullOrWhiteSpace($Text)) { return $null }
$patterns = @(
'(?i)build\s*[:#-]?\s*(\d{4,5})',
'(?<!\d)(\d{4,5})(?!\d)',
'(\d+)\.(\d+)\.(\d{4,5})',
'(\d+)\.(\d{4,5})'
)
foreach ($p in $patterns) {
$m = [regex]::Match($Text, $p)
if ($m.Success) {
# Prefer the last numeric group that looks like a build
for ($i = $m.Groups.Count - 1; $i -ge 1; $i--) {
$val = $m.Groups[$i].Value
if ($val -match '^\d{4,5}$') {
return [int]$val
}
}
}
}
return $null
}
function Get-InstallCandidates {
$candidates = New-Object System.Collections.Generic.List[string]
$uninstallRoots = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
foreach ($root in $uninstallRoots) {
Get-ItemProperty $root | ForEach-Object {
if ($_.DisplayName -match 'Exchange Reporter Plus') {
if ($_.InstallLocation) { [void]$candidates.Add($_.InstallLocation) }
}
}
}
$svc = Get-CimInstance Win32_Service | Where-Object { $_.Name -match 'Exchange Reporter Plus' -or $_.DisplayName -match 'Exchange Reporter Plus' } | Select-Object -First 1
if ($svc -and $svc.PathName) {
$path = $svc.PathName.Trim('"')
if (Test-Path $path) {
$dir = Split-Path $path -Parent
if ($dir) { [void]$candidates.Add($dir) }
$parent = Split-Path $dir -Parent
if ($parent) { [void]$candidates.Add($parent) }
}
}
$defaults = @(
'C:\Program Files\ManageEngine\Exchange Reporter Plus',
'C:\ManageEngine\Exchange Reporter Plus'
)
foreach ($d in $defaults) { [void]$candidates.Add($d) }
return $candidates | Where-Object { $_ -and (Test-Path $_) } | Select-Object -Unique
}
# 1) Try uninstall registry first
$registryFindings = @()
$uninstallRoots = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
)
foreach ($root in $uninstallRoots) {
Get-ItemProperty $root | ForEach-Object {
if ($_.DisplayName -match 'Exchange Reporter Plus') {
$registryFindings += $_
}
}
}
foreach ($item in $registryFindings) {
$versionText = @($item.DisplayVersion, $item.DisplayName) -join ' '
$build = Get-BuildFromString -Text $versionText
if ($build -ne $null) {
if ($build -lt 5802) {
Write-Result 'VULNERABLE' "Registry indicates build $build (< 5802). Source: $($item.DisplayName) $($item.DisplayVersion)" 1
} else {
Write-Result 'PATCHED' "Registry indicates build $build (>= 5802). Source: $($item.DisplayName) $($item.DisplayVersion)" 0
}
}
}
# 2) Try install path files for build/version hints
$paths = Get-InstallCandidates
foreach ($base in $paths) {
$textFiles = @(
Join-Path $base 'README.txt',
Join-Path $base 'readme.txt',
Join-Path $base 'version.txt',
Join-Path $base 'build.txt',
Join-Path $base 'conf\product.conf',
Join-Path $base 'bin\wrapper.conf'
)
foreach ($f in $textFiles) {
if (Test-Path $f) {
$content = Get-Content $f -TotalCount 200 | Out-String
$build = Get-BuildFromString -Text $content
if ($build -ne $null) {
if ($build -lt 5802) {
Write-Result 'VULNERABLE' "File $f indicates build $build (< 5802)." 1
} else {
Write-Result 'PATCHED' "File $f indicates build $build (>= 5802)." 0
}
}
}
}
# 3) Fall back to executable version metadata
$exeCandidates = Get-ChildItem -Path $base -Recurse -Include *.exe -File | Where-Object {
$_.Name -match 'Exchange|Reporter|ManageEngine'
} | Select-Object -First 25
foreach ($exe in $exeCandidates) {
$verText = @($exe.VersionInfo.FileVersion, $exe.VersionInfo.ProductVersion, $exe.Name) -join ' '
$build = Get-BuildFromString -Text $verText
if ($build -ne $null) {
if ($build -lt 5802) {
Write-Result 'VULNERABLE' "Executable $($exe.FullName) indicates build $build (< 5802)." 1
} else {
Write-Result 'PATCHED' "Executable $($exe.FullName) indicates build $build (>= 5802)." 0
}
}
}
}
Write-Result 'UNKNOWN' 'Could not confidently determine the installed Exchange Reporter Plus build. Check the web console License page or the service-pack UI for the build number.' 2