Security AdvisoryGHSA-9v52-vhvw-4w5cSEVERITY: Moderate

Cross-meeting presentation upload via unbound upload token (IDOR)

TARGET REPOSITORYbigbluebutton / bigbluebutton
PATCHED VERSIONS3.0.37, 4.0.0-rc.2
CWE CLASSIFICATION:CWE-639: Insecure Direct Object Reference · CWE-862: Missing Authorization
Sep 10, 2026•6 min read•Madhan Alagarsamy
Official GitHub Advisory
Cross-meeting presentation upload via unbound upload token (IDOR)

Executive Summary

During security research into BigBlueButton's presentation processing pipeline, an authorization bypass and IDOR vulnerability was identified in the presentation upload handler. The upload token generated for authenticated presenters in one meeting could be maliciously leveraged across unrelated active meeting instances without proper tenant or meeting boundaries verification.

Coordinated Disclosure Timeline

August 2026:

Vulnerability identified during routine source audit & API testing.

August 2026:

Comprehensive PoC formulated and reported through GitHub Private Vulnerability Reporting.

Late August 2026:

BigBlueButton security maintainers validated the report and worked on token-to-meeting binding.

September 10, 2026:

Official patch released in versions 3.0.37 and 4.0.0-rc.2; advisory GHSA-9v52-vhvw-4w5c published.

01.Architecture & Token Mechanism

In BigBlueButton, moderators or presenters can upload slide presentations (PDFs, PPTXs, images) to display in a virtual room. When a user requests an upload, the application server allocates an upload token. This token is designed to authorize the subsequent multi-part upload POST request sent to the presentation conversion worker.

Sample upload initiation endpoint response
json
{
  "status": "SUCCESS",
  "uploadToken": "tok_9f81a7b8e4c2901a",
  "uploadEndpoint": "/bigbluebutton/presentation/upload"
}

02.The Flaw: Missing Meeting Session Association

The verification logic on the receiving upload endpoint validated the cryptographic integrity and expiration timestamp of the uploadToken, but failed to assert that the associated meetingId matched the target meeting room identifier in the upload payload. Consequently, a user with presenter rights in Meeting Room A could inject arbitrary presentations into Meeting Room B as long as they possessed or could obtain the destination meeting ID.

Cross-meeting injection request
http
POST /bigbluebutton/presentation/upload HTTP/1.1
Host: target-conference.domain
Authorization: Bearer tok_9f81a7b8e4c2901a
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryX

------WebKitFormBoundaryX
Content-Disposition: form-data; name="conference"; meetingId="meeting-room-target-b"
...
[Malicious / Unsolicited Presentation Slide Data]
------WebKitFormBoundaryX--

Reproduction & Proof of Concept (PoC)

The proof of concept demonstrated cross-tenant meeting pollution without needing moderator credentials in the target session.

  1. Authenticate into an attacker-controlled meeting session (Room A) with presenter role.
  2. Request a presentation upload token from the server.
  3. Obtain or enumerate the identifier of an active target conference (Room B).
  4. Submit the multi-part presentation upload referencing Room B while utilizing Room A's upload token.
  5. Verify that Room B automatically renders and switches to the uploaded presentation.

Impact & Blast Radius

An attacker with presenter privileges in any meeting instance on the server could deface, hijack, or display unauthorized presentations in concurrent private meetings, causing denial of service, phishing exposure, or disruption of confidential conferences.

Remediation & Mitigation

Upgrade BigBlueButton to versions 3.0.37, 4.0.0-rc.2, or later. The patch enforces strict cryptographic and database-level binding between the generated upload token, the originating user ID, and the explicit meeting session ID upon upload validation.
Validation check verifying upload token association with target conference ID.
Conceptual patch diff
diff
@@ -42,6 +42,10 @@ def validate_presentation_upload(token, target_meeting_id):
     token_data = decrypt_upload_token(token)
     if token_data.is_expired():
         raise AuthorizationError("Token expired")
+
+    # Enforce meeting scope validation
+    if token_data.meeting_id != target_meeting_id:
+        raise SecurityViolation("Token does not belong to target meeting")
 
     return True

References & Documentation

#IDOR#Access Control#CWE-639#CWE-862#BigBlueButton#Disclosure