Aug 26, 2026·6 min read·1 visit
An authenticated staff user can bypass multi-tenancy access controls in OpenWISP IPAM to export IP allocation tables of other organizations by targeting the custom subnet export view with a specific identifier.
A broken object-level authorization (BOLA) vulnerability exists in the Django Admin custom export view of OpenWISP IPAM. This flaw allows a multi-tenancy restricted staff user to export subnets and associated IP addresses belonging to different organizations by supplying a targeted subnet identifier in the export request.
OpenWISP IPAM is an IP address management system designed for multi-tenant deployments, providing strict logical separation between network architectures of different organizations. The administrative interface leverages Django Admin to allow designated operators to manage subnets, IP leases, and allocation structures. Within this framework, secure multi-tenancy relies on restricting visibility and access permissions based on the active user's associated organization.
A critical authorization bypass vulnerability, identified as GHSA-x287-5c68-36wp, exists within the custom subnet export feature of the Django Admin interface. The export feature is designed to allow staff members to download complete CSV reports of the IP addresses assigned to their managed subnets. However, the endpoint handling this request fails to validate that the requested subnet belongs to an organization the authenticated user is authorized to manage.
This failure results in a Broken Object-Level Authorization (BOLA) vulnerability, classified as CWE-639. An authenticated staff user can bypass multi-tenancy isolation and access detailed IP space reports of other tenants simply by specifying an unauthorized subnet identifier in the export request. This flaw leads to unauthorized data disclosure of internal network topologies, which could be leveraged to map target networks.
The root cause of this vulnerability lies in the implementation of the export_view method within openwisp_ipam/admin.py. The OpenWISP administrative classes inherit from MultitenantAdminMixin, which intercepts standard Django Admin query requests to restrict results according to the organization of the requesting user. While this mixin secures standard database queries returned by the get_queryset method, it does not automatically enforce constraints on custom-defined views unless explicitly invoked.
In the vulnerable implementation, the export_view method processes the subnet export request using a user-controlled parameter, subnet_id, extracted from the URL. Instead of querying the database through the filtered queryset provided by the administrative mixin, the code passes the subnet_id directly to the Subnet().export_csv() method. This direct database interaction bypasses the security context established by MultitenantAdminMixin.
By omitting the tenant-filtering layer, the endpoint permits an insecure direct object reference. Since Django handles model lookup inside the raw export_csv call without checking ownership boundaries, the application retrieves and outputs records for any valid UUID. This flaw allows a restricted user to bypass the logical partitions of the multi-tenant architecture and access data across the entire database.
The vulnerability is resolved by modifying how the target subnet instance is fetched in the export_view handler. Rather than delegating lookup entirely to the underlying export_csv method, the patched code retrieves the subnet object through get_object_or_404, forcing the query to evaluate within the context of the user's filtered queryset.
Below is the comparison between the vulnerable code path and the corrected implementation:
# Vulnerable Code Path
def export_view(self, request, subnet_id):
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename="ip_address.csv"'
writer = csv.writer(response)
# Direct model method execution bypasses get_queryset authorization checks
Subnet().export_csv(subnet_id, writer)
return response
# Patched Code Path
def export_view(self, request, subnet_id):
# Enforces authorization by scoping lookup within self.get_queryset(request)
subnet = get_object_or_404(self.get_queryset(request), pk=subnet_id)
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = 'attachment; filename="ip_address.csv"'
writer = csv.writer(response)
# Uses authorized object identifier
Subnet().export_csv(subnet.id, writer)
return responseBy querying self.get_queryset(request), the system restricts the search space to objects associated with the authenticated user's organization. If an attacker submits a subnet_id belonging to a foreign tenant, the get_queryset call will exclude the object, and get_object_or_404 will raise an HTTP 404 error, blocking further execution.
Here is the flow of the unauthorized request before and after the patch:
To exploit this vulnerability, an attacker must first obtain valid credentials for a staff account on the target OpenWISP instance. While this requires authenticated status, the attacker does not need high-level global administrative privileges. The attack complexity is low, as the exploit only requires sending an HTTP GET request to the vulnerable endpoint with the targeted subnet UUID.
The targeted URL follows the pattern /admin/ipam/subnet/<subnet_id>/export/. Because OpenWISP uses UUIDs for model identifiers, an attacker must obtain or predict the target subnet_id. In scenarios where UUIDs are exposed via logs, client-side metadata, or predictable generation patterns, an attacker can construct the payload and execute the request.
The official regression test demonstrates the vulnerability mechanics. An administrator associated only with org1 attempts to trigger the export view on subnet2 belonging to org2. Prior to the patch, this request returned an HTTP 200 OK status code along with the complete CSV data of the unauthorized subnet. Following the integration of the patch, the system correctly denies access and returns an HTTP 404 response.
The impact of this vulnerability is limited to unauthorized information disclosure, resulting in a CVSS v3.1 score of 7.1. An attacker can download detailed mappings of any subnet in the system, exposing the IP addresses, associated hostnames, mac addresses, and descriptions of internal network nodes. This structural data provides a blueprint of the organization's internal architecture.
No integrity or availability impact exists, as the vulnerable view is read-only and does not permit modification or deletion of database records. However, because OpenWISP is often used by network service providers to manage infrastructure across distinct corporate clients, the breakdown of multi-tenant boundaries represents a critical threat to data isolation agreements.
Furthermore, additional REST API endpoints may remain susceptible to similar validation gaps if they bypass the filtered queryset logic. Specifically, views such as ExportSubnetView.post() handling /api/v1/subnet/{S}/export/, AvailableIpView.get(), and RequestIPView.post() must be evaluated. If these API views resolve subnets through direct object queries rather than authorization-scoped querysets, similar BOLA exposures could still be exploited.
Remediation requires upgrading the openwisp-ipam package to version 1.2.1 or later, which implements the secure get_object_or_404 verification step. This update closes the direct object access vector across the Django Admin export interface.
If an immediate package upgrade is not feasible, a manual hotfix can be applied directly to the codebase. Organizations must locate the installed openwisp_ipam/admin.py file within their environment and modify the export_view method to enforce queryset scoping. Ensure the get_object_or_404 utility is imported from django.shortcuts before replacing the vulnerable lookup line.
For long-term defensive engineering, developers must avoid executing model operations directly on user-provided primary keys without first validating ownership. In multi-tenant systems, all database operations initiated from user-facing views must route through a security-enforcing interface layer, such as an authorized queryset manager or serialization validator, to prevent regression vulnerabilities.
| Product | Affected Versions | Fixed Version |
|---|---|---|
openwisp-ipam OpenWISP | < 1.2.1 | 1.2.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639 |
| Attack Vector | Network |
| CVSS Score | 7.1 (High) |
| Exploit Status | Proof-of-Concept |
| KEV Status | Not Listed |
| Impact | Information Disclosure |
A supply-chain compromise affecting the pantheon-agents PyPI package, where versions 0.6.1 and 0.6.2 were uploaded with malicious payloads that exfiltrate sensitive environment variables and credentials.
A high-severity path traversal vulnerability in Cloudreve's WebDAV component allows authenticated users with scoped WebDAV credentials to bypass directory containment limits and access unauthorized filesystem areas.
A DOM-based Cross-Site Scripting (XSS) vulnerability was identified in SunEditor before version 3.1.4. The Embed plugin programmatically recreated and mounted script elements from raw HTML embed code, permitting remote attackers to execute arbitrary JavaScript within a user's browser session.
SENAITE LIMS core framework (senaite.core) versions 2.0.0 through 2.6.0 contain a critical vulnerability chain that permits unauthenticated remote code execution. By combining a Missing Authorization flaw (CWE-862) in multiple JSON API endpoints with an Unsafe Evaluation flaw (CWE-95) during custom field deserialization, an attacker can execute arbitrary Python commands. This execution occurs under the privileges of the hosting Zope process, creating severe risk to laboratory systems, physical instrumentation databases, and host system integrity.
A Stored Cross-Site Scripting (XSS) vulnerability exists within the legacy presentation templates of the LibreNMS network monitoring system. Due to inadequate context-aware output encoding of operational data ingested via Simple Network Management Protocol (SNMP) polling, Border Gateway Protocol (BGP) notifications, and incoming Syslog messages, an administrative user viewing device dashboards can be targeted with arbitrary JavaScript execution.
CVE-2026-54614 is an unsafe reflection vulnerability in the MailPreview component of cakephp/debug_kit prior to versions 4.10.3 and 5.2.4. Unauthenticated or low-privileged remote attackers can exploit this vulnerability to dynamically resolve and instantiate arbitrary PHP classes within the Composer autoloader environment, leading to constructor and destructor execution.