This repository has been archived on 2026-04-22. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2026-01-21 13:12:04 -05:00
..
2026-01-21 13:12:04 -05:00
2026-01-21 13:12:04 -05:00

Cross-Site Request Forgery (CSRF)

Summary

BDServer lacks CSRF protection and uses GET requests for state-changing operations. This combination allows attackers to perform unauthorized actions via image tags, links, or email content without requiring JavaScript or form submissions. Additional vulnerable endpoints likely exist given the prevalence of this pattern throughout the codebase.

Vulnerability Details

Property Value
Type Cross-Site Request Forgery (CSRF) via HTTP Method Misuse
CVSS 7.4 (High)
CWE CWE-352 (Cross-Site Request Forgery), CWE-749 (Exposed Dangerous Method)

Root Cause

BDServer uses GET requests for operations that modify server state. This violates HTTP semantics where GET should be idempotent and only POST/PUT/DELETE should modify data. Combined with no CSRF protection (no tokens, no SameSite cookies, no origin validation), this allows attackers to trigger state changes via simple image tags or links.

The vulnerable endpoints are handled in do_GET:

Endpoint Action
/comment Create or edit comments
/delete_comment Delete comments
/update_account Modify user profile
/grant_publication_rights Grant or revoke permissions
/create_invite Generate invite codes
/cancel_invite Delete invite codes
/log_out Terminate sessions
/sign_petition Sign petitions
/read_notification Delete notifications
/do_install_plugin/ Install plugins and restart server
/do_delete_plugin/ Delete plugins

Forms in the application don't specify method="POST", so they default to GET. For example, from Render.py:1828:

<form action="update_account">

Without a method attribute, forms default to GET.

Action buttons are implemented as <a> links rather than form submissions. The Button() helper generates anchor tags, so clicking "Log Out" or "Delete" triggers a GET request:

<a class="button" href="/log_out?cookie=...">Log Out</a>

Traditional CSRF requires JavaScript to auto-submit forms. GET-based CSRF is more dangerous because it works without JavaScript, requires no user interaction beyond viewing a page, works in HTML emails, and bypasses most Content Security Policies since browsers don't block image loads.

Reproducing the Vulnerability

These examples assume a local test server running on localhost:8080. The attack works by embedding image tags that trigger GET requests when a logged-in user views the page.

Profile Modification

An attacker can modify a victim's profile by having them view a page containing:

<img src="http://localhost:8080/update_account?bio=Account%20Compromised&website=https://evil.com" style="display:none" />

When a logged-in user views this page, their profile bio and website are silently changed. The image tag triggers an automatic GET request with the victim's session cookie.

Comment Deletion

Multiple comments can be deleted by chaining image tags:

<img src="http://localhost:8080/delete_comment?url=/articles/Welcome_To_BDServer&number=0" />
<img src="http://localhost:8080/delete_comment?url=/articles/Welcome_To_BDServer&number=1" />

Admin Plugin Manipulation

If an administrator visits a malicious page, an attacker can manipulate server plugins:

<img src="http://localhost:8080/do_delete_plugin/plugin_hash" />
<img src="http://localhost:8080/do_install_plugin/malicious_plugin_hash" />

This can delete security plugins and install malicious ones, triggering a server restart.

Proof of Concept

  1. Log into BDServer at http://localhost:8080 and note the current profile settings
  2. Open poc.html in the same browser
  3. Return to BDServer and check the profile: the bio and website fields have been changed

The PoC embeds an invisible image tag that triggers a GET request to /update_account. The browser sends the session cookie with the request, authenticating the action.

Remediation

Use POST for State-Changing Operations

RFC 9110 defines GET as a "safe" method: it should only retrieve data, never modify it. Browsers rely on this assumption. They prefetch links, cache responses, allow embedding in image tags, and let users bookmark URLs. These behaviors are fine for reading data but cause problems when GET requests delete comments or modify profiles.

POST exists specifically for operations that change state. Browsers handle POST differently: they don't prefetch it, don't cache it, and can't trigger it from an image tag. Switching to POST eliminates the attack vectors described in this report.

Move all state-modifying endpoints from do_GET to do_POST in Run.py. Update forms to specify method="POST" and replace link-based buttons with form submissions.

Implement CSRF Tokens

CSRF tokens provide defense in depth beyond using POST. The server generates a random token for each session and embeds it in forms as a hidden field. When the form is submitted, the server verifies the token matches the session. An attacker cannot forge requests without first obtaining the victim's token, which requires a separate vulnerability like XSS.

The session cookie currently lacks security attributes (Render.py:80). Setting SameSite=Strict prevents browsers from sending cookies with cross-site requests, providing defense in depth against CSRF. Modern browsers default to SameSite=Lax which provides some protection, but this should not be relied upon.

Disclaimer

This assessment was performed on a best-effort basis against BDServer commit dc86854 and reflects the state of the software at the time of testing. The findings and remediations are provided for informational purposes and should be independently validated before implementation. This report does not guarantee all vulnerabilities have been identified, nor does it guarantee the suggested fixes will be effective in all environments.