# 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)](https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator?vector=AV:N/AC:L/PR:N/UI:R/S:C/C:N/I:H/A:N&version=3.1) | | 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`](https://codeberg.org/blenderdumbass/BDServer/src/commit/dc86854a261f61042868a5e73de5272a6f2799db/modules/Run.py#L341-L403): | 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`](https://codeberg.org/blenderdumbass/BDServer/src/commit/dc86854a261f61042868a5e73de5272a6f2799db/modules/Render.py#L1828): ```html
``` Without a `method` attribute, forms default to GET. Action buttons are implemented as `` links rather than form submissions. The [`Button()` helper](https://codeberg.org/blenderdumbass/BDServer/src/commit/dc86854a261f61042868a5e73de5272a6f2799db/modules/Render.py#L3249-L3278) generates anchor tags, so clicking "Log Out" or "Delete" triggers a GET request: ```html Log Out ``` 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: ```html ``` 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: ```html ``` ### Admin Plugin Manipulation If an administrator visits a malicious page, an attacker can manipulate server plugins: ```html ``` 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](https://www.rfc-editor.org/rfc/rfc9110.html#section-9.2.1): 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. ### Set Secure Cookie Attributes The session cookie currently lacks security attributes ([`Render.py:80`](https://codeberg.org/blenderdumbass/BDServer/src/commit/dc86854a261f61042868a5e73de5272a6f2799db/modules/Render.py#L80)). 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](https://codeberg.org/blenderdumbass/BDServer/src/commit/dc86854a261f61042868a5e73de5272a6f2799db) 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.