MISP Core `deleteSelection` Broken Access Control — Bulk Deletion of Foreign Event Reports & Sharing Groups (CVE-2026-56423)
Published: 2026-07-27 • Researcher: BiiTts (Caio Fabrício)
- Severity
- High
- CVE
- CVE-2026-56423
- Category
- web
- Affected product
- MISP (Malware Information Sharing Platform) Core — EventReportsController::deleteSelection and SharingGroupsController::deleteSelection
- Affected versions
- MISP Core up to and including 2.5.41 (fixed in 2.5.42)
- Disclosed
- 2026-07-27
- Patch status
- Patched
Tags
References
Archive entry
intelseclab/poc-archiveOn this page
Metadata
| Field | Value |
|---|---|
| Date Added | 2026-07-27 |
| Last Updated | 2026-07-27 |
| Author / Researcher | BiiTts (Caio Fabrício) |
| CVE / Advisory | CVE-2026-56423 |
| Category | web |
| Severity | High |
| CVSS Score | 8.8 (CVSS 3.1, AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) |
| Status | Weaponized — contributor-level bulk hard-delete of a foreign organizations Event Report confirmed against a real MISP core build; denied on the patched build |
| Tags | misp, misp-core, broken-access-control, cwe-862, bulk-deletion, authenticated, threat-intel-platform |
| Related | N/A |
Affected Target
| Field | Value |
|---|---|
| Software / System | MISP (Malware Information Sharing Platform) Core — EventReportsController::deleteSelection and SharingGroupsController::deleteSelection |
| Versions Affected | MISP Core up to and including 2.5.41 (fixed in 2.5.42) |
| Language / Platform | PHP (CakePHP), MISP core application |
| Authentication Required | Yes — any authenticated account whose role has perm_add (the default built-in “User”/contributor role qualifies) |
| Network Access Required | Yes — direct HTTP(S) access to the MISP web/API interface |
Summary
MISP’s bulk-deletion endpoints for Event Reports (/eventReports/deleteSelection) and Sharing Groups (/sharingGroups/deleteSelection) authorize each selected item using a checkModifyCallback that discards the item id and instead returns the acting user’s global role permission ($this->userRole['perm_add'] / perm_sharing_group). The equivalent single-item endpoint (/eventReports/delete/{id}) correctly performs a per-object check via fetchIfAuthorized/ownership resolution. As a result, any low-privileged authenticated contributor (default “User” role) can submit report or sharing-group IDs belonging to any organisation on the instance and hard-delete them in bulk, even though the per-item delete path for the exact same object is properly denied. This is a cross-tenant integrity/availability break in a platform CERTs, ISACs, and SOCs use to share sensitive threat intelligence.
Vulnerability Details
Root Cause
Tracked as CWE-862 (Missing Authorization). In app/Controller/EventReportsController.php, the deleteSelection action passes a checkModifyCallback closure to CRUDComponent::deleteSelection:
| |
CRUDComponent::deleteSelection invokes this callback per selected id and deletes whenever it returns true:
| |
Because the callback returns $this->userRole['perm_add'] — a global boolean that is true for the default “User” role — the ownership/organisation of the target object is never evaluated. The item lookup itself (recursive => -1, by raw id or UUID) has no organisation scoping either, so any object on the instance can be targeted. Contrast this with the correctly guarded single-object action:
| |
fetchIfAuthorized(..., 'delete') resolves the report against the caller’s organisation/permissions and throws if unauthorized — which is why the same request against /eventReports/delete/{id} is denied while /eventReports/deleteSelection succeeds. SharingGroupsController::deleteSelection has the identical defect, gated by perm_sharing_group instead of perm_add.
The ACL gate for deleteSelection (app/Controller/Component/ACLComponent.php) only requires AND(theming_enabled, perm_add) — theming_enabled being a dynamic check on the MISP.enable_themes instance setting (off by default, but a normal UI feature flag enabled on many instances since it powers the v2 index/list UI). No per-object or per-organisation permission is enforced at the ACL layer; that responsibility was expected to live in the controller callback, and it was implemented incorrectly there.
Attack Vector
An authenticated user holding any role with perm_add (e.g. the default “User”/contributor role) — on an instance with MISP.enable_themes = true — submits a POST to /eventReports/deleteSelection (or /sharingGroups/deleteSelection) with the id(s)/UUID(s) of Event Reports (or Sharing Groups) owned by a different organisation. Because the authorization callback checks only the caller’s global perm_add/perm_sharing_group flag rather than ownership of the specific item, the objects are hard-deleted regardless of who owns them.
Impact
Any low-privileged user on a shared/multi-tenant MISP instance can irreversibly hard-delete Event Reports (analyst narrative attached to threat-intel events) and Sharing Groups belonging to other organisations, instance-wide. This is a cross-tenant integrity and availability compromise of a threat-intelligence sharing platform — deleted analyst work product and sharing-group configuration cannot be trivially recovered and directly undermines the trust model of a multi-org MISP deployment.
Environment / Lab Setup
OS: Linux host with Docker + docker compose
Target: MISP core (official misp-docker stack), pinned via CORE_RUNNING_TAG:
v2.5.40 (vulnerable) for the exploit demo, v2.5.42 (patched) for the boundary check
Attacker: Any host with Python 3 (stdlib only — urllib, json, ssl)
Tools: exploit.py (this folder), lab/setup.sh + lab/teardown.sh (this folder)Setup Steps
| |
Proof of Concept
See
exploit.py,ANALYSIS.md,EVIDENCE.txt, andlab/(setup.sh,teardown.sh) in this folder — mirrored unmodified from BiiTts/CVE-2026-56423-MISP-deleteSelection-BrokenAccessControl. Verified before ingestion: real file contents were read in full —exploit.pyis a straightforward, honest urllib-based script that (1) confirms the victim report exists via an admin read, (2) confirms the correctly-guarded per-objectdelete/{id}denies the contributor’s request (the discriminant), (3) issues thedeleteSelectionbulk-delete call and shows it succeeds, and (4) verifies the report is now gone.lab/setup.shclones the real, officialMISP/misp-dockerproject and provisions a genuine local MISP instance rather than faking output. No obfuscation, no unrelated network calls, no destructive default behavior beyond what the PoC explicitly documents. The claimed fix commits (ada02fa6,f99b3f16) were independently cross-checked directly against theMISP/MISPGitHub repository viagh apiand confirmed to match the described root cause exactly — the callback is switched from returning the global role permission to a per-itemfetchIfAuthorizedcall.
Step-by-Step Reproduction
Stand up the vulnerable lab — brings up MISP core v2.5.40 via the official misp-docker compose stack, enables
MISP.enable_themes, and provisions an attacker org, a contributor (“User” role) account, and a victim Event Report owned by the admin org.Shell script1 2 3cd lab ./setup.sh source /tmp/misp_poc.envRun the exploit — confirms the per-object
deletepath denies the contributor, then showsdeleteSelectionbulk-deleting the same foreign report.Shell script1 2python3 ../exploit.py https://127.0.0.1:443 \ --attacker-key "$CONTRIB_KEY" --admin-key "$ADMIN_KEY" --report-id "$VICTIM_REPORT_ID"Verify the patched boundary — re-run the same lab pinned to the fixed release and confirm the identical request is now denied.
Shell script1 2 3CORE_RUNNING_TAG=v2.5.42 ./setup.sh # re-run the exploit against the new instance; deleteSelection now returns 403 ./teardown.sh
Exploit Code
See
exploit.py(full, unmodified) in this folder.
| |
Expected Output
[*] target report id = 2 (owned by another org)
[+] report exists before attack
[1] contributor legit delete/2 -> HTTP 404 (DENIED (expected))
[2] contributor deleteSelection [2] -> HTTP 200 {"saved":true,"success":true,"name":"EventReport deleted."...}
[+] CONFIRMED: contributor hard-deleted another org's Event Report via deleteSelection
(legit per-object delete was denied; deleteSelection bypassed ownership).Screenshots / Evidence
EVIDENCE.txt— full transcript in this folder: contributor identity, the per-objectdeletedenial (404), thedeleteSelectionbulk-delete success (200), post-attack confirmation the foreign report is gone (404 on adminview), and the same request re-run against the patched v2.5.42 build (403, report intact).
Detection & Indicators of Compromise
SIEM / IDS Rule (example):
alert http any any -> any any (msg:"Possible MISP deleteSelection cross-org bulk delete (CVE-2026-56423)"; content:"POST"; http_method; content:"/eventReports/deleteSelection"; http_uri; sid:9000002;)
alert http any any -> any any (msg:"Possible MISP deleteSelection cross-org bulk delete (CVE-2026-56423)"; content:"POST"; http_method; content:"/sharingGroups/deleteSelection"; http_uri; sid:9000003;)Remediation
| Action | Detail |
|---|---|
| Patch | Upgrade MISP core to 2.5.42 or later, which replaces the global-permission callback with a per-item EventReport::fetchIfAuthorized($user, $itemId, 'delete') authorization check (and the equivalent for Sharing Groups). Fix commits: ada02fa6 and f99b3f16 in MISP/MISP. |
| Workaround | Where upgrading is not immediately possible, disable MISP.enable_themes to close the ACL gate for deleteSelection (breaks the v2 index/list UI as a side effect), and/or restrict which roles are granted perm_add/perm_sharing_group to trusted, single-org users only. |
| Config Hardening | Audit and monitor bulk-deletion actions instance-wide; on multi-org instances, treat any contributor role with perm_add as able to affect other orgs’ Event Reports/Sharing Groups until patched. |
References
Notes
Verified before ingestion per this archive’s standing verify-before-ingest policy: the real file contents of the upstream repo (exploit.py, ANALYSIS.md, EVIDENCE.txt, lab/setup.sh, lab/teardown.sh) were read in full — the script is a plain, honest urllib-based reproduction with no obfuscation, droppers, or unrelated network calls, and the lab scripts clone and provision a genuine local MISP instance via the official MISP/misp-docker project rather than fabricating output. The claimed fix commits (ada02fa6, f99b3f16) were independently cross-checked directly against the MISP/MISP GitHub repository via gh api and confirmed to match the described root cause exactly: the vulnerable checkModifyCallback returns the caller’s global role permission (perm_add/perm_sharing_group) instead of performing a per-item fetchIfAuthorized ownership check, and the fix commits replace it with exactly that per-item check.
The author (BiiTts / Caio Fabrício) has a track record of other verified-real PoCs ingested into this archive this session (Budibase, Crawl4AI, Apache APISIX), which increased confidence in this submission ahead of the independent commit cross-check.
| |