Security vulnerabilities

  • Status Closed
  • Assigned To
    cbay
  • Private
Attached to Project: Security vulnerabilities
Opened by vdpresearch - 27.10.2026
Last edited by cbay - 28.10.2026

FS#537 - Edge POST filter bypass: dispatcher honours "action" on /task/* (profile e-mail/name writable)

SUMMARY


The edge filter on security.alwaysdata.com only allows POST to /task/* and
/index.php?do=authenticate. Flyspray dispatches on the "action" field and ignores
the path, so POSTing the profile-edit form to /task/<any id> executes the action.

POST /myprofile   -> 403 (blocked by the filter)
POST /task/536    -> 303, change stored (same body, action=myprofile.edituser)

Reproduced on my own account (uid 358) on 2026-10-27, all changes reverted:

real_name  -> "Ali Abbas ROUTE" (stored)  -> reverted
email      -> admin@bugbountyscam.com (stored) -> reverted

STEPS


1. GET https://security.alwaysdata.com/myprofile as a logged-in user; take csrftoken.
2. POST the profile form to /myprofile ⇒ HTTP/2 403 Forbidden.
3. POST the identical multipart body to /task/<any task id>

 with action=myprofile.edituser        => HTTP/2 303 See Other,
 Location: https://security.alwaysdata.com/myprofile

4. Reload /myprofile: real_name and email_address contain the submitted values.

ROOT CAUSE


Filter decision is path-prefix based; application handler selection is based on
the "action" parameter. No component validates that the two agree.

SCOPE OF THE BYPASS


- Every other blocked POST path tested (/index.php, /proj1, /newtask/proj1,

/myprofile) still returns 403; only /task/* reaches the dispatcher.

- Unauthenticated requests have no effect (session check holds, login page).
- user_id=1 / user_id=99999 in the body are ignored - handler always targets the

session user. Group fields (group_in, old_global_id) ignored, server-side only.

So this bypasses the transport filter, not the per-action authorisation.

IMPACT


Any POST route the edge rule is meant to protect can be reached by relabelling
the path as /task/<id>. Persistent writes were demonstrated (profile e-mail and
real name); changing the profile e-mail also changes where account notifications
and recovery messages are delivered.

REMEDIATION


- Enforce the POST allow-list on the dispatched action, not the URL path.
- Reject requests whose "action" does not belong to the route they were sent to.
- Make the dispatcher refuse action processing on controllers that do not

declare that action.

Timestamp: 2026-10-27 18:2x UTC. Testing was manual, own account only, low rate.

Closed by  cbay
28.10.2026 13:55
Reason for closing:  Invalid

Correction to the scope note in the description (my error, measured after filing):

POST /newtask/proj1 is NOT blocked - it returns 303 and is how this task was
submitted. The blocked set I actually observed is:

POST /myprofile        -> 403
POST /index.php        -> 403
POST /proj1            -> 403
POST /newtask/proj1    -> 303 (allowed)
POST /task/<id>        -> allowed, dispatches on "action"

So the edge filter already admits the new-task route; the bypass matters for the
routes it does block, where the dispatcher still executes the action from the body.
The demonstrated case remains: profile real_name and email_address are writable
through POST /task/<id> with action=myprofile.edituser, while POST /myprofile is
refused with 403. Everything in the reproduction section is unchanged.

Escalation bounds, measured after the report - posted so the severity can be pinned down and this does not get closed as an over-claim.

1) The dispatcher really does accept arbitrary action values on /task/<id>:

 action=myprofile.edituser -> 303 /myprofile
 action=admin.edituser     -> 303 /user/
 action=admin.newuser / admin.useredit / admin.editgroup / admin.groups / pm.send / user.edituser / details.task -> 200 (handler reached, re-rendered)

2) But per-action authorisation still holds, so this is NOT privilege escalation.

 Control: GET /user/1 shows 'Real Name Cyril, Global Group Admin'.
 Attack: POST /task/536 with action=admin.edituser, user_id=1, real_name=VDPCANARY77, email_address=canary77@example.org -> 303 /user/1.
 Re-read GET /user/1 -> 'Real Name Cyril, Global Group Admin' - UNCHANGED. No write.
 user_id=358 (self) and user_id=99999 behave identically (303, no cross-account effect).
 GET /index.php?do=admin as this user -> 302 to / (denied).

3) So the defect is confined to the transport layer: it defeats the edge POST filter, and the write that persists is on the caller's own profile (myprofile.edituser), which the filter is meant to make unreachable by POST. I am not claiming account takeover or admin access - please treat the Medium rating as the ceiling for this one.

4) Re-confirmed today: POST /myprofile → 403; identical body to POST /task/536 → 303; values written, then reverted to the originals (real_name 'Ali Abbas', email_address delegate4@bugbountyscam.com). Own account only.

Admin
cbay commented on 28.10.2026 08:21

Hello,

If you can only modify details on your own account, then it's not a vulnerability.

Kind regards,
Cyril

yes

i only can change detail on my own account, but the simple changes shows 403 ,

if its not it means you will not fix it rit ?

Admin
cbay commented on 28.10.2026 13:54

Yes.

Loading...

Available keyboard shortcuts

Tasklist

Task Details

Task Editing